技術約9分で読めます

Animaの4人LoRAをモジュール別に分けて、衣装の着せ間違いがどこで起きるか調べた

いけさん目次

前回の立ち位置と衣装の指定を2×2で入れ替えた実験では、かなとこはるの立ち位置と動作は入れ替えられた一方、黒タイツは12/12で前景右の人物が履いていた。人物名や空間上の役割を末尾で言い直しても直らなくて、プロンプトを短くすると別の要素まで崩れた。

次は、この着せ間違いがQwen、T5、LLMAdapter、DiTのどこで起きているのかを確認する。4人LoRAのチェックポイントをモジュール別に分け、プロンプトとノイズは同じまま生成して比べた。

検証環境

項目設定
環境M4 Mac mini上のComfyUI
モデルanima-base-v1.0
テキストエンコーダーqwen_3_06b_base
4人LoRAanima-4char-v1_epoch100
Turboなし
サンプラーer_sde / simple
ステップ数 / CFG25 / 4.0
解像度1344×768

主な比較はseed42で、プロンプト、T5のトークンID列、ノイズ、サンプラーはどの条件でも同じにした。

4人LoRAの描き分けと画風はどのモジュールが作るか

チェックポイントのキーを対象モジュール別に分類すると、Qwen本体のLoRAは0件だった。

対象LoRAモジュール数テンソル数
Qwen3-0.6B text encoder00
LLMAdapter36108
DiT280840

全体は316モジュール、948テンソル。ファイルをLLMAdapter onlyDiT onlyへ分け、まずは衣装を指定していない場面だけのプロンプトで比べた。使ったのは、かなの手振りとくらら・けいの会話が両方成立していた前回のセル110で、seed42・プロンプト・ノイズは前回と同じにした。比較用に、4人LoRA全体を適用したfullと、LoRAなしのbase Animaも同条件で並べた。

full LoRA。4人の描き分け、会話、奥の手振りまで描けている比較基準

full。4人の描き分けと画風が保たれた比較の基準になる。

base Anima。場面の構図は描けているが、4人は学習キャラの外見にならない

base Anima。キャラは崩壊して4人とも別人になり、手前2人は腕や顔まわりの絡みも不自然で、絵として気持ち悪い。手前の向き合う2人・横の1人・奥で手を振る1人という配置だけは残っている。

LLMAdapter-only。baseに近く、4人LoRAの画風と人物像にならない

LLMAdapter-only。base Animaとほとんど同じ絵で、キャラは崩壊したまま。

DiT-only。full LoRAに近い描き分けと画風になっている

DiT-only。描き分けも画風もfullとほぼ同じに保たれていて、下半身の衣装の誤り方までfullと一致した。

まだ1プロンプト・1シードの比較だが、4人の配置まではAnima本体だけでも出て、キャラを崩壊させない描き分けと画風はDiT側のLoRAが効いていると推測できる。この画像に限れば、LLMAdapter LoRAなしでも成立した。他のプロンプトでもLLMAdapter LoRAが要らないかは、この切り離しでは分からない。

衣装を着せ間違えた前回のP1O0を、そのままモジュール分割した

前の分割で使った110は、衣装を指定していない場面だけのセルだった。次は、実際に着せ間違えたプロンプトで同じ分割をやる。

前回の2×2で立ち位置だけを入れ替えたP1O0のseed42をそのまま使う。P1O0のプロンプトでは、奥で手を振るのがこはる、前景右で腕を組むのがかなで、スカートと黒タイツは奥のこはるへ指定している。つまり、奥で手を振るこはるが黒タイツを履けば正解だが、前回のfullでは前景右のかなが履いていた。

このプロンプトとノイズのまま、base、LLMAdapter-only、DiT-onlyを生成した。Qwen3-0.6BもT5のトークンID列もサンプラーも同じにした。fullは2×2で生成済みのP1O0を使った。

条件4人LoRAの描き分け・画風黒タイツの実位置P1O0の奥こはる指定
full前景右かな×
base対象外奥で手を振っている子
LLMAdapter-only対象外、base寄り奥で手を振っている子
DiT-only○、full寄り前景右かな×
full 4人LoRAのP1O0。黒タイツは指定した奥のこはるでなく前景右のかなが履いた

full。学習した4人の姿が出ていて、黒タイツは指定した奥のこはるでなく、前景右で腕を組むかなが履いた。奥で手を振るこはるは素足になっている。

base AnimaのP1O0。同じQwenとT5で、黒タイツは奥で手を振っている子が正しく履いた

base Anima。110の時と同じく、キャラは崩壊して手前2人の絡みも不自然で、構図もfullとは別物になっている。ただ黒タイツは、プロンプトの指定どおり、奥で手を振っている子(こはるの位置)が履いた。

LLMAdapter-onlyのP1O0。base寄りの画面で、黒タイツは奥で手を振っている子が履いた

