AnimaのDiTの残差ストリームに色の差を足して、髪色だけ変わる方向を探した
目次

GPT-OSSの隠れ状態を記号構造の式に差し替えても答えがほぼ同じだった論文の話をしていた。
LLMの全層の隠れ状態をテンソル積表現という閉じた式で作り直しても本体の答えがほぼ変わらず、役割を書き換える介入も通る。
ならば画像生成のDiTでも同じ見方ができるんじゃないか、という流れになった。
LLMでいう文法や論理の内部アルゴリズムにあたるものは、DiTなら空間配置、部品構造、属性の束縛、遠近と遮蔽、denoise過程の役割分担あたりに対応するはずだと考えた。
Animaの4人LoRAの崩れをconditioningの中まで覗いた記録では、DiT直前のconditioningまでは介入して調べたが、そのconditioningをDiTがどう画像空間へ実装しているかは調べていない。
入口だけ調べて「プロンプトは理解してそうだ」で止まっていた。
今回はDiT本体を開けてみる。
まず赤一色と青一色の絵で色がどこで決まりどこに書き込まれるかを調べ、次に1人の髪、最後に2人並びの髪色を試した。
検証環境
| 項目 | 内容 |
|---|---|
| マシン | Apple M1 Max 64GB、macOS 26.5 |
| 実行方法 | ComfyUI v0.30.1(commit 0764232)の comfy パッケージを直接importする自作ハーネス(.image-work/dit-probe/) |
| DiT | Anima-Base v1.0(bf16) |
| テキストエンコーダ | Qwen3-0.6B-Base+T5トークナイザー、Anima本体のLLMAdapter |
| LoRA | なし(Turboも外す) |
| 共通条件 | 30 step、CFG 4.0、euler、scheduler simple、1216×832(トークン格子52×76) |
| ネガティブ | worst quality, low quality, blurry, lowres, text, watermark, bad hands |
| 計測対象 | CFGのcond側パスだけ |
DiTの構造はComfyUIの comfy/ldm/cosmos/predict2.py にある。
各Blockは self-attention(画像トークン同士)→ cross-attention(画像トークンがconditioningを参照)→ MLP の順で、adaLNでtimestep埋め込みが掛かる。
テキストはcross-attentionだけを通って画像側へ入るので、E1では各画像トークンがどのテキスト位置をどれだけ強く参照したかをcross-attentionの重みで測る。重みだけで実際の寄与が決まるわけではないので、あとの節ではconditioningの差し替えでも確かめる。
Qwen-ImageのようなMMDiTだと画像とテキストが同じattentionに混ざるが、Animaではテキスト側の重みだけを別に扱える。
モデルの構成はAnima-Baseのmodel cardのとおりで、以下は手元で動かして測った値。
| 項目 | 実測値 |
|---|---|
| Block数 | 28 |
| hidden次元 | 2048 |
| ヘッド数 | 16(head_dim 128) |
| トークン格子(縦×横) | 52×76=3952画像トークン(patch 2、1216×832のまま偶数) |
| conditioning shape | (1, 512, 1024)。実際のプロンプトは38トークン前後で、残りはゼロパディング |
| 1枚の生成時間(30 step) | 254秒(4 stepで38秒) |
cond側とuncond側は transformer_options["cond_or_uncond"] で見分ける。
この解像度ではcondとuncondが別呼び出しで交互に来るので、0の行だけを計測・改変した。
単語とcross-attentionのキー位置の対応は、T5トークナイザーで実際にトークン化して調べた。
ハーネスの動作確認でまず引っかかったのが、self-attentionの左右遮断。(b,1,S,S) の真偽値マスクでSDPAに指定すると、MPSでは数Block進んだところでNaNになって真っ黒な画像が出る。
同期を強制すると再現しない。原因は分からないままだが、左右のトークンを切り出してモデル自身のattention演算を別々に走らせる方式(ブロック対角マスクと等価)にしたら通ったので、そのまま進めた。
もう1つは残差ストリームで、ComfyUI側がfp32で保持していて値が大きく(最大で2.7e5程度)、fp16で保存すると中盤Blockでごく一部がinfになる。E2の保存はfp32にした。
計測を入れても画像が変わらないかは、attnとresidのフック有無で出力PNGを比べた。bit単位で一致。conditioning差し替えも、全Block・全stepで差し替えるとプロンプトBを素で生成した画像とbit単位で同じになった。
実験の順序
実際に行った順は2人並び(E0〜E7)が先で、単色(S0〜S5)はそのあとに追加した。
| 段 | 番号 | 名前 | やること | 測るもの |
|---|---|---|---|---|
| 単色 | S0 | 単色が出るか | 赤・青・緑・黄の単色プロンプトをseed 42で生成する | 画像の平均RGBと標準偏差。単色と呼べるか |
| 単色 | S1 | 色が決まるstep | 赤と青の生成で、各stepのdenoise予測(x0)をVAEで絵に戻し、平均RGBを取る | 何step目で赤と青に分かれるか |
| 単色 | S2 | 残差の差 | 同じseedで赤と青を回し、全Block・全stepの出力を保存して差を取る | 差のL2がどのBlockで大きいか。差の大きい次元が巨大値の次元と同じか |
| 単色 | S3 | 方向の移植 | 青 − 赤 の平均方向を赤の生成に足す。Block群を変えて7回、全Blockでstepを限定して2回 | 画像の平均RGBが青に近づくか。どのBlockで変わるか |
| 単色 | S3x | 単独Blockと係数 | S3で色が変わったBlock群を1つずつに分け、step 0〜1だけに足す。係数0.7も1回 | Block 1つで足りるか |
| 単色 | S4 | 空間で切る | S3で色が変わったBlock群に、左半分のトークンにだけ方向を足す | 左半分だけ青くなるか |
| 1人 | S5 | 髪への移植 | 同じ方向を、1人の金髪の絵の髪トークンに足す | 髪が青くなるか。顔と服が残るか |
| 2人 | E0 | ベースライン | 左右の髪色を入れ替えた2本をseed 5個ずつ素で生成する | 左右の髪色が指示どおりか |
| 2人 | E1 | cross-attention map | 全Block・全stepの blonde と black へのattention重みを空間マップに戻す | 偏りが立ち上がるBlockとstep |
| 2人 | E2 | 残差ストリーム差分 | 同じseedで2本を回し、全Block出力の差を取る | 差の左右非対称度 |
| 2人 | E3 | conditioning差し替え | 指定Block群または指定step範囲だけ、もう一方のconditioningに差し替える | どこを差し替えると髪色が入れ替わるか |
| 2人 | E4 | self-attention左右遮断 | 画像トークンのself-attentionで左右の相互参照を切る | 遮断で何が起きるか |
| 2人 | E5・E6 | トークン単位の書き換え | 髪色のトークン位置だけを差し替える。Block・step・空間・混合比で絞る | 元の絵を残して髪色だけ変わるか |
| 2人 | E7 | 残差ストリームを直接書き換える | 髪色の差ベクトルを髪トークンにだけ足す | 髪だけ変わるか |
S0 単色が出るか
プロンプトは solid red background, plain background, no humans, flat color, empty の色名だけを変えた4本。ネガティブは共通条件のまま。
1回目で4色とも単色になったので、文言の試行はしていない。
| 色 | 平均RGB | 標準偏差(R / G / B) | 単色度 |
|---|---|---|---|
| red | 213 / 18 / 30 | 0.61 / 0.55 / 0.46 | 100% |
| blue | 1 / 87 / 187 | 0.50 / 0.41 / 0.57 | 100% |
| green | 62 / 132 / 79 | 0.51 / 0.43 / 0.51 | 100% |
| yellow | 255 / 241 / 73 | 0.01 / 0.52 / 0.76 | 100% |
単色度は、RGBの3チャンネルすべてがその画像の平均から±20以内に入る画素の割合。どの画像も各チャンネルの値の幅が5〜10階調しかない。




