備忘録:Stable diffusion 試してみたいこと
単なる思い付きなので、やるかどうかわかりません。
実装してみたいという方は是非お願いします。
既存の model, lora 等資産がある程度使えるという制限つきにしておきます。
Negative prompt 側に流れてくるデータを使ってみる
SlothfulAttention開発中に、batch = 1 で生成しているのに、2枚分のデータが流れてくるのは何だろうと思ってました。
cfg周りの説明読み直したら、Positive prompt と Negative prompt の条件で u-net を通して、差分をcfgで増幅したのが、 1stepで除去するノイズになる・・・という感じらしいです。
で、これらが同時に流れてくるので、u-netの中間でPositive側とNegative側を比較するとかそんな事もできそうなんですよね。
Self-attention の K を混ぜてみる
単に混ぜるだけだとダメそうですが、とりあえず混ぜたら何が起ころかはちょっと試してみたいところです。
混ぜた分のKに対応するVを細工すれば、画像コントロールできそうな気がしてます。
ネガティブ側をなるべく計算しない
cfg = 1 の時は(Positive側のみu-net通すので)計算量がほぼ半分まで落ちるというのは魅力的ですね。
Cross-attention で Negative側の V をペナルティとして使えるなら、 基本 Positive側のみ計算すればよいので速くなる……はず。
In最初のブロックで Negative側を捨てて、途中のCross-attentionでNegative promptの影響分を何とかする。 Out最後のブロックでNegative側にゼロTensorを設定するとか?
すでに実装されてそうな気もするので、まずは検索してからですね……
HyperTile + SlothfulAttention
HyperTile はSelf-attentionの Q を分割することで、 類似度計算の計算量を削減しているみたいなんですが、 この手法でQを分割する場合は それぞれ別の K, V を与えることもできそうです。 (テンソルのサイズは揃える必要がありますが)
分割後のQをローカル、分割前のQをグローバルとして、ローカル・グローバルに異なるプーリングを適用して結合すると比率が変わるので、 近傍を重視するとかができそうな気がしてます。
(LLMで使われている Sparse-attention とかに近い感じになりそうですね)
SlothfulAttentionでは手や顔などが崩れやすくなってしまうため、対策に使えるかもしれません。
この場合、Slothful(怠惰)じゃなくて Near-sighted(近視)とかの名称になりますかね。
また、タイル境界を変化させるために HyperTileでは分割数を変動させるような作りになってましたが、 Swin-Transformer のように、シフトでもいけるような気がしてます。 エッジ同士が同タイルになるので、影響が出てしまうかもしれませんが……
Depth, Normal を生成するmodel
HyperHuman 凄そうと思ったけど、非公開だし既存のSDモデルとか使えなそう・・・
劣化版になりそうですけど、Controlnetなどで利用できる Depth とか Normal を生成するmodelで下絵を描いて、それをガイドとして描画させるとかなら、今使っているSDモデルとかが活用できそう。
In, Middleブロックの重みは流用、Out ブロックのトレーニングから始めれば 多少はトレーニングが楽になる?
画像からDepth, Normal推定させた場合は 教師画像の品質が問題かも。 3Dモデルがあるなら、レンダリングで出せそうな気がするけど・・・
SD1.5ベースの蒸留モデル tiny-sd とかをベースに実験してみてもよいかも?
Attentionのチャンネル数を絞る
アテンションの q, k, v に同じチャンネル数を与えているけど、q, k の類似度計算に全チャンネル分必要?という疑問から。
to_q, to_k のLinearの後に次元を減らすような同じ行列かけてあげれば、Weightそのままでいけそうな気がしてます。
一律で削減だとひどい結果になりそうですが、Headごとに学習してあげればなんとかなる?
……これもちょっと大変そうですね。労力に見合わなそう
Self-attention 前に スパースコーディング
最近あまり聞かなくなった気がするスパースモデリングですけど、まだ使えると考えてます。
学習済みの辞書(基底ベクトル群)を準備しておいて、基底ベクトルに Self-attentionを適用してキャッシュ。 Attentionブロックへの基底ベクトルに分解して、キャッシュ済みの値で復元。
もうちょっと進めて、スキップコネクション含めて Cross-attentionまで一気に計算してキャッシュしておくとよいかも?
(同一Promptなら使いまわせるはず)
ただ、スパース表現に変換する際に基底ベクトルとの類似度計算する必要があるので、辞書サイズを絞らないとうまくいかなそう。
というか、スパースである必要もないので、辞書の疑似逆行列で分解してしまえば良いだけの話かもしれないです。
同一辞書で生成すると一貫性がありそうな気もするので、何かしらの使い方はあるかもしれないです。