LLMAdapter-only。baseとほぼ同じ絵のままで、黒タイツも同じく奥で手を振っている子が履いた。

DiT-onlyのP1O0。full寄りの描き分けと画風になり、黒タイツも前景右のかなが履いた

DiT-only。fullとほぼ同じ画面で、学習した4人の姿になり、黒タイツは前景右で腕を組むかなが履いた。

baseとAdapter-onlyで描かれた4人は、学習したキャラとは別人のままだ。しかし同じ0.6BのQwen/T5コンディショニングから、黒タイツは奥で手を振っている子へ、紺スカートは前景右で腕を組んでいる子へ、指定どおり描き分けられていた。

DiT-onlyを適用した時だけ、fullと同じ描き分け・画風になり、黒タイツもfullと同じ前景右のかなが履いた。このP1O0 seed42では、0.6Bエンコーダの情報不足というより、4人LoRAのDiT側に黒タイツを前景右の人物へ履かせる強い偏りがあって、それがbase Animaでは正しかった対応を上書きしていた。

1シードのモジュール分割なので、他のプロンプトにも当てはまるかは分からない。ただ、QwenとT5側の入力は全条件で同じまま、DiT LoRAの有無だけで、正しく履くか着せ間違えるかが入れ替わった。

手振りの違いをQwenとT5の交差で切り分けた

010はくらら・けいの会話だけ、110はそこへかなの手振りを足したセル。seed42の010の画像では、くららとこはるが向き合い、けいはカメラ寄りで、会話に加わっているように見える程度だった。110では、かなが手を振るだけでなく、けいもはっきり2人の方を向くようになった。この違いを切り分けに使う。

010と110で会話の文章は同じで、プロンプト後方にある、かなが手を振るという一文だけが違う。010のQwenの隠れ状態は394トークン、T5のトークンID列は470。110ではQwen 404、T5 481になった。

片方のセルのQwen出力と、もう片方のセルのT5出力を組み合わせて生成する。これを以下では交差と呼ぶ。010と110のQwen側コンテキストとT5側クエリ列で、次の5通りを生成した。

QwenT5結果
010 control010 control010の失敗型を再現
110 factor110 factor110の成功型を再現
010 control110 factorfactor側を再現
110 factor010 controlcontrol側を再現
zero110 factor3人の混成と壊れた空間
Qwen=010、T5=010。かなの手振りがなく、くららとこはるが向き合い、けいはカメラ寄りのcontrol

Qwen=010、T5=010。かなの手振りがなく、くららとこはるが向き合い、けいはカメラ寄りのまま。

Qwen=110、T5=110。かなが手を振り、けいも2人の方を向いたfactor

Qwen=110、T5=110。かなが手を振り、けいもはっきり2人の方を向いた。

Qwen=010、T5=110。factor側と同じく、かなが手を振り、けいも2人の方を向いた

Qwen=010、T5=110。110側と同じく、かなが手を振り、けいも2人の方を向いた。

Qwen=110、T5=010。control側と同じく、けいはカメラ寄りのままで、かなの手振りも出ない

Qwen=110、T5=010。010側と同じく、くららとこはるが向き合ったまま。かなは手を振らず、けいもカメラ寄りのまま。

Qwen=全ゼロ、T5=110。3人の混成と鏡写しのような壊れた空間になった

Qwen=全ゼロ、T5=110。3人の混成と、鏡写しのような壊れた空間になった。

かなの手振りと、けいの向きは、T5を110側へ替えると変わり、Qwenだけを110側へ替えても変わらなかった。つまり010から110への差分は、T5側のクエリ列を通って画像に反映されていた。

一方、Qwenをゼロにすると画像全体が壊れ、場面の意味も空間も保てなかった。ただ、010と110の違いにQwen側は関わっていなかった。

Qwenの隠れ状態を平均プールしたコサイン類似度は0.999935だったが、共通する394トークンの位置を対応させた比較では0.9124だった。平均値だけではほぼ同じに見えてしまうので、隠れ状態の数字を比べて判断するのはやめて、交差した組み合わせごとに実際に画像を生成し、どこが変わるかで判定した。

なお、seed1234でも同じ交差を試したが、直接実行した010の絵がComfyUI API版と合わなかった。API版は4人、直接版は3人の混成だったので、seed1234は途中でやめた。だからこの交差は、seed42でしか確認できていない。

同じ交差を衣装の割り当てでも試した

手振りの有無を分けた010/110では、T5側の交換だけで画像が切り替わった。では、P1O0とP1O1の衣装指定の違いはQwenとT5のどちらに現れるのか。

P1O0とP1O1は、かなとこはるの立ち位置を入れ替えた後の同じ場面だ。違うのは、スカートと黒タイツを奥のこはるへ指定するか(P1O0)、前景右のかなへ指定するか(P1O1)だけ。P1O0なら奥のこはるが、P1O1なら前景右のかなが黒タイツを履けば正解になる。どちらもQwenの隠れ状態は435×1024、T5のトークンID列は518だった。