T5トークン化では4本とも15トークンで、色の単語は solid の次の位置1に1トークンで来た。conditioningの1行が色の単語1つに対応していた。
S1 色が決まるstep
各sampling stepでサンプラーが出すdenoise予測(x0)をVAEで絵に戻し、平均RGBを取った。
取り方はComfyUIのサンプラーのcallbackで、プレビュー用に渡される denoised をそのまま保存し、サンプリング後にまとめてデコードした。
DiTは変更していないので最終画像は通常生成の gen とbit単位で一致した(SHA-256で確認)。30回のデコードは110秒で、1回3.7秒。
red・blueに加えて、S5で使う1人の絵 G(1girl, upper body, looking at viewer, simple background, blonde hair, long hair)でも取った。
| step | red | blue | G |
|---|---|---|---|
| 0 | 255 / 66 / 59 | 5 / 133 / 255 | 255 / 254 / 250 |
| 1 | 220 / 17 / 28 | 3 / 87 / 179 | 239 / 212 / 185 |
| 2 | 210 / 24 / 35 | 4 / 89 / 180 | 244 / 225 / 199 |
| 3 | 213 / 24 / 33 | 2 / 89 / 183 | 248 / 228 / 206 |
| 5 | 213 / 20 / 31 | 1 / 88 / 185 | 248 / 225 / 207 |
| 10 | 213 / 17 / 30 | 1 / 87 / 186 | 247 / 223 / 204 |
| 15 | 213 / 17 / 30 | 1 / 87 / 186 | 247 / 222 / 203 |
| 29 | 213 / 18 / 30 | 1 / 87 / 187 | 246 / 222 / 203 |



3本とも、step 1で全チャンネルが最終色の±30以内に入った。
step 0のx0はどれか1チャンネルが255に張り付いていて外れるが、2回目の予測でもう色は決まっていて、あとは値が詰まっていくだけ。redの単色度はstep 0で51%、step 1で96%、step 2で100%。
Gも色の平均はstep 1で決まっていた。形のほうはstep 1ではぼやけた塊で、step 4で人物と分かる形になり、目や襟の細部はstep 10あたりから。
色は最初の2 stepで決まるらしい。なのでS3以降で方向を足すときは、全stepに足す条件のほかにstep 0〜1だけに足す条件も入れた。
S2 残差の差
同じseed 42でredとblueを回し、全28 Block・全30 stepの出力をfp32で保存した(1本25GB)。
同じstep・同じBlockの出力の差を取り、全トークンで平均したベクトル d = blue − red を作った。
確かめるのは、差が少数の次元に偏るか、偏るならそれがE2で見つかる巨大値の次元と同じか。なので d のノルム、redの残差ノルムに対する比、|d| の上位20次元がノルムに占める割合、その20次元がredの残差自体で値の大きい上位20次元と重なる数を出した。
表はstep 1と15、Blockは4つおき。
| step | Block | dのノルム | 残差ノルム | 比 | 上位20次元の割合 | 巨大値の次元との重なり |
|---|---|---|---|---|---|---|
| 1 | 0 | 5 | 30 | 0.18 | 0.93 | 0 |
| 1 | 4 | 1038 | 8309 | 0.13 | 0.88 | 0 |
| 1 | 8 | 1242 | 8703 | 0.14 | 0.87 | 2 |
| 1 | 12 | 1239 | 10630 | 0.12 | 0.88 | 0 |
| 1 | 16 | 1250 | 11960 | 0.11 | 0.88 | 0 |
| 1 | 20 | 1377 | 13700 | 0.10 | 0.86 | 0 |
| 1 | 24 | 3054 | 14220 | 0.22 | 0.89 | 2 |
| 1 | 27 | 12030 | 61820 | 0.19 | 0.58 | 1 |
| 15 | 0 | 27 | 57 | 0.48 | 0.90 | 1 |
| 15 | 4 | 3271 | 8614 | 0.38 | 0.94 | 1 |
| 15 | 8 | 3477 | 8793 | 0.40 | 0.93 | 1 |
| 15 | 12 | 3511 | 10600 | 0.33 | 0.92 | 2 |
| 15 | 16 | 3527 | 11930 | 0.30 | 0.92 | 2 |
| 15 | 20 | 3583 | 13610 | 0.26 | 0.92 | 1 |
| 15 | 24 | 4925 | 15020 | 0.33 | 0.91 | 4 |
| 15 | 27 | 11460 | 63520 | 0.18 | 0.65 | 4 |



赤と青の差は2048次元中の20次元に85〜94%が集中していた。Block 26〜27だけ58〜65%に下がる。あとのE7で髪色の差も20次元に7〜8割集中するのと同じ形。
その20次元は、残差自体で値の大きい巨大値の次元とはほぼ重ならない(中間Blockで0〜2、Block 24と27で最大4)。2人の実験のE7の段階では同じ次元じゃないかと考えていたが、違った。色の差はおおむね普通の大きさの次元にある。
差は空間的には均一で、Block 0〜11と22〜27ではトークン間のばらつき(変動係数)が0.02〜0.17。
Block 12〜21だけ3952トークン中62個(1.6%)で差が中央値の10倍以上あり、位置はBlock 12〜21で同じで、Block 22で消えた。
Block 0の差は5〜27で、Block 1以降の1000以上に比べるとほぼゼロ。赤青の2本では、Block 0の出力はプロンプトの違いをほとんど反映していないらしい。
S3 方向の移植
S2の d をredの生成に足した。領域は全トークン、平均方向、係数1.0。Block群を7つに分けて全stepに足す7本と、全Blockでstepを限定する2本。
射影は平均RGBを red→blue の直線に射影した値で、0がred、1がblue。
| 番号 | Block | step | 平均RGB | 単色度 | 射影 | 見た目 |
|---|---|---|---|---|---|---|
| S3-1 | 0〜3 | 全部 | 255 / 40 / 1 | 43% | −0.16 | 飽和した橙赤に黄色の粒 |
| S3-2 | 4〜7 | 全部 | 254 / 21 / 1 | 34% | −0.18 | 飽和した赤に細かい粒 |
| S3-3 | 8〜11 | 全部 | 0 / 0 / 0 | ― | ― | 全面黒(残差がNaN) |
| S3-4 | 12〜15 | 全部 | 0 / 0 / 0 | ― | ― | 全面黒(残差がNaN) |
| S3-5 | 16〜19 | 全部 | 0 / 0 / 0 | ― | ― | 全面黒(残差がNaN) |
| S3-6 | 20〜23 | 全部 | 0 / 0 / 0 | ― | ― | 全面黒(残差がNaN) |
| S3-7 | 24〜27 | 全部 | 0 / 162 / 255 | 97% | 1.22 | 単色のシアン寄りの青。薄いトークン格子の織り目 |
| S3-8 | 0〜27 | 0〜1 | 0 / 0 / 0 | ― | ― | 全面黒(残差がNaN) |
| S3-9 | 0〜27 | 2〜29 | 0 / 0 / 0 | ― | ― | 全面黒(残差がNaN) |
飽和した2本には、上位20次元を0にした版も回した。
| 番号 | Block | step | 平均RGB | 単色度 | 射影 | 見た目 |
|---|---|---|---|---|---|---|
| S3-1c | 0〜3 | 全部 | 236 / 234 / 243 | 61% | 0.59 | 白に近い薄紫、粒状 |
| S3-2c | 4〜7 | 全部 | 167 / 223 / 255 | 30% | 0.80 | 水色、斜めの織り目が強い |











Block 24〜27に足したときだけ青に変わった。しかも青を通り越してシアン寄り(射影1.22)。
Block 8〜23は4Blockまとめて足すと残差がNaNで全面黒。全Blockで足してstep範囲を絞っても同じだった。Block 0〜7は赤のまま飽和した。
差ベクトルは各Blockでそれぞれ次のBlockの入力もずらすので、4つまとめて足すと影響が重なる。NaNはそのせいかもしれないが、この測定では判別できない。
上位20次元を0にした版は、Block 0〜7でも青の側に変わったが、単色度が30〜60%まで下がって織り目が出た。
S3の追加 単独Blockと係数
S1で色がstep 1までに決まっていたので、Block 24〜27の4つを1つずつに分け、step 0〜1だけに足してみた。係数を0.7に下げた4本まとめも1本試した。
| 番号 | Block | step | 係数 | 平均RGB | 単色度 | 射影 |
|---|---|---|---|---|---|---|
| S3x-1 | 24 | 0〜1 | 1.0 | 0 / 142 / 255 | 100% | 1.20 |
| S3x-2 | 25 | 0〜1 | 1.0 | 0 / 142 / 255 | 100% | 1.20 |
| S3x-3 | 26 | 0〜1 | 1.0 | 0 / 136 / 255 | 100% | 1.19 |
| S3x-4 | 27 | 0〜1 | 1.0 | 0 / 137 / 255 | 100% | 1.19 |
| S3x-5 | 24〜27 | 0〜1 | 0.7 | 0 / 175 / 255 | 100% | 1.23 |





