「シロクマ効果」だと思っていました

ネガティブプロンプトに glasses と書いたのに眼鏡が消えない。この現象を調べていたとき、最初に思いついたのは心理学でいう「シロクマ効果」でした。「シロクマのことを考えるな」と言われると逆に考えてしまう、あの有名な話です。

ネガティブプロンプトに「眼鏡」と書くことで、モデルに眼鏡を意識させてしまっているのではないか。そう仮説を立てて検証を進めていました。

ところが、再検証してみると話はもっと単純でした。シロクマ効果とは関係なく、このモデルにとって眼鏡は「かけるか、かけないか」の二択しかないということが分かりました。


検証:眼鏡はどう書いても顔にかかる

Illustrious系モデルでキャラクターを生成していたとき、意図しない眼鏡が100%出現する問題に遭遇しました。ここから、いくつかのパターンで検証を行っています。

パターン1:コメントアウトしたのに消えない

ポジティブプロンプトに含まれていた silver-rimmed glasses をコメントアウトしました。

#silver-rimmed glasses

しかし、プロンプトの別の箇所にも眼鏡に関する記述が残っていたため、眼鏡は消えませんでした。コメントアウトだけでは不十分で、プロンプト全体を確認する必要があります。

パターン2:手に持った眼鏡

眼鏡を顔ではなく手に持たせる、という構図を試しました。

holding silver-rimmed glasses in hand

結果、キャラクターは眼鏡を手に持つのではなく、顔にかけた状態で生成されました。「手に持つ」という指示は再現できませんでした。

パターン3:机の上の眼鏡

眼鏡を小道具として机の上に置く、という描写を試しました。

silver-rimmed glasses on desk

こちらも同様に、机の上に眼鏡は置かれず、キャラクターが眼鏡をかけた状態で生成されました。


分かったこと:眼鏡は「装着属性」でしかない

3パターンの検証結果から見えてきたのは、シロクマ効果のような心理学的な話ではなく、もっとシンプルな事実でした。

少なくとも今回の検証では、このモデルにとって眼鏡は「かけるもの」以外の何物でもありませんでした。

Illustrious系モデルはDanbooruのタグシステムで学習されています。Danbooruにおいて glasses はキャラクターの属性タグです。「眼鏡をかけている」という状態を示すタグとして圧倒的多数の画像と紐づいています。

一方で、「手に眼鏡を持っている」「机の上に眼鏡が置いてある」といった用法は、学習データ上にほとんど存在しないと思われます。そのため、glasses というトークンがポジティブプロンプトに含まれている限り、今回試したどの書き方でも、モデルは「眼鏡をかけた状態」として解釈しました。

つまり、眼鏡にまつわる問題の構造はこうなります。

「holding glasses in hand」
  → モデルの解釈: glasses = 顔に装着
  → 「in hand」はほぼ無視される

「glasses on desk」
  → モデルの解釈: glasses = 顔に装着
  → 「on desk」はほぼ無視される

「#silver-rimmed glasses」(コメントアウト)
  → この行は無効化される
  → しかし他の行に glasses が残っていれば同じ結果になる

否定語の問題もあるが、本質はそこではない

もちろん、no glasses と書いた場合にCLIPが noglasses をバラバラに解釈してしまう問題もあります。Stable Diffusionのトークナイザーは否定語をうまく処理できないため、no glasses が「眼鏡を召喚する」ことは事実です。

しかし、今回の検証で分かったのは、否定語の問題以前に、肯定的な文脈であっても「小道具としての眼鏡」を再現できないということです。これはネガティブプロンプトの仕組みとは関係のない、モデルの学習データに起因する制約です。


技術的な背景:CLIPとDanbooruの学習バイアス

もう少し技術的に掘り下げておきます。

Stable DiffusionはCLIPを使ってプロンプトをベクトル(数値表現)に変換します。holding silver-rimmed glasses in hand というプロンプトは、CLIPによって個別のトークンに分割されます。

