画像生成AIは、どうやって「中間の姿」を描いているのか

このサイトでは、2つ(または4つ)の生き物を混ぜた「中間の姿」を眺められます。ここでは、その裏で動いている画像生成AIの一般的な仕組みを、このサイトで実際に作った画像を例に説明します。

1. 絵ができるまでの流れ

このサイトで使った画像生成AI(拡散モデルと呼ばれる種類)は、大きく分けて次の順番で絵を描きます。

言葉(プロンプト)「かわいい犬」など テキストエンコーダ言葉→ベクトル シード(乱数の種)→ 最初のノイズ ノイズを少しずつ取り除く(×28回)UNet 圧縮された絵latent(128×128×4) デコーダ(VAE)→ 1024px の画像 案Cで混ぜる 案Cで混ぜる 案Aで混ぜる
拡散モデル(このサイトでは Animagine XL 4.0)の大まかな流れ。「案C」「案A」は、このサイトで2つの生き物を混ぜている場所です(4章で説明します)。

ポイントは、AIが絵をいきなり描くのではなく、ノイズ(砂嵐のような乱れ)から少しずつ整えていくことと、その方向づけに言葉をベクトルにしたものを使うことです。

2. 言葉はベクトル(数の並び)になる

AIは言葉をそのまま理解しているわけではありません。テキストエンコーダが、言葉を数千個の数が並んだもの(ベクトル)に変換します。ベクトルは「巨大な空間の中の1点」と考えることができます。

学習の結果、意味の近い言葉は近い場所に、遠い言葉は遠い場所に置かれます。例えば「狼」と「熊」は近く、「狼」と「青年」は遠くなります。

狼 熊 ドラゴン 青年 女性 直線の中間 動物どうしは近い 人どうしも近い
ベクトル空間のイメージ(実際は数千次元ですが、2次元に描いています)。2つの点を直線で結んだ「中間の点」を描かせると、中間の姿が生まれます。

このサイトの「中間の姿」は、2つの言葉のベクトルを割合を変えて足し合わせた点(例:狼70%+青年30%)をAIに渡して描かせたものです。

3. ノイズから少しずつ描く

拡散モデルは、学習のときに「きれいな絵に少しずつノイズを足していき、それを元に戻す」練習をしています。描くときはその逆で、完全なノイズから出発し、言葉のベクトルを手がかりに、ノイズを少しずつ取り除いて絵にしていきます。

ノイズから犬の絵ができていく6段階
左端が出発点のノイズ、右へ行くほど描き込みが進んだ状態(28回中の1・4・8・14・28回目)。途中の状態を軽量デコーダで見えるようにしたものなので、途中の色は実際より乱れて見えます。

出発点のノイズはシードという数で決まります。同じ言葉・同じシード・同じ手順なら、毎回同じ絵になります。シードを変えると、ポーズや構図が変わります。

4. どこで混ぜるか:案Cと案A

このサイトでは、2つの生き物を「どの段階で混ぜるか」が違う2つの方式を見比べられます。

案C:描く前に混ぜる

言葉のベクトル(と出発点のノイズ)を混ぜてから、AIに一から描き直させます。AIが「混ざった指示」を解釈して描くので、中間でも1匹の生き物として描かれます。重い計算なので、画像は事前にPCで作っておきます。

案A:描き終わった絵を混ぜる

完成した2枚の絵の圧縮データ(latent)を混ぜて、デコーダで画像に戻します。描き直しはしないので、2枚が透けて重なったような見え方になります。軽い計算なので、ブラウザの中でその場で計算しています。

犬からタコへの中間。上が案A、下が案C
犬→タコ(0%・25%・50%・75%・100%)。上段が案A(圧縮データを混ぜる)、下段が案C(言葉を混ぜて描き直す)。

同じ「中間」でも、意味(言葉)で混ぜるか、見た目(絵のデータ)で混ぜるかで、結果が大きく変わります。

5. 遠い組み合わせほど「謎の姿」になる

ベクトルの近い組み合わせ(熊↔狼)は、中間でもどちらかの動物らしい姿を保ち、なめらかに変わります。遠い組み合わせ(狼↔青年)は、中間でどちらでもない姿(このモデルでは小さな獣人のようなキャラ)になります。

狼から青年、ドラゴンから女性、熊から狼への中間
上:狼→青年、中:ドラゴン→女性、下:熊→狼。

実際に、このサイトで使った言葉のベクトルどうしの距離を測ると、次のようになりました(数字が大きいほど遠い)。