Block 1つ、step 0〜1だけで、赤が完全に青になった。24〜27のどれでも同じで、単色度も100%のまま。
射影が1を超えてシアン寄りになるのは4本まとめでも単独でも変わらず、係数0.7に下げても1.23。2点しか試していないが、方向の大きさに対して色が線形に変わる感じではない。
S4 空間で切る
Block 24〜27に、左半分(列0〜37)のトークンにだけ d を足した。全stepの版と、step 0〜1だけの版。
| 番号 | step | 左半分の平均RGB | 右半分の平均RGB | 境界 |
|---|---|---|---|---|
| S4-1 | 全部 | 0 / 161 / 255(射影1.22) | 188 / 170 / 131(射影0.43) | x=631で色差141。トークン境界に沿ってギザギザ |
| S4-2 | 0〜1 | 0 / 162 / 255(射影1.22) | 171 / 6 / 9(射影0.07) | x=629で色差327。幅1画素 |


step 0〜1だけの版は、左が青、右が赤のままで、境界は1画素幅の直線。
全stepの版は左が青になる一方、右がベージュに崩れて、境界がトークン境界のギザギザになった。
境界の位置は列38のトークン境界にあたる608画素より1.3〜1.4トークン分右の629〜631画素。VAEの受容野(1画素を復元するときに参照する周辺の範囲)の分だと思う。
この条件では、単色の差方向を最後の4 Blockへstep 0〜1で足すと、左右を分けて色を変えられた。
無介入のときに色がそのBlockで書き込まれているかまでは確かめていない。中間Block(8〜23)に足すと残差が発散するので、そこには同じ形では足せない。
S5 髪への移植
単色で取れた方向を、1人の金髪の絵Gの髪トークンに足した。
髪はもともと黄色系なので方向は blue − yellow にして、yellowの残差はBlock 24〜27・step 0〜1だけ保存した。比較で blue − red も1本足した。
Gの髪マスクは素Gから金髪の画素(R>150、G>110、B<160、R−B>40)を取り、25%以上で髪トークンとした。3952トークン中1054個。頭頂のハイライトを拾うためにBの上限を140ではなく160にしていて、首の影が2〜3トークン入っている。

素Gの髪内の平均RGBは 235 / 190 / 118。
| 番号 | 方向 | Block | step | 領域 | 素Gとの画素差(全体 / 髪内 / 髪外) | 髪内の平均RGB |
|---|---|---|---|---|---|---|
| S5-1 | blue − yellow | 24〜27 | 0〜1 | 髪 | 94 / 185 / 61 | 0 / 3 / 252 |
| S5-2 | blue − red | 24〜27 | 0〜1 | 髪 | 68 / 137 / 43 | 0 / 177 / 256 |
| S5-3 | blue − yellow | 24〜27 | 0〜1 | 全部 | 165 / 177 / 161 | 0 / 25 / 248 |
| S5-4 | blue − yellow | 24〜27 | 全部 | 髪 | 223 / 181 / 239 | 0 / 0 / 0 |




髪トークンに足したS5-1は、髪マスクの形がそのまま青いベタ塗りの塊になった。
塊の輪郭は滑らかな曲線で黒い縁取りが付き、人物はその下の空いた場所に小さく描き直されて、服は赤のまま、塗りは平坦な線画調。
blue − red のS5-2も同じ崩れ方で、色が水色になった。
全トークンに足したS5-3は全面が青になって人物が消えた。全stepに足したS5-4は残差が発散して真っ黒。
単色で取れた方向は、足した領域を青一色の面にする方向だったらしい。
髪の領域に足すとそこを青い物体として描いて、人物は空いた場所に描き直された。
step 0〜1は色だけでなく構図も決まる段階なので(S1でGの形はstep 4まで固まらない)、そこに面の指示を足したから構図ごと変わったのだと思う。
2人並びの髪色へ
時系列では単色より前にやった実験。2人並んだ絵で、左の子が金髪、右の子が黒髪という属性と位置の束縛を、conditioningの差し替えから入って最後に残差ストリームの操作まで調べた。
LoRAを使わない理由
キャラLoRAを当てると、見つかった構造がAnimaの性質なのかLoRAの性質なのか見分けがつかない。上の4人LoRAの記録で、キャプションの書き方しだいで外見がトリガーへ吸収されるのも確かめているので、LoRAの影響が混ざってしまう。
素のAnimaで blonde hair と black hair のような普通の属性なら、テキスト側で属性が1〜2トークンに対応して、cross-attentionでその単語からどのパッチに重みが乗ったかを調べやすい。同じ理由でTurbo LoRAも外して、通常stepとCFGありで回した。
プロンプト
2人が横に並ぶ絵で、髪色だけを左右で入れ替えた2本を基本にする。
| 記号 | プロンプト |
|---|---|
| A | 2girls, standing side by side, upper body, looking at viewer, simple background. The girl on the left has blonde hair. The girl on the right has black hair. |
| B | 2girls, standing side by side, upper body, looking at viewer, simple background. The girl on the left has black hair. The girl on the right has blonde hair. |
AとBは単語の集合が同じで、束縛だけが違う。
エンコーダ側の表現にも差は出るが、cross-attentionの重みを単語ごとに空間へ戻せば、DiTがその差をどこで位置へ変換したかが分かるはず。
E0 ベースライン
A・Bをseed 42〜46で素のまま生成。10枚とも2人が描かれて、左右の髪色は指示どおりだった。
判定は画像を1枚ずつ開いて、人数と左右の髪色だけを見たままで書いた。
| プロンプト | seed | 左の髪色 | 右の髪色 |
|---|---|---|---|
| A | 42 | blonde | black |
| B | 42 | black | blonde |
| A | 43 | blonde(彩度の高い黄色) | black |
| B | 43 | black | blonde(彩度の高い黄色) |
| A | 44 | blonde | black |
| B | 44 | black | blonde |
| A | 45 | blonde | black |
| B | 45 | black | blonde |
| A | 46 | blonde | black |
| B | 46 | black(青みを含む濃紺寄り) | blonde |










服の色は指定していないが、seed 42のAでは左の子の服が白系、右の子の服が黒、seed 46のBでは左が紺の上着、右が赤のセーターになっている。
髪色と位置が入れ替わったseedはE4で使うつもりだったが、10枚とも指示どおりで出なかった。素のAnimaはこのプロンプトだと崩れないらしい。
E4は髪色に服の色を足した条件にして、まず指示から外れるかどうかから確かめた。
E1 cross-attention map
E0で指示どおりだったA・seed 42を、全Block・全stepのcross-attention重みを記録しながら同条件で生成した。
記録はq・kのコピーから別計算しているので、出力画像は記録なしのE0と同一になる(bit単位で一致することはハーネスの動作確認で確かめた)。
各Blockの各stepで、画像トークン3952個それぞれが blonde(T5トークン位置25)と black(位置34)へ向けたattention重みをヘッド平均で取り、52×76の格子に戻した。
そのうえで「左半分の格子に落ちた重みの合計 ÷ 全体」を左半分比率とした。0.5なら左右に偏りがない。