ここで問題になるのは、CLIPの学習データにおいても「手に持った眼鏡」という概念の出現頻度が低いことです。Illustrious系モデルのDanbooru学習データと合わせて、glasses というトークンの意味がほぼ一義的に「顔に装着」へと固定されていると考えられます。

ネガティブプロンプトのClassifier-Free Guidance(CFG)の仕組みも簡単に触れておきます。

最終出力 = 無条件出力 + CFG_Scale × (条件付き出力 − 無条件出力)

ネガティブプロンプトは「無条件出力」を置き換えて、「その方向から離れろ」と誘導する仕組みです。「消す」のではなく「遠ざける」処理なので、ポジティブ側に glasses が強く存在すれば、ネガティブの誘導では太刀打ちできません。

ただし繰り返しになりますが、今回の核心はネガティブプロンプトの仕組みではなく、「ポジティブにglassesがある時点で装着が確定する」というモデル側の制約です。


よくある「装着属性トラップ」パターン

眼鏡と同じ構造の問題は、他の装着属性でも起きる可能性があります。今回検証したのは眼鏡だけですが、同じ理屈で考えると以下のようなパターンも起きうるのではないかと思います。

アイテム意図した描写予想される結果
眼鏡手に持つ、机に置く顔にかけてしまう(検証済み)
帽子棚に置く、手に持つ頭に被ってしまう(未検証)
武器壁に飾る、地面に置く手に持ってしまう(未検証)

いずれもDanbooruでキャラクター属性タグとして学習されているアイテムです。帽子や武器は未検証なので断言はできませんが、学習データの構造を考えると同じ傾向がありそうです。


結論:かけるか外すかの二択で考える

検証を通じて得られた、現時点での実用的な結論はこうです。

眼鏡は「かけるか、かけないか」の二択にする。 小道具として机の上に置いたり、手に持たせたりする構図は、少なくとも今回試した方法では再現できませんでした。もっと高度なアプローチで回避できる可能性はあるかもしれませんが、今の自分の知識の範囲ではここが限界です。

具体的な対処法としては、以下のようになります。

  • 眼鏡をかけたキャラを生成したい → ポジティブに glasses を入れる。それだけで確実に装着されます
  • 眼鏡をかけていないキャラを生成したい → ポジティブから glasses に関連するすべての記述を削除する。ネガティブへの追加は保険程度に
  • 眼鏡を小道具として描きたい → プロンプトでの再現は諦めて、生成後に加筆修正する

3つ目の選択肢は「プロンプトだけで完結しない」という、少し残念な結論です。加筆修正にはそれなりの画力が必要になりますし、正直なところ誰にでもお勧めできる方法ではありません。ただ、モデルの学習データに存在しない概念を無理にプロンプトで表現しようとするより、割り切ったほうが結果的に早いケースが多いです。

ネガティブプロンプトの使いどころ

ネガティブプロンプトが無意味というわけではありません。ポジティブから眼鏡関連のトークンを完全に排除した上で、念のため glasses, eyewear をネガティブに軽く入れておくのは有効です。ウェイトは1.0〜1.3程度が目安で、1.5以上にするとアーティファクトの原因になります。

ただし、ポジティブ側に glasses が残っている状態でネガティブをいくら積み上げても、効果は期待できません。


まとめ

この記事のポイントを3つにまとめます。

  1. 今回の検証では、Illustrious系モデルにとって眼鏡は「装着属性」でした。 手に持つ、机に置く、といった表現はどれも再現できませんでした
  2. これはネガティブプロンプトの問題ではなく、学習データの問題だと考えています。 Danbooruのタグ体系が眼鏡を装着属性としてのみ定義しているためです
  3. 眼鏡は「かけるか外すか」の二択で考えるのが、今のところ一番確実です。 小道具としての再現はプロンプトでは困難で、必要であれば後から加筆する形になります

最初はシロクマ効果を疑っていましたが、再検証の結果、もっとシンプルな話でした。モデルが知らない概念は、どう書いても生成できない。当たり前のようですが、実際にハマってみないと気づけないポイントでした。