【技術的なお話】色移りとBREAK構文【stable diffusion】 (Pixiv Fanbox)
Content
stable diffusion(以下SD)とかautomatic web ui(以下UI)とかの技術的なお話。
気が向いたときだけ書きます。
AIでイラストを作っていると、「色移り」という現象が起きます。
「yellew eyes」と入れただけなのに、ヘアリボンが黄色に染まる、といった現象。
分析している方の話によると、どうやら原因は、トークンのエンコード時に起きているらしい。と、突然用語が入るので少し説明しますが、詳しく理解しているわけではなく、自分なりの解釈なので間違ってても許してヒヤシンス。
トークン:SDで入力する単語、「1 gilr」とか「silver hair」とか。
プロンプト:75個のトークンの一塊
エンコード:あるデータを別のデータに変換すること。たぶん。
エンベディング:プロンプトをSDが扱えるようにしたデータ
そもそものところ、SDは一度に75個のトークンまでしか扱えないように設計されているそうです。それを超えると、本来は76個目以降は切り捨てられるようになっている。つまり、76個目に「silver hair」と入力されても、SDはそれを無視して画像生成をする。
あれ、でも、普通に使うとトークンの数はそれを越えているはず。しかも反映もされている。
なぜそうなるかというと、UI側で工夫が行われているらしい。SDは確かに75トークンまでしか扱わないのだが、トークンが75個を超えた場合、UIが自動でプロンプトを分割して、複数のエンベディングを作り、エンベディング同士を合成することで、最終的に全部のトークンを反映させるようにしてくれている。
別の言い方をすると、
・トークン(呪文)の段階では、75個以上は同時に扱えない
→75個以下のトークン(呪文)から、「システム的に処理された後のデータ」を掛け合わせることはできる。
という仕組みらしい。
もっと雑な言い方を試みる。
「玉ねぎ、にんじん、カレー粉、etc...」の75個の材料と、それに加えて76個目に「うどん」を加えようとすると、SDは本来、「うどん」の存在を無視してカレーだけ作ってしまう。
なので、「玉ねぎ、にんじん、カレー粉、etc...」が「カレー」になった後で、「うどん」と合成するようにSDに指示を送ると、「カレーうどん」になる(ことがある)。
しかし、このカレーうどん法(そんな呼び方はしませんが)、万能かといえばそうでもない。
一つのプロンプト(=75個のトークン)内で「カレー」と「うどん」が同時に存在している状態と、別のプロンプト(エンベディング)で作った「カレー」と「うどん」を合成する場合では、生成される画像の傾向に違いが生じます。
同一プロンプトの場合は、トークン同士が「混ざりやすい」。あくまでカレーうどんの例を使うならば、「カレーとうどんが一つのどんぶりに入る」傾向がある。
一方で、別のエンベディングを合成した場合は「混ざりにくい」。つまり、「カレーとうどんが別の皿に入っている」状態になりやすい。というか、実際には「カレーかうどん」になりやすい。
イメージでいうと、
同一プロンプト:A and B(カレーandうどん)
別のエンベディング:A with B(カレーwithうどん)
要するに、「別々のエンベディングの要素は分離されやすい」。
先述のように、SDは75以上のトークンを同時に扱えないので、UIは76個~150個なら二つのエンベディングを、151~225個なら三つのエンベディングを、自動で作って合成してくれる。
で、この分割を任意に行うのが「BREAK」という指示。ここで区切って、別のエンベディングを作ってね、とUIにお願いするための呪文。
エンベディングを強制で分割するBREAKは、メリットもデメリットもある。
メリットとしては、
色移りの対策としては、これが有効に使えることがある。
例えば、「1 girl,silver hair,BREAK yellow eyes, BREAK green ribbon」のようにすると、それぞれの要素を混ざりにくい状態で合成してくれるために、リボンが黄色くなったりしづらくなる。
デメリットとしては、
要素が混ざらないので狙ったようにいかない場面が出る。
実験した例を載せますが、R18な内容なので注意。
ざっくりこんな感じのプロンプトを考える。(実験したのはもっと長いプロンプト)
①1 girl,nsfw,nude,naked,doggy style,1 boy,
②1 girl,nsfw,nude,naked,doggy style,BREAK 1 boy,
③1 girl,BREAK nsfw,nude,naked,doggy style,BREAK 1 boy,
どんな場面かは頭の中でのSDくんが描いてくれると思うので説明しませんが、完成図はなんとなくわかるはず。
シード次第では全部上手く行くことも、全部失敗することもありますが、傾向として、①が最も狙ったものになりやすく、③がもっとも乖離しやすい。
③のようにプロンプトが分割されると、トークン同士を結び付ける必要がないので、画面上のどこかに「1 girl」「nsfw...」「1boy」の要素があればいい、という解釈になるのでしょう。カレーandうどんか、カレーwithうどんかの違い。色についてが顕著なので目立ちますが、おそらく本質的には、トークン同士の関係(干渉)の度合いの問題なのでしょう。
色移りしないから便利だー、と思ってBREAK構文を使うと、意外な副作用がある、というお話でした。