数値はこんな感じ。
| Block | blonde step 0 | blonde step 10 | blonde step 29 | black step 0 | black step 10 | black step 29 |
|---|---|---|---|---|---|---|
| 0 | 0.50 | 0.50 | 0.50 | 0.50 | 0.50 | 0.48 |
| 2 | 0.54 | 0.63 | 0.58 | 0.46 | 0.32 | 0.44 |
| 5 | 0.67 | 0.81 | 0.57 | 0.31 | 0.25 | 0.46 |
| 9 | 0.91 | 0.90 | 0.64 | 0.09 | 0.12 | 0.38 |
| 13 | 0.90 | 0.84 | 0.66 | 0.10 | 0.12 | 0.31 |
| 16 | 0.81 | 0.75 | 0.60 | 0.19 | 0.20 | 0.39 |
| 19 | 0.61 | 0.63 | 0.52 | 0.41 | 0.39 | 0.48 |
| 20 | 0.49 | 0.49 | 0.49 | 0.49 | 0.49 | 0.50 |
| 27 | 0.50 | 0.50 | 0.50 | 0.50 | 0.50 | 0.50 |
Block 0〜1とBlock 20〜27は、どのstepでも両方の単語が0.50前後で、左右の偏りがなかった。
偏りはBlock 2あたりから出始め、Block 8〜16で最も強く、step 0の時点でBlock 9は blonde が0.91、black が0.09でほぼ鏡像になっていた。
偏りはstepが進むほど弱まり、Block 9の blonde は step 0 の0.91から step 29 では0.64まで下がった。
左半分比率は方向だけを表しているので、格子全体の重みの平均(1トークンあたり)も出した。conditioningは512トークンなので、均等に参照していれば1トークンあたり 1/512 ≒ 0.00195 になる。表は1000倍した値。
| Block | blonde step 0 | blonde step 10 | blonde step 29 | black step 0 | black step 10 | black step 29 |
|---|---|---|---|---|---|---|
| 0 | 1.0 | 0.9 | 1.0 | 0.9 | 0.9 | 0.9 |
| 5 | 2.3 | 1.6 | 0.3 | 1.7 | 0.9 | 0.3 |
| 9 | 6.2 | 2.3 | 0.4 | 7.7 | 2.2 | 0.3 |
| 13 | 3.6 | 1.1 | 0.2 | 2.9 | 1.2 | 0.2 |
| 19 | 5.6 | 2.1 | 0.8 | 5.9 | 2.0 | 0.7 |
| 20 | 0.9 | 0.9 | 1.0 | 0.9 | 0.9 | 1.0 |
| 27 | 0.9 | 0.9 | 1.0 | 1.0 | 1.0 | 1.1 |
step 0のBlock 9は均等の3〜4倍の重みが髪色の単語に集まっていて、step 29ではその同じBlockが均等の1/5以下まで下がった。
一方でBlock 0〜1と20〜27は最初から最後まで均等の半分程度で、値がほとんど変わらなかった。
後半Blockの0.50は、この2単語をほとんど参照していない状態の値らしい。代わりに何を参照しているかは、この計測では取っていない。
空間マップは、Block 4・8・12・16・20をstep 0・5・10・20・29で切り出し、パネルごとにそのパネルの最大値で正規化した(パネル間で明るさは比較できない。形だけを確かめる図)。



blonde の図では、Block 4がstep 5以降で左の人物の髪の形に沿って明るくなり、Block 8もstep 5以降は左の人物の輪郭が出た。Block 12と16は少数の点に重みが集中していて面としての形が出ず、Block 20は格子全体がほぼ平らだった。
Block 4の左半分比率は0.6前後で表の上では偏りが小さいが、空間マップでは左の人物の髪の形が出ている。右の人物側にも薄く重みが広がっていて、その分だけ比率が下がっている。
Block 12・16の点状の集中が何のトークン位置なのかは、この図からは分からない。
E2 残差ストリームの差分
同じseed 42でAとBを生成し、全Blockの出力(残差ストリーム、形は 1×52×76×2048)をstep 0・1・2・5・10・15・20・29でfp32のまま保存した。1回あたり6.8GB。
AとBの同じstep・同じBlockの出力を引き、トークンごとのL2ノルムを取って52×76の格子に戻した。
step 0は初期の潜在表現が同じなので、差はconditioningの違いだけから生じる。step 1以降は潜在表現の軌道も分かれ、差にはそれも混ざっていた。



step 0のトークン平均L2はBlockが深くなるほど増えた。
| Block | step 0のL2平均 |
|---|---|
| 0 | 0.08 |
| 1 | 18 |
| 4 | 27 |
| 8 | 56 |
| 9 | 116 |
| 12 | 330 |
| 16 | 542 |
| 20 | 546 |
| 24 | 613 |
| 27 | 1416 |
Block 0の出力はAとBでほぼ同じで、Block 1で一気に18まで上がった。Block 11から12で170から330へ、Block 26から27で946から1416へ急に上がった。
ただし残差ストリーム自体の大きさもBlockごとに違うはずで、ここでは差の絶対値だけを出している。
空間マップでは、step 0のBlock 0〜8の差は格子全体に散ったノイズ状で形が出ておらず、Block 24と27は同じstep 0でもすでに2人の頭の位置に2つの塊が出ていた。
step 1〜2になるとBlock 0〜8でも2人の頭の位置に塊が出て、step 5以降は2人の髪と輪郭の形がそのまま差になった。
どのBlock・どのstepでも差は左右両方の人物に出ていて、片側にだけ差が集まるパネルはなかった。AとBは左右両方の髪色を入れ替えているので、差は入れ替えの内容どおりに両側へ出た。
Block 12・16・20では、格子の上端付近の数トークンだけが10万〜20万の値を持ち、残りは真っ暗になった。ハーネスの確認でfp16の範囲を超えた要素があったのはこのトークンで、ComfyUIが残差ストリームをfp32で保持している理由もここにあると思われる。
左右非対称度は「左半分の平均 − 右半分の平均」を全体平均で割った値で、どのBlock・stepでも±0.4の範囲になった。
step 0のBlock 9が−0.38で右寄り、step 5〜20のBlock 12〜20が−0.16〜−0.37で右寄り、step 2の同じBlock範囲は+0.11〜+0.22で左寄り、step 29はどこもほぼ0だった。
Block 12〜20の値には上で書いた上端の外れ値トークンも含まれている。
どのBlockで束縛が決まるかは差分だけでは分からないので、E3で差し替えて確かめた。
E3 conditioningの差し替え
Aで生成しながら、指定した範囲のcross-attentionだけBのconditioningに差し替えた。seed 42、cond側だけ。
差し替えが全Block・全stepなら素のBとbit単位で一致することはハーネスの動作確認で確かめた。
判定は画像を1枚ずつ開いて髪色の配置を見たままで書き、補助として素のA(E0のseed 42)と素のBに対する平均絶対画素差(RGB、0〜255)を付けた。素Aと素Bの間の画素差は65.49。
E3a Block軸
step 0〜29の全部で、Block群だけを差し替えた。
| 差し替え範囲 | 髪色の配置 | 髪色以外の変化 | 素Aとの画素差 | 素Bとの画素差 |
|---|---|---|---|---|
| Block 0〜3 | Aのまま | 両者の目が黒くなった(Aの左は青緑、右は茶) | 5.98 | 65.14 |
| Block 4〜7 | Aのまま | 襟元が縦リブのボタン付き立ち襟に変わり、顔が面長になった | 11.70 | 62.52 |
| Block 8〜11 | Aのまま | 顔の寄りが強くなり目が大きな黒目、左のトップスが薄紫のボタンシャツ | 17.04 | 62.49 |
| Block 12〜15 | Bに反転 | 二人とも黒のノースリーブタートルネックで肩出し、右の髪が短いボブ、上半身の寄り構図 | 59.04 | 38.06 |
| Block 16〜19 | Aのまま | 襟がフリルからバックル付きの詰襟に変わった | 6.48 | 64.28 |
| Block 20〜23 | Aのまま | 襟元に金具のディテールが加わった | 4.23 | 65.87 |
| Block 24〜27 | Aのまま | ほぼ同じ | 3.11 | 65.63 |
| Block 0〜13 | Aのまま | 二人ともノースリーブのリブタートルネックで肩出し、右の髪が肩までのボブ、左のトップスは灰紫、寄り構図 | 30.76 | 59.40 |
| Block 14〜27 | Bに反転 | 二人とも黒のノースリーブタートルネックで肩出し、右の髪が短いボブ、寄り構図 | 59.77 | 38.35 |









Block 12〜15とBlock 14〜27の2つで髪色の配置が反転した。どちらも画素差が素Aから59、素Bへ38で、AでもBでもない別の絵になっている。反転した2枚は服・髪型・構図の変わり方も同じ。
Block 0〜13の差し替えは反転しなかったが、服と構図は反転した2枚と同じように変わった(画素差30.76)。
Block 12〜13を含んで反転しなかったのはこの1枚だけなので、Block 12〜15の4つのうち14〜15を含むかどうかが分かれ目っぽい。ただBlock群の切り方が2通りしかなく、Block 14〜15だけの差し替えは試していない。
Block 0〜3、16〜19、20〜23、24〜27の差し替えは髪色の配置を変えず、画素差も3〜6程度。目の色や襟の飾りといった細部だけが変わった。
Block 4〜7と8〜11は画素差が12〜17で、顔の寄り方やトップスが変わったが髪色の配置はAのまま。
E1で左右の偏りが最も強かったのはBlock 8〜16で、E3aではそのうちBlock 12〜15を差し替えたときに反転した。
E1の偏りが強いBlock 8〜11を差し替えても反転しなかったので、cross-attentionの偏りの強さと、そのBlockを差し替えたときに髪色が入れ替わるかどうかは、この実験では一致していない。
E3b step軸
全Blockで、step範囲だけを差し替えた。
| 差し替え範囲 | 髪色の配置 | 髪色以外の変化 | 素Aとの画素差 | 素Bとの画素差 |
|---|---|---|---|---|
| step 0〜4 | Bに反転 | Bと同じ平面的な線画、茶のカーディガン+薄紫のフリル襟、右の目は灰色。Bより肩の写る範囲がやや広い | 65.34 | 10.11 |
| step 5〜9 | Aのまま | 襟がバックル付きの詰襟に変わった | 5.77 | 66.15 |
| step 10〜19 | Aのまま | ほぼ同じ | 2.23 | 65.56 |
| step 20〜29 | Aのまま | ほぼ同じ | 0.75 | 65.46 |
| step 0〜9 | Bに反転 | 素Bとほぼ同一 | 65.60 | 1.90 |
| step 10〜29 | Aのまま | ほぼ同じ | 2.29 | 65.55 |