seed42でQwen側コンテキストとT5側クエリ列を交差した。直接実行の生成はAPI版とピクセル単位では一致しないが、4人の描き分けも、奥で手を振るこはるも、前景右で腕を組むかなも、黒タイツを前景右のかなが履くところも同じだったので、この方法で進めた。

黒タイツは、4つの条件すべてで前景右のかなが履いていた。

QwenT5P1O0の奥こはる指定
P1O0P1O0×
P1O1P1O1-
P1O0P1O1-
P1O1P1O0×
Qwen=P1O0、T5=P1O0。両方とも奥のこはるへ黒タイツを指定しても、前景右のかなが履いた

Qwen=P1O0、T5=P1O0。両方とも奥のこはるへ黒タイツを指定しても、前景右のかなが履いた。

Qwen=P1O1、T5=P1O1。前景右のかな指定と実際の出力先が一致した

Qwen=P1O1、T5=P1O1。前景右のかなという指定と、実際に履いた人物が一致した。

Qwen=P1O0、T5=P1O1。黒タイツは前景右のかなが履いたまま

Qwen=P1O0、T5=P1O1。黒タイツは前景右のかなが履いたまま。

Qwen=P1O1、T5=P1O0。T5が奥のこはるを指定しても黒タイツは前景右のかなが履いたまま

Qwen=P1O1、T5=P1O0。T5が奥のこはるを指定しても、黒タイツは前景右のかなが履いたまま。

010/110とは違い、今回はQwenだけを替えてもT5だけを替えても、両方をP1O0にしても衣装の割り当ては変わらなかった。P1O0/P1O1のQwenの隠れ状態は、平均プールしたコサイン類似度が0.9999946、435位置を対応させた比較では0.9806485だった。文章の違いはQwenの隠れ状態にもT5のトークンID列にも反映されているのに、このチェックポイントでは黒タイツを履く人が変わらなかった。

前のゼロ介入のとおり、Qwenを消せば人数も空間も壊れるから、Qwenそのものは場面に要る。それでも黒タイツを誰が履くかについては、QwenをP1O0とP1O1のどちらにしても、T5をどちらにしても、結果は変わらなかった。

Qwenの違いを大きくしたら、履く人が変わるか確かめた

それでも、P1O0とP1O1のQwen出力の違いが小さすぎるだけ、という可能性は残る。そこでT5をP1O0へ固定し、Qwenの隠れ状態をP1O0側へ線形に外挿した。x2は2 × Qwen(P1O0) - Qwen(P1O1)、x4は4 × Qwen(P1O0) - 3 × Qwen(P1O1)とした。

学習時にはあり得ない値のテンソルを無理やり作る操作なので、大型Qwenに替えた状態の再現にはなっていない。本題は黒タイツを履く人が変わるかどうかだが、画像がまったく変わらないなら外挿自体が効いていない可能性もある。だから画像全体がどれくらい変わったかも一緒に確かめた。

P1O0方向へQwen差分をx2外挿。場面は保たれたが黒タイツは前景右のかなのまま

x2。場面は保たれたが、黒タイツは前景右のかなのまま。

P1O0方向へQwen差分をx4外挿。奥のこはるが両手を上げるほど画像は変わったが、黒タイツは前景右のかなのまま

x4。奥のこはるが両手を上げるほど画像は変わったが、黒タイツは前景右のかなのまま。

x2、x4とも、奥のこはるが黒タイツを履くことはなかった。x4では奥のこはるが両手を上げるほど構図が変わったから、介入は画像まで効いていた。ただ、P1O0とP1O1のQwen出力の違いを4倍まで大きくしても、黒タイツは前景右のかなが履いたままだった。

一方でモジュール分割では、同じ0.6Bのコンディショニングからbase Animaが黒タイツを正しく履かせていた。0.6Bの情報が足りないなら、baseも間違えるはずだ。だから今回の黒タイツは、DiT LoRAの上書きのせいだと考えている。

大型Qwenより先にDiT LoRAへ手を入れることにした

QwenもT5も同じ出力なのに、base AnimaとLLMAdapter-onlyは黒タイツを指定どおり奥で手を振っている子へ履かせて、DiT-onlyだけがfullと同じく前景右のかなへ履かせた。大きなQwenに替えればもっと確実になるのかもしれない。ただ少なくとも今回は、エンコーダは間違えていない。

そもそも衣装をトリガーへ固定しなかったのは、推論時に着せ替えたいからだ。その着せ替えが、今回は正しい相手に効かなかった。だったら、役割を入れ替えた学習データの作り直しか、DiT LoRAの当て方の調整を先に試して、大型エンコーダへの交換は後回しでいい。