stable diffusionのmergeや階層についてのメモ
Added 2023-04-25 15:48:49 +0000 UTCモデルのマージを試してみて、わかったことのまとめ。
〇前提
ネットの情報はかなり錯そうしており、断片化していて本質的でない議論も多い。
ここに記載する情報が正しいかは不明。ただ、以下にまとめる推測とmergeやloraの挙動に一定の整合性が見られるので、仮説として一定の機能はすると思われる。
特に重要に思われることとして、
・日常言語的に理解すべきでない
・細分化して考えるよりも、抽象的に捉えるほうが実態に合致する
→おそらく「SDのU-netが25個のレイヤー(層)で構成されている」といった表現から、少なくない人が「U-netのレイヤー」を「フォトショなどのレイヤー」のようにイメージしてしまっているのではないか。というか、それに基づいて「顔層」のような表現がされていたため、自分も最初はそう勘違いした。しかし、実際には機械学習のレイヤーは、当然ながらペイントツールのレイヤーとは全く違うものである様子。
これはstep2-4くらいの絵を生成してみるとわかるが、初期に近いstepは「区切り」と「色」と「グラデーション」しかない。ここに「顔」や「アクセサリー」のレイヤーなど存在しない。
〇階層の役割について
wikiやその他の記事では「どの階層がどのような役割を果たしているか」に言及されているが、これはあまり本質を射ていない様子。
手掛かりになったのが以下の二つの記事。
上がstable diffusionのmergeの解説。
下がU-net構造の解説。
U-netの仕組みは画像認識系のAIで一般的に使われている構造らしいので、U-netの解説がそのままSDの階層に当てはまるかは不明。ただ、下の記事のU-netの構造に基づくと、上の記事の内容の裏付けになっている。
自分がどうにか理解できた(つもりの)部分をまとめると、
・画像分析を直線構造のネットワークで処理しようとすると、一部の情報(位置情報)が失われる
→U-net構造により、対応する階層ごとに一部の情報をバイパスすることで解決している(SDでも同じ構造なら、IN00→OUT11やIN01→OUT10の対応関係があるはず)。
・SDでは浅層で細部を、深層で大まかなものを処理している
・IN層は画面の区切りを作り、OUT層ではその区切りに基づいて色をつける(おそらくAI的には輪郭線も単なる色の一つ)
実際、モデルAのin層に丸ごとモデルBをmergeしても、モデルの絵柄はそれほど変化しない。一方で、モデルAのout層にモデルBを丸ごとmergeすると、絵柄はほとんどモデルBになる。
つまり、inで画面の区切りを作り、outでその区切りに基づいて絵にしていると推測される。
ただし、その区切りの中で何を描くかはout側、もしくはstepを繰り返す中で相互的に行われていると思われる(outの浅層だけ違うモデルでも、構図に変化が起こることがある)。
また、構図決定に影響するのはinのみではなく、clipの影響も強い、というか、clipのが強い模様(厳密にはおそらく強弱ではなく役割の違い)。
〇層の役割に関するざっくりまとめ
IN浅層→細部の構図
IN中層→浅層と深層の中間
IN深層→大まかな構図
M→重要っぽいがよくわからん
OUT深層→大まかな描き方
OUT中層→パーツの描き方
OUT浅層→輪郭やグラデーションの描き方
という感じで区切るとイメージに近そうではあるが、厳密ではない。
〇顔層などの表現について
先に少し書いたが、顔層などの層の役割を固定化するのはおそらく誤解。
上記の推測が正しければ、浅層は細かい描写、深層は大まかな描写に影響しているが、これは人間的な認識ではなく、あくまで数量的な話。例えば、cowboy shotの図柄では、人物の全体像は大まかな構図なので深層で決められる。このとき、「顔」はそれほど大きくならないため、主に中層が顔の描写を担うことになる。一方で、顔のアップの構図の場合は、顔の輪郭を深層、顔のパーツを中層、顔の細部を浅層が担当する、ということになるはず。
つまり、「この層の影響が顔に現れる」というのは、画面内に同じような比率で顔が存在する場合には当てはまるが、常に当てはまることではない。
ただ、浅層(out8-11)は構図を問わず、いわゆる「塗り」の要素が強い模様。
〇mergeの試行錯誤で観察された問題と考察
・inとoutの対応がずれると、絵に違和感が出る
定量的な観測はしていないが、inとoutを完全に別のモデルにすると、絵に違和感が出やすい印象がある。奇形になりやすくなったり、人物と背景との遠近感がおかしくなったり、など。
描画に関するin側の影響が人間的にはあまり感じないからといって、軽視はするべきではなさそう。
おそらく、近いモデル同士(例えばAOMの同じナンバリング同士)なら起きないと思われるが(試してない)、リアル系とアニメ系をmergeする場合には、考慮しておいたほうが良さそう。
これは、上記の通り、U-netの構造を考えれば奇妙なことではなさそう。つまり、inからoutに情報をバイパスしているわけで、モデルAのinからモデルBのoutにパスしてるなら、そこで齟齬が起こるのはむしろ当然のはず。
そのため、これをずらすことによる特殊な効果を期待するのでなければ、inとoutのmerge比率は同量にしておくほうが良さそう。
・base/alphaは0か1(ベースモデルに合わせる)のが良いのではないか
特に検証したわけではないが、主にテキストエンコーダー部分のmergeのようなので、モデルの認識できる語彙を調整したいなどの理由がなければ、半端に混ぜるよりも触らないほうが良さそうに思われる。
・add difference
効果はあるが、未知の要素が多すぎてあまり使いたくないもの。
AOM2hardの成り立ちが、この機能を使ってNAIのnsfwやgapeのエロ部分を加算したものらしい。ただ、AOM2のsfwとhardを比較してみると、実際のところ、hardだから一概にエロい構図になる、というわけでもない。
同じプロンプト、seedなら、sfw版でも実は構図はそれほど変わらない。違いとしては、おそらくhardのほうが性器が描かれている面積が増えたり、男の身体が出やすくなったりする。
ただ、代わりに性器がでかすぎたり、ウェストあたりの構造がほんのり肥大化するような印象がある。なので、add differenceが「加算処理」さているのが、「エロくなる」のではなく「エロ要素が面積的に大きくなる」ように機能しているのかもしれない。
ただ、結局はエロ特化モデルでなくとも(少なくともノーマルなものなら)、プロンプトやloraでどうにかなるので、AOM2hardのような目的で新たにmergeする意味があるかは疑問。
・ベタ塗りにすると、やや奇形率が上がる
これは低stepでノイズが残ってる状態をみるとわかるが、ベタ塗り(out8-11あたりをアニメ系モデルにする)にすると、陰影がつぶれるせいでAIが混乱するのではないかと思われる。
あくまで確率的なものなので、それを承知でベタ塗りにするのも手だが、メリットデメリットはみて調整してもいいかもしれない。
〇どのようにmergeするのが良さそうか
結局は何のモデルのどの要素をどうしたいかによるので、統一的な解はなさそう。
ただ、大まかな方針として、
1,ベースモデルに対して何を変更したいかを明確にする
2,その変更したい要素を持つモデルを用意する
3,変更したい要素が主にどの層の影響なのかを調べる(mergeして生成してみるを繰り返すしかない)
4,目的の層が限定できたら、その層を中心に周辺の層の影響を調べる
このとき、パラメーターの調整のコツとして、
・対応するinとoutは基本的に配合比を揃える
・主に変更したい層の上下の層も段階的に調整する
→一例として、out7まではweight0,out8からはweight1、のように極端な構成をすると、輪郭線がかなり強調される場合があった(モデルの組み合わせによるはず)。そのような効果を狙う場合はありかもしれないが、自然なmergeを目指すなら上下の層の役割と馴染むように、主に変更したい層を80→上下の層を60、などのように勾配をつけたほうがよさそう。
基本的な方針としては、AOM2の配合方針がよいのかも。リアル系モデルが深層、アニメ系モデルが浅層に段階的に調整されているらしい。
merge block weightedのプリセットでいえば、gradvかgradaを使えば、「モデルAの構造でモデルBの絵柄」かその逆になるので、これを中心にパラメータ調整をしていけば、このタイプのmergeの方針が見えやすいはず。