step 0〜4だけBにすると、髪色の配置も服も線画の質感も素Bに寄った(素Bとの画素差10.11)。step 0〜9なら素Bとほぼ同一(1.90)。
逆にstep 5〜9、10〜19、20〜29、10〜29のどれを差し替えても素Aとほぼ同じで、step 5〜9で襟が変わった以外は画素差3以下。
step 5〜9はstep 0〜4と同じ長さなのに、結果は素Aのままだった。
E1で測った、cross-attentionの偏りがstepとともに弱まって後半stepでは髪色の単語をほとんど参照しなくなる傾向とは合っている。ただE1の偏りは最終stepでも0.5まで下がりきっていなかったので、後半stepの参照が完全にゼロというわけでもない。
E4 self-attentionの左右遮断
E0で髪色の束縛が崩れたseedがなかったので、まず髪色に服の色を足したプロンプトCで、素のまま3seed生成した。
| 記号 | プロンプト |
|---|---|
| C | 2girls, standing side by side, upper body, looking at viewer, simple background. The girl on the left has blonde hair and wears a red dress. The girl on the right has black hair and wears a blue dress. |
| seed | 人数 | 左の髪色 | 左の服色 | 右の髪色 | 右の服色 | 一致数 |
|---|---|---|---|---|---|---|
| 42 | 2 | 金 | 赤 | 黒 | 紺 | 4/4 |
| 43 | 2 | 金 | 赤 | 黒 | 青 | 4/4 |
| 44 | 2 | 金 | 赤 | 黒 | 青 | 4/4 |



3枚とも4項目すべて指示どおり。seed 42の右の服は青というより紺だが、青系として一致に入れた。
この条件でも崩れず、遮断で束縛が改善するかは比較しようがない。
それでも遮断を入れると絵がどう変わるか自体は分かるので、同じ3seedでself-attentionのマスクを入れてみた。
マスクは画像トークンのself-attentionで左右のトークンが同じ側だけを参照する形にし、cross-attentionとMLPは変更していない。実装は検証環境に書いた左右分割のattentionのまま。
6枚とも最左の人物は金髪に赤い服、最右の人物は黒髪で、最右の服色だけ紺と青に分かれた。
| マスク範囲 | seed | 人数 | 最右の服色 | 素との違い | 素との画素差 |
|---|---|---|---|---|---|
| 全Block | 42 | 4 | 紺 | 画面中央に縦の継ぎ目。左半分は白背景の平塗り線画、右半分は陰影付きの塗り込みで画風が別。左半分の2人は腕・胴が白く塗り残され、腕が途中で消える | 86.75 |
| 全Block | 43 | 4 | 紺 | 中央に縦の継ぎ目。左半分は陰影付き、右半分は平塗り。右半分の2人は腕がなく胴のシルエットのみで、首が細く体と繋がっていない | 99.88 |
| 全Block | 44 | 4 | 紺 | 中央に縦の継ぎ目。左半分は白背景、右半分はグレー背景・太線の別画風。右半分の右の人物は髪が黒に青緑が混ざる | 88.94 |
| Block 8〜16 | 42 | 4 | 青 | 継ぎ目なしで画風は連続。人物が2人から4人に増え、金髪+赤と黒髪+青のペアが2回繰り返される | 78.25 |
| Block 8〜16 | 43 | 4 | 青 | 継ぎ目なし。4人で同じペアが2回。左から2人目の胸元が肌色のまま服に繋がっていない | 79.19 |
| Block 8〜16 | 44 | 3 | 青 | 継ぎ目なし。3人で、中央の人物は前髪が金・後頭部が黒に分かれ、服は青 | 71.60 |






全Blockで遮断すると、3枚とも画面中央に縦の継ぎ目が入って、左半分と右半分がそれぞれ独立した1枚の絵になった。
各半分の中に金髪+赤と黒髪+青の2人組が両方描かれて、合計4人。左右で画風も背景の明るさも違う。
左半分と右半分が互いを参照できないと、それぞれの半分がプロンプト全体を単独で描くらしい。
Block 8〜16だけの遮断では継ぎ目は消えて画風も1枚として連続したが、人数は4人・4人・3人に増えた。seed 44では髪が金と黒に分かれた人物が1人出ている。
E5 トークン単位の書き換え
E3の差し替えはconditioning全体を替えたので、髪色以外も変わっていた。
そこでconditioningのうち blonde(位置25)と black(位置34)のトークンベクトルだけを別プロンプトのものに差し替えた。入れ替えのBに加えて、左を赤髪にしたRも用意した。
| 記号 | プロンプト | 差し替え元の位置 |
|---|---|---|
| B | Aの左右の髪色を入れ替えたもの | 位置25=black、位置34=blonde |
| R | Aの blonde を red にしたもの(The girl on the left has red hair.) | 位置25=red |
| 番号 | 差し替え元 | 差し替える位置 | 範囲 |
|---|---|---|---|
| E5-1 | B | 25と34 | 全Block・全step |
| E5-2 | B | 25と34 | Block 12〜15・全step |
| E5-3 | B | 25と34 | 全Block・step 0〜4 |
| E5-4 | R | 25 | 全Block・全step |
| E5-5 | R | 25 | Block 12〜15・全step |
| E5-6 | R | 25 | 全Block・step 0〜4 |
seed 42、その他はE0と同条件。比較用にRを素のまま生成した1枚も加えた。
A・B・RはT5トークン化すると38トークンで完全に整列していて、位置25はそれぞれ blonde・black・red、位置34はそれぞれ black・blonde・black だった。
差し替えはE3と同じ段階(DiT Blockのcross-attentionに届く 1×512×1024 のconditioning)で、指定した行だけを置き換える。
全512位置を指定するとE3の全体差し替えとbit単位で一致した。
| 番号 | 元 | 位置 | 範囲 | 左の髪色 | 右の髪色 | 一番近い基準 | 髪色以外の変化(素A比) |
|---|---|---|---|---|---|---|---|
| E5-1 | B | 25と34 | 全Block・全step | black | blonde | 素B | 襟が薄紫のフリル高襟、茶のボタン付き上着、目の色も線の濃さも素B |
| E5-2 | B | 25と34 | Block 12〜15 | black | blonde(ボブ) | 素A(画風・構図・肌)。服は別 | 黒のノースリーブのリブタートルネックで肩と腕が露出、フリル襟なし、右がボブ |
| E5-3 | B | 25と34 | step 0〜4 | black | blonde | 素B | 素Bとほぼ同じ。右の髪が素Bより少し長い |
| E5-4 | R | 25 | 全Block・全step | red | black(ボブ) | 素R | 肌がグレー、赤・黒・白だけの高コントラストな画風、赤と黒のハイネック。素Rとの画素差4.3 |
| E5-5 | R | 25 | Block 12〜15 | オレンジ寄りの明るい茶 | black | 素A(画風・構図・肌)。服は別 | くすんだピンクと黒のボタン付きハイネック、フリル襟なし、目は茶〜黒。素Rとの画素差39.7 |
| E5-6 | R | 25 | step 0〜4 | red | black(ボブ) | 素R | 素Rとほぼ同じ(画素差5.4)。左の首元に紫と茶の色斑 |
| 素R | なし | なし | なし | red | black(ボブ) | (基準) | 肌がグレー、赤・黒・白の高コントラスト、赤と黒のハイネック |
| 番号 | 素A全体 | 左上 | 右上 | 左下 | 右下 | 素B全体 |
|---|---|---|---|---|---|---|
| E5-1 | 64.3 | 64.7 | 65.6 | 69.0 | 58.0 | 9.5 |
| E5-2 | 57.7 | 48.9 | 55.5 | 77.6 | 48.8 | 39.5 |
| E5-3 | 64.2 | 64.3 | 65.7 | 68.8 | 57.9 | 12.3 |
| E5-4 | 48.3 | 48.9 | 25.1 | 76.5 | 42.5 | 65.6 |
| E5-5 | 18.7 | 17.3 | 12.3 | 32.7 | 12.4 | 57.7 |
| E5-6 | 47.6 | 48.7 | 25.0 | 73.7 | 43.2 | 66.0 |
| 素R | 47.7 | 49.1 | 25.7 | 76.0 | 39.9 | 65.9 |
画素差は素Aとの平均絶対差(RGB、0〜255)で、4象限は画面を縦横に2分割したもの。上段に髪、下段に服が入る。







