見出し画像

Stable Diffusion のネガティブプロンプトとは何か?

Stable Diffusionにはネガティブプロンプト(negative prompt)という謎の呪文を入れることができるのですが、これは一体どういう効果があるのか、ということを解明したいというのが、この記事の狙いです。

参考)他のStable Diffusionについての記事

ネガティブプロンプトの例

具体的な話をする前に、まず、下の2つのツイートを見てください。

どうしてこういう効果が得られるのかは、ネガティブプロンプトがどのように画像生成プロセスで使われているかを知る必要があります。

画像生成プロセスの概略

その前に、そもそもStable Diffusionの画像生成はどのような手順で行われているのでしょうか?

図1は、非常に単純化したStable Diffusionの画像生成プロセスの模式図です。

図1
  1. プロンプトを、テキストエンコーダーがトークンに分割して、各トークンをテキストエンベッディングと呼ばれる数値ベクトルに変換する。この数値ベクトルは、トークンの持つ意味を数値的に表現したものである。

  2. 入力として与えられたノイズ画像を、変分オートエンコーダーが潜在変数と呼ばれる数値ベクトルに変換する。この数値ベクトルは、画像の特徴を示す要素を数値的に表現したものである。

  3. 画像の潜在変数を、U-Netで解像度を変化させながら、プロンプトの意味を表すテキストエンベッディングを用いて、潜在変数を更新する。これにより、潜在変数の示す特徴が、プロンプトの意味に近づく。

  4. 更新された潜在変数を、変分オートエンコーダーで出力画像へと変換する。出力画像は入力として与えられたノイズ画像よりも、プロンプトの意味に沿った内容へと更新されている。

図1はプロンプトのみを用いた画像生成プロセスですが、実際にはここにネガティブプロンプトが加わることになります。

図2

図2は、ネガティブプロンプトを含めた画像生成プロセスの模式図です。図1で作られた更新後の潜在変数を、プロンプトとネガティブプロンプトの両方で計算し、その差にCFGスケールを掛けたものを、ネガティブプロンプトから生成した潜在変数に加えて、最終的な潜在変数を生成します。

CFGスケールはStable Diffusionの画像生成の際に与えられる設定値で、通常は7~11とされています。また、1より小さい値は無視されます。

この操作により、プロンプトとネガティブプロンプトの間の差が、より強調された画像が生成されるようになるのです。この仕組みは、CFG(= Classifier Free Guidance、分類器なし誘導)と名付けられています。

ネガティブプロンプトの使い方

ここから分かることは、CFGにおいて意味があるのは、プロンプトとネガティブプロンプトの差の部分だけだ、ということです。このことを念頭に置くと、ネガティブプロンプトをより効果的に使うことができると考えられます。

例1 "1girl, 1boy"

プロンプト: "1girl, 1boy"
ネガティブプロンプト: "1girl"

"1girl, 1boy" というプロンプトでは、特にanything-v3.0を使っている時に、人物が少女1人や、少年が描かれていても顔や体が画像の外に半分出ているような画像が生成されることがあるようです。

この場合、ネガティブプロンプトに "1girl" と指定すると、ネガティブ画像として「少女1人」の画像が生成され、差分が「少年」となるため、少年の存在がより強調されるようになり、「少年と少女」の両方が描かれた画像が生成されやすくなります。

プロンプト: "1girl, 1boy"
ネガティブプロンプト: なし
プロンプト: "1girl, 1boy"
ネガティブプロンプト: "1girl"

例2 "1girl, red hair, blue eye"

プロンプト: "1girl, red hair, blue eye"
ネガティブプロンプト: "1girl, blue hair, red eye"

プロンプトで色を指定した時に、指定しない要素にまで色が混ざるという問題が、Stable Diffusionを使っているとよく発生します。そして、プロンプトを書き換えてもなかなか直らない厄介な問題となりがちです。

この場合、問題となっている色混ざりをネガティブプロンプトに指定することで、色混ざりがより少ない画像が生成されやすくなります。例では "red hair, blue eye" の赤と青が混ざることのないよう、"blue hair, red eye" をネガティブプロンプトに指定しています。

この際、問題を起こしていない要素をネガティブプロンプトに含めることで、その要素については強調されないようにすることもできます。例では "1girl" は無関係なので、ネガティブプロンプトにもそのまま含めました。が、これは必須要素ではありません。

プロンプト: "1girl, red hair, blue eye"
ネガティブプロンプト: なし
プロンプト: "1girl, red hair, blue eye"
ネガティブプロンプト: "1girl, blue hair, red eye"

この記事が気に入ったらサポートをしてみませんか?