組み合わせ距離中間の姿
狼 × 熊0.016なめらかに変わる
熊 × ドラゴン0.019なめらかに変わる
青年 × 女性0.365—
人 × 動物(6組)0.41〜0.43どれも似た「謎のキャラ」

距離は「1−コサイン類似度」で、プロンプト全体のベクトルを比べたものです。この測り方はプロンプトの長さや語順の違いにも影響されるので、目安として見てください。

中間で何が描かれるかは、ベクトルの置かれ方と、そのモデルが学習で何を多く見てきたかの両方で決まります。このモデルはアニメのキャラクターを中心に学習しているため、あいまいな場所ではアニメキャラとして描きやすいと考えられます。また、直線で結んだ中間が「意味の上での中間(半分人・半分狼)」になる保証は、どのモデルにもありません。

6. そろえると、変化が見やすくなる

変化を見やすくするには、違いを1か所に絞るのが効果的です。「年齢×性格」のページでは、4人の言葉の形・服装・シードをすべてそろえ、「若い/年配」「クール/熱血」の言葉だけを変えました。

年齢と性格の7×7の格子画像
左→右:青年→老人、上→下:クール→熱血。4つの角の言葉を、割合を変えて混ぜた49枚。

7. 言葉は文字どおりに描かれる

最初、熱血を表すために「hot-blooded(熱血)」「fiery eyes(燃えるような目)」と書いたところ、AIは本当に頭が燃えているキャラを描きました。言葉の比喩的な意味ではなく、学習した絵と結びついた見た目として解釈されるためです。

熱血側が炎のキャラになった格子画像
「炎の熱血」スタイル。下の2段で、急に炎のキャラに切り替わります。言葉を「表情としぐさ」に変えたものが「現代マンガ」スタイルです。

8. LLM(文章のAI)との共通点と違い

ChatGPTやClaudeのような文章を扱うAI(大規模言語モデル、LLM)も、言葉をベクトルにして扱う点は同じです。ここでは一般的な仕組みとして整理します。

共通点

  • 言葉をベクトルにする:LLMも文章を「トークン」という単位に区切り、それぞれを数百〜数千次元のベクトルに変換してから処理します。画像生成のテキストエンコーダも、LLMと同じ「Transformer」という仕組みでできています。
  • 意味の近さが距離になる:意味が似た言葉ほど、ベクトル空間で近くに置かれる傾向があります。
  • 置き方はモデルしだい:どの言葉をどこに置くかは学習で決まるので、モデルが違えば配置も変わります。

違い

  • ベクトルの使い道:画像生成では、ベクトルは「何を描くか」の指示で、絵そのものはノイズから描く部分が作ります。LLMは、ベクトルを何層もの計算で処理して、次に来るトークンを1つずつ予測し、文章を組み立てます。
  • 文脈で変わる:LLMの内部では、同じ単語でも前後の文脈によってベクトルが変わっていきます。「1つの言葉=1つの点」と言えるのは、入口の部分(埋め込み)までです。
  • 混ぜた結果の見え方:画像では、ベクトルの中間を「中間の絵」として目で見られます。LLMで2つの単語のベクトルを混ぜても、なめらかな「中間の文章」になるとは限らず、このサイトのように目で確かめるのは難しいです。

この節は一般的な説明です。このサイトで実際に計測・確認したのは、画像生成モデル(Animagine XL 4.0)のテキストエンコーダの距離までです。

9. このサイトの作り方と注意点

  • 使ったモデル:Animagine XL 4.0(SDXL系、ライセンス:CreativeML Open RAIL++-M)、SD-Turbo(「ダークファンタジー」スタイル)。
  • 事前生成(案C):PCのGPU(GeForce RTX 2070 SUPER)で、1枚あたり約19秒(1024px・28回)。表示は512pxに縮小しています。
  • ブラウザでの計算(案A):TAESD / TAESDXL(軽量デコーダ、MIT)をONNX形式に変換し、ONNX Runtime Web(WebGPU)で動かしています。
  • 中間の作り方:言葉のベクトルは割合で足し合わせ、出発点のノイズはシードが違う場合に球面補間(slerp)で混ぜています。毎回同じ結果になるよう、ランダム性のない手順(Euler)で描いています。
  • 中間の姿の崩れや奇妙さも含めて楽しむ技術デモです。

試してみる:狼 → 青年

スライダーを動かすと、事前に描いた16枚の中間を順に表示します(「ひと・けもの・竜」と同じ画像です)。

狼から青年への中間画像
狼青年

狼 100% / 青年 0%