2トークンだけをBに替えて全Block・全stepで差し替えると、絵全体が素Bになった(素Bとの画素差9.5)。step 0〜4だけでも同じ(12.3)。seed 42では、AとBの絵の違いは512トークンのうちこの2つのベクトルでほぼ決まっていた。
位置を絞っても範囲を全部にすると元の絵Aは残らず、髪色以外の服も襟も線の質感も一緒にBのものに変わった。
Block 12〜15だけに絞ると、髪色は元に従って変わり(Bなら反転、Rならオレンジ寄り)、顔・構図・画風は素Aのまま残った。素Aとの画素差はRで18.7、4象限では髪のある上段が17と12、服のある左下が33。
ただしその服は素AでもBでもRでもない。3本のBlock 12〜15差し替え(E3aのconditioning全体、E5-2、E5-5)はどれもフリル襟が消えてタートルネックかハイネックになった。
Rの位置25を全Blockで差し替えると素Rとほぼ同じ(4.3)で、こちらは髪だけでなく肌がグレーになって画風が赤黒白の高コントラストに変わった。red の1トークンが画面全体の色設計を変えているようだ。
Block 12〜15限定のRでは、髪は鮮やかな赤にはならず、オレンジ寄りの明るい茶どまり。
E6 単独Block・混合比・空間制限
E5でBlockとstepのどちらで区切っても髪色だけを切り出せなかったので、残りの条件を試した。
| 番号 | 軸 | 内容 | 本数 |
|---|---|---|---|
| E6-a | 単独Block | Rの位置25、Bの位置25と34を、Block 12・13・14・15の1つずつに入れる | 8 |
| E6-b | 混合比 | Rの位置25を全Block・全stepに、元ベクトルとの混合比0.25と0.5で入れる | 2 |
| E6-c | 空間制限 | 差し替えたトークンを、指定した画像トークン領域のcross-attentionにだけ効かせる。領域外は元のconditioningで計算した出力を使う | 4 |
E6-cの領域は52×76のトークン格子で決める。「左半分」は列0〜37、「左上」は列0〜37かつ行0〜29(E1の空間マップで左の人物の髪が入る範囲)。
| 番号 | 元 | 位置と領域 | 範囲 |
|---|---|---|---|
| E6-c1 | R | 25を左半分 | 全Block・全step |
| E6-c2 | R | 25を左上 | 全Block・全step |
| E6-c3 | R | 25を左半分 | Block 12〜15 |
| E6-c4 | B | 25を左半分、34を右半分 | 全Block・全step |
seed 42、その他はE0と同条件。判定と画素差の出し方はE5と同じで、素R(E5の基準)との全体差も加えた。
空間制限の実装は、領域付きトークンがあるBlock・stepでcross-attentionを2回計算し、差し替えなしのconditioningで出した出力と差し替えありの出力を、画像トークンが領域に入るかどうかで選ぶ形。
領域外のトークンは差し替えなしの出力をそのまま使う。self-attentionとMLPは変更していない。
混合比1.0と0.0はそれぞれ従来の差し替えと素Aにbit単位で一致した。
| 番号 | 差し替え | 範囲 | 左の髪色 | 右の髪色 | 一番近い基準 | 髪色以外の変化(素A比) |
|---|---|---|---|---|---|---|
| E6-a | R 25 | Block 12 | blonde(やや黄土寄り) | black | 素A | 目が茶褐色に、襟が縦リブのハイネック+ボタン列(両名同型) |
| E6-a | R 25 | Block 13 | blonde | black | 素A | 目はそのまま。襟がボタン留めのスタンドカラー(両名同型) |
| E6-a | R 25 | Block 14 | blonde(オレンジ寄りの黄色) | black | 素A | 目が茶褐色、襟が縦リブのハイネック+ボタン列、右の人物が左に寄って肩が接触 |
| E6-a | R 25 | Block 15 | blonde | black | 素A | 目はそのまま。襟がボタン留めのスタンドカラー |
| E6-a | B 25,34 | Block 12 | blonde | black | 素A | 目が黒に、左の服が白〜灰の縦ストライプ+グレーのフリル襟 |
| E6-a | B 25,34 | Block 13 | blonde | black | 素A | ほぼ同じ |
| E6-a | B 25,34 | Block 14 | blonde(くすんだ薄黄) | black | 素A | 目が黒褐色、左の服が灰紫の縦リブ+ボタン列、右の人物が左に寄り肩が接触 |
| E6-a | B 25,34 | Block 15 | blonde | black | 素A | 目が黒に。服はほぼ同じ |
| E6-b | R 25、混合比0.25 | 全Block・全step | blonde(オレンジ寄りの黄色) | black | 素A | 目が茶褐色、襟がハイネック+ボタン列、右の人物が左に寄る |
| E6-b | R 25、混合比0.5 | 全Block・全step | オレンジ(blondeとredの間) | black | 構図は素A、服と塗りは素R寄り | 左が赤・右が黒のハイネック、肌がくすんだ灰褐色、線が太くフラット塗り |
| E6-c1 | R 25を左半分 | 全Block・全step | red | black | 素R | 全面が別画風。肌がグレー、赤黒白の高コントラスト、右がボブ |
| E6-c2 | R 25を左上 | 全Block・全step | red | black | 素R | 全面が別画風。左は赤のVネック、右は太いリブのタートルネック、右がボブ、線が荒い |
| E6-c3 | R 25を左半分 | Block 12〜15 | オレンジ(明るい橙) | black | 素A | 目が茶褐色、左が薄赤茶・右が黒のハイネック+ボタン列、右の人物が左に寄る |
| E6-c4 | B 25を左半分、34を右半分 | 全Block・全step | black | blonde | 素B | 全面が別画風。ベタ塗りと太い黒線、茶カーディガン+薄紫フリル襟、右がボブ |
| 番号 | 素A全体 | 左上 | 右上 | 左下 | 右下 | 素B全体 | 素R全体 |
|---|---|---|---|---|---|---|---|
| E6-a R 25 Block 12 | 12.3 | 8.7 | 11.0 | 18.3 | 11.2 | 63.1 | 44.4 |
| E6-a R 25 Block 13 | 5.1 | 4.5 | 2.9 | 9.5 | 3.7 | 65.7 | 47.3 |
| E6-a R 25 Block 14 | 14.9 | 13.8 | 11.0 | 23.3 | 11.7 | 59.8 | 41.3 |
| E6-a R 25 Block 15 | 4.0 | 2.9 | 2.0 | 7.9 | 3.4 | 66.0 | 47.4 |
| E6-a B 25,34 Block 12 | 9.4 | 6.1 | 9.1 | 11.8 | 10.5 | 65.2 | 44.9 |
| E6-a B 25,34 Block 13 | 3.2 | 1.7 | 3.3 | 5.6 | 2.4 | 65.7 | 47.2 |
| E6-a B 25,34 Block 14 | 17.0 | 12.4 | 13.6 | 29.4 | 12.6 | 58.9 | 45.2 |
| E6-a B 25,34 Block 15 | 6.0 | 4.2 | 5.5 | 8.5 | 6.0 | 65.3 | 45.9 |
| E6-b 混合比0.25 | 14.6 | 10.9 | 12.1 | 23.3 | 12.1 | 61.6 | 41.7 |
| E6-b 混合比0.5 | 26.9 | 26.5 | 15.2 | 49.6 | 16.1 | 57.8 | 33.2 |
| E6-c1 | 47.2 | 48.4 | 24.8 | 75.3 | 40.5 | 65.7 | 5.6 |
| E6-c2 | 39.7 | 46.6 | 23.0 | 60.3 | 29.0 | 59.7 | 25.2 |
| E6-c3 | 18.6 | 17.4 | 12.3 | 32.3 | 12.4 | 57.8 | 39.7 |
| E6-c4 | 70.1 | 67.8 | 71.7 | 71.6 | 69.3 | 18.1 | 69.7 |














単独Block(E6-a)では、4つのどれを差し替えても髪色の配置は反転せず、赤にもならなかった。Block 13と15は画素差3〜6でほぼ素Aのまま、Block 12と14は目の色と襟が変わった。E3aとE5で反転したBlock 12〜15は、4つ全部を差し替えないと反転しない範囲だった。
混合比(E6-b)では色が連続的に変わり、0.25でオレンジ寄りの黄色、0.5で赤みの強いオレンジになって、顔と構図は素Aのままだった。ただし0.5では服の色も肌の塗りも素R寄りに変わっていて、髪だけが変わる段階はなかった。
空間制限(E6-c)では髪色だけを切り出せなかった。位置25を左半分の画像トークンにだけ参照させても、絵全体が素Rになった(素Rとの画素差5.6)。左上だけに絞っても素R側(25.2)。Block 12〜15に限定したものは、領域なしのE5-5と画素差18.6対18.7でほぼ同じ絵になった。
cross-attentionの出力を領域外でそのままにしても、そのBlockのself-attentionとMLP、次のBlock以降を通って全体へ広がっていた。E4で確かめた左右のトークンが互いを参照する動きが、ここでは差し替えの影響を全体へ広げている。
髪色のトークンを差し替えた画像では、素Aで左右非対称だった襟(左が淡いピンクのフリル、右が黒のフリル)が、左右で同じハイネック+ボタン列に毎回置き換わった。E5でも同じで、Block 12〜15を経由する差し替えに共通している。
Block、step、空間、混合比の4つを試して、元の絵を残したまま髪色だけを書き換える条件はこのハーネスの範囲では見つからなかった。
反転が起きるBlock 12〜15を通す差し替えでは服が必ず一緒に変わり、空間で切ってもself-attentionが全体へ広げていた。髪色のトークンがそこで服の情報と一緒に扱われているのだと思う。
切るならcross-attentionだけでなくself-attentionも同時に領域で切ることになるが、E4ではそれをすると絵が左右2枚に分かれた。
E7 残差ストリームを直接書き換える
conditioningを替えると服まで一緒に変わったので、conditioningは一切変更せず、DiTの中の残差を直接書き換える側に移った。
論文は隠れ状態を役割と内容に分けて、内容だけを書き換えていた。画像側ではBlock出力の隠れ状態から左の人物の髪色の方向を取り出して、髪のトークンにだけ足した。
方向の作り方は、同じseedでAとRを回して、各Block・各stepの出力を保存し、髪マスク内のトークンで R − A を取る。
髪マスクは素A(seed 42)の画像から金髪の画素を色でしきい値処理して52×76の格子単位にまとめたもの。
足し方は2通りで、領域内の平均ベクトルを1本足す「平均方向」と、トークンごとの差をそのまま足す「トークン別」。
| 番号 | 方向 | 足すBlock | 領域 | 係数 | 足し方 |
|---|---|---|---|---|---|
| E7-1 | R − A | 12〜15 | 左の髪 | 1.0 | 平均方向 |
| E7-2 | R − A | 12〜15 | 左上(列0〜37、行0〜29) | 1.0 | 平均方向 |
| E7-3 | R − A | 8〜19 | 左の髪 | 1.0 | 平均方向 |
| E7-4 | R − A | 12〜15 | 左の髪 | 2.0 | 平均方向 |
| E7-5 | R − A | 12〜15 | 左の髪 | 1.0 | トークン別 |
| E7-6 | R − A | 12〜15 | 右の髪(左の髪領域を左右反転) | 1.0 | 平均方向 |
| E7-7 | B − A | 12〜15 | 左の髪 | 1.0 | 平均方向 |
E7-6は対照で、左の人物用の方向を右の人物の髪に足したときに右が赤くなるかを確かめる。
seed 42、全step、cond側だけ、その他はE0と同条件。判定と画素差の出し方はE5と同じで、髪マスクの内側と外側でも分けた。
最初の7本で加算が飽和したので、係数0.1と0.3、差ベクトルの絶対値が大きい上位20次元を0にしたもの、その両方を組み合わせたものを追加した。
| 番号 | 方向 | Block | 領域 | 係数 | 次元の除外 |
|---|---|---|---|---|---|
| E7-8 | R − A | 12〜15 | 左の髪 | 0.1 | なし |
| E7-9 | R − A | 12〜15 | 左の髪 | 0.3 | なし |
| E7-10 | R − A | 12〜15 | 左の髪 | 1.0 | 上位20次元を0 |
| E7-11 | R − A | 12〜15 | 左の髪 | 0.1 | 上位20次元を0 |
| E7-12 | R − A | 12〜15 | 左の髪 | 0.3 | 上位20次元を0 |
| E7-13 | R − A | 12〜15 | 左の髪 | 0.05 | 上位20次元を0 |
| E7-14 | R − A | 12〜15 | 左の髪 | 0.1 | 上位102次元(5%)を0 |
E7の髪マスクと差ベクトルの大きさ
素Aの左半分から金髪の画素(R>150、G>110、B<140、R−B>40)を取り、16×16画素ごとに25%以上なら髪トークンとした。3952トークン中562個で、行4〜51、列10〜32の範囲にある。襟のフリル上部にも数トークン入っている。

残差はA・R・BをBlock 8〜19・全30 stepでfp32で保存し直した(1本11.7GB)。
表は髪マスク内の平均ベクトルのノルムと、同じ領域の残差ノルムの平均。
| Block | step | 差ベクトルのノルム | 残差ノルム | 比 | 上位20次元がノルムに占める割合 |
|---|---|---|---|---|---|
| 12 | 0 | 80 | 9706 | 0.008 | 0.80 |
| 12 | 15 | 1494 | 8790 | 0.170 | 0.80 |
| 13 | 0 | 76 | 9781 | 0.008 | 0.70 |
| 13 | 15 | 1496 | 9125 | 0.164 | 0.79 |
| 14 | 0 | 103 | 10646 | 0.010 | 0.71 |
| 14 | 15 | 1619 | 9935 | 0.163 | 0.83 |
| 15 | 0 | 156 | 10892 | 0.014 | 0.84 |
| 15 | 15 | 1527 | 10800 | 0.141 | 0.79 |
step 15の差ベクトルはstep 0の約19倍あり、残差の14〜17%の大きさだった。
そのノルムの7〜8割が2048次元中の20次元に集中していて、差ベクトルは方向というより少数の次元の大きさで決まっている。この20次元がE2で見つけた巨大値のトークンの次元と同じかどうかは確かめていない。前半の単色実験S2では、色の差が集中する20次元は巨大値の次元とほぼ重ならなかった。
上位20次元を0にするとノルムは0.55〜0.71倍になった。
E7の結果
| 番号 | 方向 | Block | 領域 | 係数 | 次元の除外 | 左の人物 | 右の人物 | マスクの形が出るか |
|---|---|---|---|---|---|---|---|---|
| E7-1 | R−A 平均 | 12〜15 | 左の髪 | 1.0 | なし | 髪のあった場所が白の塊で埋まり、縁と内部に赤のブロック。顔は灰色でぼやけ目鼻が判別できない | ボブ丈、肌は灰色、黒のハイネック | 出る |
| E7-2 | R−A 平均 | 12〜15 | 左上 | 1.0 | なし | 頭部が単色オレンジの矩形で覆われ髪が見えない。服はピンク | ボブ丈、肌は灰色、黒のハイネック | 出る |
| E7-3 | R−A 平均 | 8〜19 | 左の髪 | 1.0 | なし | 髪のあった場所が水色のブロック塊。顔は隠れる。画面全体がピンクのノイズ | 髪がこげ茶、うねりのある中程度の長さ、顔に赤の斑点 | 出る |
| E7-4 | R−A 平均 | 12〜15 | 左の髪 | 2.0 | なし | 髪のあった場所が水色のブロック塊。全体がピンクのノイズ | 髪が灰茶、顔に赤とピンクの斑点 | 出る |
| E7-5 | R−A トークン別 | 12〜15 | 左の髪 | 1.0 | なし | 髪のあった場所が水色で髪の筋の線だけ残る。顔は水色と赤の縞 | ボブ丈、肌は灰色、黒のハイネック | 出る |
| E7-6 | R−A 平均 | 12〜15 | 右の髪 | 1.0 | なし | 髪は金のまま彩度が上がる。目が茶に、服がサーモン色のハイネック | 髪のあった場所が白と灰の粒状ノイズ、顔は灰色で目鼻がない | 出る |
| E7-7 | B−A 平均 | 12〜15 | 左の髪 | 1.0 | なし | 全面が黒(残差にNaN) | 同左 | ― |
| E7-8 | R−A 平均 | 12〜15 | 左の髪 | 0.1 | なし | 髪が赤〜橙の単色で面塗り、前髪の筋が消える。顔の輪郭と表情は残り、目が暗赤に。服が暗赤のリブハイネック | 長い直毛と前髪は保持、襟元が暗赤、髪の右端に緑の帯 | わずかに出る |
| E7-9 | R−A 平均 | 12〜15 | 左の髪 | 0.3 | なし | 髪が橙〜赤でブロック状の濃淡。顔は灰白の面で目鼻が消える | ボブ丈、肌は灰白 | 出る |
| E7-10 | R−A 平均 | 12〜15 | 左の髪 | 1.0 | 上位20次元を0 | 髪がベージュの網点模様に赤の斑。顔は灰色の面 | ボブ丈、肌は灰白、フリル襟なし | 出る |
| E7-11 | R−A 平均 | 12〜15 | 左の髪 | 0.1 | 上位20次元を0 | 髪がオレンジ〜赤で毛の筋が残る。顔は素Aのまま、目が青緑から茶に。淡いピンクのフリル襟が残り赤みが少し乗る | 長い黒髪、黒のフリル襟つき上着のまま | 上端がわずかに角張る |
| E7-12 | R−A 平均 | 12〜15 | 左の髪 | 0.3 | 上位20次元を0 | 髪が赤の面塗りで縦縞、顔は目鼻の線だけ残り肌が灰白。服も赤の面 | ボブ丈、肌が灰白、黒のハイネック | 出る |
| E7-13 | R−A 平均 | 12〜15 | 左の髪 | 0.05 | 上位20次元を0 | 髪がオレンジで毛の筋が残る。顔は素Aのまま、目が茶に。淡いピンクのフリル襟が残る | 長い黒髪、黒のフリル襟つき上着のまま | 出ない |
| E7-14 | R−A 平均 | 12〜15 | 左の髪 | 0.1 | 上位102次元を0 | 髪は金のまま彩度がわずかに上がる程度。目が黒に。他は素Aとほぼ同じ | 素Aとほぼ同じ | 出ない |
| 番号 | 素A全体 | 左上 | 右上 | 左下 | 右下 | 髪内 | 髪外 | 素R全体 |
|---|---|---|---|---|---|---|---|---|
| E7-1 | 42.6 | 47.1 | 25.3 | 55.4 | 42.7 | 91.5 | 34.5 | 51.2 |
| E7-2 | 52.5 | 52.5 | 45.4 | 64.8 | 47.4 | 43.3 | 54.0 | 55.3 |
| E7-3 | 47.3 | 48.0 | 33.1 | 56.0 | 52.3 | 91.0 | 40.1 | 77.0 |
| E7-4 | 49.3 | 43.6 | 39.9 | 51.8 | 61.8 | 82.5 | 43.7 | 78.7 |
| E7-5 | 42.5 | 44.8 | 29.5 | 51.3 | 44.4 | 83.8 | 35.6 | 48.4 |
| E7-6 | 47.2 | 24.7 | 63.2 | 46.1 | 55.0 | 49.5 | 46.9 | 52.3 |
| E7-7 | 163.8 | 214.0 | 156.1 | 186.2 | 99.1 | 156.3 | 165.1 | 129.4 |
| E7-8 | 38.3 | 48.1 | 17.1 | 70.6 | 17.4 | 104.9 | 27.3 | 26.7 |
| E7-9 | 45.0 | 40.6 | 23.5 | 75.2 | 40.9 | 76.4 | 39.8 | 26.0 |
| E7-10 | 35.2 | 21.8 | 23.0 | 50.1 | 45.8 | 33.9 | 35.4 | 34.1 |
| E7-11 | 31.2 | 40.6 | 15.3 | 53.2 | 15.6 | 93.0 | 20.9 | 31.2 |
| E7-12 | 41.2 | 46.0 | 18.9 | 75.3 | 24.6 | 93.1 | 32.6 | 25.1 |
| E7-13 | 22.3 | 27.1 | 13.4 | 34.9 | 13.7 | 60.1 | 16.0 | 36.8 |
| E7-14 | 8.9 | 9.9 | 6.4 | 13.2 | 6.0 | 23.0 | 6.5 | 43.6 |
画素差は素Aとの平均絶対差(RGB、0〜255)。髪内・髪外は髪マスクを画素へ戻した領域の内外。














係数1.0の平均方向(E7-1)は飽和した。髪マスクの領域が白い塊になり、輪郭にトークン格子のギザギザがそのまま出た。差ベクトルの大部分を占める20次元を髪マスク内の全トークンに足すと残差が発散した。
領域を矩形にする(E7-2)、Blockを広げる(E7-3)、係数を上げる(E7-4)、トークン別にする(E7-5)は、いずれも壊れ方が変わり、髪として描かれたものは1枚もなかった。
右の髪に足す対照(E7-6)は右の髪領域が粒状ノイズになり、左の髪は金のまま彩度が上がった。左用の方向でも右に足せば右が壊れた。
B − A の方向(E7-7)は残差がNaNになり全面黒になった。左右入れ替えの差ベクトルは、色替えの差ベクトルと同じやり方では使えなかった。
係数を0.1に下げる(E7-8)と髪が赤くなり顔の輪郭が残ったが、髪は面塗りで前髪の筋が消え、服は暗赤のハイネックに変わった。
上位20次元を0にしただけ(E7-10)では飽和が別の形の壊れ方(網点模様)に変わった。
上位20次元を0にしたうえで係数0.1(E7-11)で、左の髪だけ赤系になり、顔・襟・右の人物が残った。髪は毛の筋を保ったオレンジ〜赤で、淡いピンクのフリル襟も右の人物の黒髪と黒い上着も残っている。変わった点は左の目の色が茶になったことと、襟に赤みが少し乗ったこと。画素差は素Aから31.2、髪外で20.9、右上と右下は15前後だった。
同じ条件で係数0.3(E7-12)に上げるとまた飽和した。
係数を0.05(E7-13)に下げると、髪はオレンジで毛の筋が残り、顔・襟・右の人物は素Aのままだった。髪外の画素差は16.0、右上と右下は13〜14で、E7-11より素Aからの変化が少なく、髪の色は赤より手前のオレンジで止まった。マスクの形は出ていない。
除外を上位5%(102次元)に広げて係数0.1(E7-14)にすると、髪は金のままで素Aとの画素差が8.9まで下がった。色を変えていた成分は、上位1%より外で5%より内の次元にもあった。
E7-11とE7-13で、残差ストリームを直接書き換えるとconditioning経由では出なかった、左の髪だけ色が変わって顔・襟・右の人物が残る画像が出た。
E5-5(conditioning側でBlock 12〜15に限定)は素Aとの画素差18.7で服が変わっていたが、E7-13は22.3で服が残っている。差が出た場所が違う。
ただ条件はかなり狭い。係数は0.05〜0.1で、0.3だと壊れ、上位20次元の除外がいり、除外を102次元まで広げると色が変わらなくなる。
方向そのものは少数の巨大値の次元が大部分を占めていて、そこを外した残りの成分がようやく色として働くのだと思うが、その残りが髪色だけを表しているかは確かめていない。目の色が茶に変わるのは4条件とも同じで、髪と目が同じ成分で変わっている可能性がある。
単色の色方向と髪色の属性
単色の実験で分かったことを2人並びに戻す。
色はdenoiseのstep 1までに決まる。赤・青・人物の絵で共通だった。赤と青の残差の差は2048次元中の20次元に85〜94%が集中していて、その20次元は残差の巨大値の次元とは別。
Block 24〜27に差を足すと色が変わり、そのうち1つだけ、step 0〜1だけで足りた。中間Block(8〜23)に足すと残差が発散する。最後のBlock群にstep 0〜1で左半分だけ足すと、1画素幅の境界で左が青、右が赤に分かれた。
同じ方向を人物の髪に足すと、髪の形そのままの青い面になって、人物は描き直された。今回単色差から作った方向は、領域を面として塗り直すように働くらしい。
2人並びで髪色が切り出せなかった理由の一部はたぶんここで、残差の中にある色の方向が「この髪を何色にするか」ではなく「この領域を何色の面にするか」だったから。
今回の抽出法では、物体の形を保って髪色だけ変える安定した方向は見つからなかった。E7-11とE7-13は、係数0.05〜0.1と上位20次元の除外という狭い条件で残った2枚。