AIが書いたキャプションの3割が嘘だった──音声つきキャラLoRA改善編、2回の再学習で直したこと・悪化したこと・2倍速くなった学習

テクノロジー

前回、顔も声も存在しない人物を動画AIに覚えさせる話を書きました。LTX-2.3という映像と音声を同時に生成するモデルに、Qwen-Imageで作った顔とQwen3-TTSで設計した声を覚えさせた、あのLoRA(v2)です。記事の最後に「正直、気になっていること」として3つ書きました。肩越しに振り返ってと言っても正面を向く、未学習の台詞を読み間違える、学習が1ステップ14秒と遅い。

公開してから、私自身にもう2つ気になることが湧いてきました。採用した1640ステップは、動きの汎用性を過学習で失っていないか。会社で働く、町で買い物をする、家で料理をする、そういう日常の動作は残っているのか。そしてもう1つ、学習データのキャプションはQwen2.5-VLに書かせたままだったが、Claudeはちゃんとレビューしたのか。そのまま使って大丈夫だったのか。

Claudeに確かめさせたところ、1つ目は半分当たり、2つ目は完全に当たっていました。ここから2回の再学習(v3、v4)が始まります。この記事は、v2の弱点に対して何をして、何が直り、何が悪化したかの記録です。ついでに学習を2倍速くした話も書きます。速くならないと、1日に2回まわせませんので。

まず結果をどうぞ

v2で一番困っていたのは、この人物を出すとカメラが固定になってしまうことでした。v4では、プロンプトのカメラの一文が効きます。同じ場面・同じseedで、その一文だけを変えた2本です。

「static camera, steady framing」と書いた方。カメラは動かず、人物だけが動きます。台詞「今回は、そういう基準でモデルを選びました。」は音声認識で全文一致、声の類似度0.83
「slow dolly-in: the camera pushes forward to a close-up」と書いた方。同じ台詞を喋りながら、部屋の引きから顔の寄りまで、ちゃんと寄ります

比較として、v3の同じプロンプト・同じseed。「寄って」と書いても寄りません。

v3で同じプロンプト・同じseed。台詞は喋りますが、カメラは最初から最後まで同じ画角のまま。これがv2とv3の限界でした

回り込みと後退追従も出るようになりました。

「the camera slowly orbits around her」。友人に話しかけながら、カメラがテーブルの周りをぐるりと回ります。v2では人物が横を向くだけでした
「hand-held tracking shot, the camera moves backward ahead of her」。喋りながら歩く彼女の前を、カメラが下がりながら追います

実はこの記事の下書きでは、台詞を書かずに「speaks to the camera」とだけ書いたカメラ語テストの動画を載せていました。すると、この人物の声で日本語風・英語風の意味のない発話が入り、中には「MZKV」というトリガー語を読み上げているように聞こえる本もあった。LTX-2は映像と音声を同時に生成するので、音声を指定しなければモデルが勝手に埋めます公式のプロンプトガイドが「環境音・音楽・台詞は明示的に書け、台詞は引用符で、言語も指定しろ」と言っているのはそういうことでした。上の動画は台詞を引用符で書いて撮り直したものです。副産物として、カメラ移動は台詞なしのクリップでしか教えていないのに、喋りながらでもカメラが動くことが分かりました。4本とも音声認識で台詞が読み取れ(文字誤り率0〜0.04)、声の類似度は0.78〜0.83です。

もう1つ、v2で正面を向いてしまった「肩越しに振り返る」がこうなりました。

v2。「肩越しに振り返る」と書いても正面を向きます。学習データが全部、正面の会話だったので
v4。背中から、肩越しにこちらを見ます。声と顔は落ちていません

念のため、本業の「喋る」ほうも。

v4で、前回と同じ台詞・同じseed。声の類似度は前回の0.81から0.83へ、わずかに上がっています

v2の弱点を棚卸しする

まず、v2に何が足りなかったのかを整理します。前回の記事で自覚していたものと、公開後の私の疑問から掘り出したものが混ざっています。

弱点症状原因(調べて分かったこと)
正面バイアス横顔・肩越し・全身の遠景を指示しても正面の中景になる学習クリップ41本が全部、正面の会話
固定カメラの焼き付き日常動作のプロンプトで、LoRAなしより動き量が35%減る。どのステップでも同じ学習クリップが全部固定カメラで、キャプションにカメラの記述がない
キャプションの矛盾「口は閉じている」と「唇が動く」が同じキャプションに同居静止画用に書かせた説明文を、動画のキャプションにそのまま流用した
読み間違い未学習の台詞で「今日は」が「急は」ローマ字の長音の解釈
遅い1ステップ14.5秒、2000ステップで8時間ブロックスワップの双方向転送

私の疑問の1つ目、「1640ステップは動きを失っていないか」の答えは、動作そのものはどのステップでも成立しているが、動き量はLoRAを入れた時点で35%減り、その後はステップに依らず一定でした。つまり過学習で失われたのではなく、データ設計の時点で「固定カメラ」がトリガー語に焼き付いていた。前作で服や背景の焼き付きを経験した教訓の、カメラワーク版です。

2つ目の「キャプションはレビューしたのか」は、正直に言うと、していませんでした。眼鏡・髪・年齢の語が混じっていないかを機械検索して、数枚を目で見ただけです。全文を読ませたところ、こうなりました。

種別件数内容
属性の漏れ(眼鏡・髪・年齢)0「書くな」と指示した属性は守られていた
事実の誤り4 / 58目を閉じた画像を「左下を見て歯を見せて微笑む」、全身の遠景を「腰から上」など
意図した変種の未記載3 / 58髪を下ろした3枚に髪の記述がなく、髪型が制御不能なノイズになっていた
定型文の反復約40 / 58「照明は柔らかく均一で…」がほぼ全枚に同文で入る
クリップの自己矛盾29 / 46「口は閉じて一文字」「無表情」と「話している、唇が動く」が同居
v2のクリップキャプション(上)とv3以降(下)。1つの文章の中で口が閉じたまま喋っていました。音声つき学習で、テキストは「口を閉じている」、映像は口が動く、音声は喋っている。それでも声と口パクは成立したのだから、モデルは偉い
v2のクリップキャプション(上)とv3以降(下)。1つの文章の中で口が閉じたまま喋っていました。音声つき学習で、テキストは「口を閉じている」、映像は口が動く、音声は喋っている。それでも声と口パクは成立したのだから、モデルは偉い

視覚言語モデルは「書くな」は守るが、目・口・画角の事実を7%ほど間違える。そして静止画用の文章を動画に転用すると、時間的に成り立たない文が残る。生成後に全文を読む工程を省いてはいけなかった、というのがv3の出発点です。

v3:データだけ直して、3つのうち2つが直った

学習レシピ(rank 32、学習率、fp8、2000ステップ前後)はv2から一切変えず、データとキャプションだけを直しました。差が出たらデータの効果だと言い切るためです。

  • キャプション:静止画の事実誤り4件と髪下ろし3件を手で修正。クリップ用には「口・表情・視線の静的な記述を除去する」モードを作り、全クリップに「Static camera, steady framing.」を明記
  • 非正面データ:横顔・肩越し・後ろ向きから振り向いて話すクリップ4本、三等分の向きで画面外の相手に話すクリップ4本、非正面の静止画13枚(横顔・後ろ姿・全身・遠景)を追加
  • ローマ字:長音の表記をヘボン式(Kyou)・重ね書き(Kyoo)・マクロン(Kyō)で比較。重ね書きは「oo」を英語風に読んで最悪、マクロンは素のモデルでは最良だがLoRAを通すとヘボン式と同点。ヘボン式のままにしました。ついでに、前回の未学習行の読み間違いの一部は「1時間 / 一時間」のような数字表記の差で、実害は見立てより小さいことも分かりました

結果です。

観点v2 (1640)v3 (2144)
声の類似度(平均 / 最低)0.811 / 0.7830.829 / 0.796
顔の一致(12プロンプト)0.8490.853
横顔・肩越し・全身遠景の指示3本とも正面か中景に逸脱3本とも従う
終盤の暗転6本中1本なし
過学習の出方1968ステップ以降で顔が0.77に低下最終2800でも0.84を保つ
日常動作の動き量5.043.08(悪化)
カメラ語の効き+2.53+0.85(悪化)
上から横顔、広い部屋の全身、肩越し。左がv3、右がv2。v2は3本とも正面の中景にしてしまいますが、v3は指示どおり。非正面のデータ21本の効果です
上から横顔、広い部屋の全身、肩越し。左がv3、右がv2。v2は3本とも正面の中景にしてしまいますが、v3は指示どおり。非正面のデータ21本の効果です

正面バイアスは解消し、声と顔は落ちず、過学習も遅くなりました。ところがカメラだけは悪化しました。「カメラ語の効き」というのは、同じ場面・同じseedで「static camera」と書いた場合と「tracking shot / push-in / orbit / hand-held」と書いた場合の動き量の差で、素のモデルは+8.44、v2は+2.53、v3は+0.85。全クリップに「static camera」と書いたのに、書けば書くほど固定が深まった。

理由は考えてみれば当然でした。対照になる「動くカメラ」のサンプルが1本もない。前作で服と背景の焼き付きが解けたのは、服と背景が実際に散らばっていたからです。「書かれていない共通要素はトリガー語に焼き付く」の続きとして、書くだけでは足りず、変化する例が要る。v3の教訓はこれに尽きます。

v4:「話しながらカメラが動く」クリップは作れなかった

なら、カメラが動く学習クリップを作ればいい。ここからが長かった。

学習クリップは、この人物の静止画1枚と台詞の音声をLTX-2.3に渡して口パク動画を作る手順で生成しています。この手順でカメラを動かそうとした結果がこれです。

やり方結果
静止画を種に、プロンプトでカメラ移動を指示歩き 0/4、カメラ移動 0/4。種画像の構図から離れない
種画像なし、音声+テキストのみ(同一性はv2のLoRA)0/8。全部が固定カメラの正面バストショットに収束
CFGを1から3〜5に上げる寄りは動かず、回り込みは人物が横を向くだけ。唯一歩いた1本は顔が別人に
蒸留LoRAを外して30ステップの通常サンプリング同上。蒸留の有無は関係なかった
静止画を種にした生成で「回り込み」「寄り」「後退追従」を指示した結果。上から順に、台詞なし蒸留・台詞つき30ステップ。回り込みは人物が横を向いて退場し、寄りは動かず、追従は振り返って歩き去る。カメラだけが頑として動きません
静止画を種にした生成で「回り込み」「寄り」「後退追従」を指示した結果。上から順に、台詞なし蒸留・台詞つき30ステップ。回り込みは人物が横を向いて退場し、寄りは動かず、追従は振り返って歩き去る。カメラだけが頑として動きません

分かったのは、台詞つきの生成は、モデルが「正面の会話」に強く引き寄せられるということです。音声を凍結して口を合わせる方式では、LoRAの有無にかかわらずカメラは動きませんでした。

突破口は、v2の評価で偶然見えていました。日常動作のプローブ(台詞なし)では、LoRA版でもカメラが動いていたのです。そこで発想を変えました。カメラ移動は台詞なしのクリップで教え、声は従来の会話クリップで教える。種画像なしのテキストからの生成に、v3のLoRAを載せて同一性を持たせ、台詞を外します。

種画像なし・台詞なし・v3 LoRA入りの生成。商店街の横追従、書斎の寄り、公園の横追従、広場のクレーンアップ、廊下の後退追従。ようやくカメラが動きました。顔の一致は平均0.78
種画像なし・台詞なし・v3 LoRA入りの生成。商店街の横追従、書斎の寄り、公園の横追従、広場のクレーンアップ、廊下の後退追従。ようやくカメラが動きました。顔の一致は平均0.78

これは自分のLoRAの出力で自分を学習する「自己蒸留」なので、雑に入れると顔が崩れていきます。3つのゲートを作りました。顔の一致(最良フレーム0.72以上、平均0.60以上)、動きの有無(フレーム差分か全体シフト)、そして人物が最後まで画面にいるか。さらに目視。3バッチ55本を生成して20本を採用し、学習前に音声を取り除いて映像だけのサンプルにしました。音声ブランチが「MZKVの音」として環境音を覚えないためです。

第3バッチ16本のゲート結果。REJECTの理由が行頭に出ます。横追従・遠景・後ろ姿はLoRAでも同一性が保てず、顔がレンズを向いたままの中景に絞ると通過率が上がりました
第3バッチ16本のゲート結果。REJECTの理由が行頭に出ます。横追従・遠景・後ろ姿はLoRAでも同一性が保てず、顔がレンズを向いたままの中景に絞ると通過率が上がりました

ゲートにも穴が2つありました。末尾で人物が画面から消えるクリップを、顔の検出率だけでは弾けなかったこと(検査を追加)。そして寄り・引きのズームは、フレーム差分にも位相相関にもほとんど映らず「静止」と誤判定されること(3本を目で救済。次回はスケール変化の指標を足します)。自動検品は、意図した動きが起きたかを測っていなければ、動いていないクリップを通す。v2の「暗転を通した」と同じ穴でした。

最終的なv4のデータは、会話クリップ54本、遠景から歩いて寄りながら話すクリップ2本、台詞なしのカメラ移動クリップ20本、非正面の静止画13枚の89サンプル。カメラ移動は全体の2割です。

v4の結果

カメラ語の効き。v3で+0.85まで落ちたものが、v4で+5.12。素のモデルの6割まで戻りました
カメラ語の効き。v3で+0.85まで落ちたものが、v4で+5.12。素のモデルの6割まで戻りました
観点v3 (2144)v4 (2848)
カメラ語の効き+0.85+5.12
日常動作の動き量3.084.22
声の類似度(平均 / 最低)0.829 / 0.7960.826 / 0.819
顔(声プローブ6本)0.868 / 0.8390.833 / 0.800
顔の一致(12プロンプト)0.8530.856
肩越しに振り返る背中だけ肩越しに目線をくれる
広い部屋の全身(向きの指定なし)3/3 正面1/4 正面(向きを書けば3/3)
v4のカメラ語テスト全8本。奇数行がstatic camera、偶数行が動くカメラの指示、場面とseedは同じ。2行目の後退追従は建物が流れ、4行目は引きから顔の寄りまで、6行目はテーブルを回り込みます
v4のカメラ語テスト全8本。奇数行がstatic camera、偶数行が動くカメラの指示、場面とseedは同じ。2行目の後退追従は建物が流れ、4行目は引きから顔の寄りまで、6行目はテーブルを回り込みます

全体の2割の対照データで、映像側の「固定カメラ」の焼き付きが剥がれました。声は落ちず、最低値はむしろ歴代最高です。v4のステップ2848を新しい既定にしました。

代償も2つあります。顔の一致が0.03ほど下がったこと(自己蒸留のカメラクリップの影響と見ています)。そして、向きを書かずに全身の遠景を出すと、4本中3本が後ろ向きで立つという新しい癖です。振り向きクリップや後ろからの追従クリップの「背中から始まる」構図が漏れたのでしょう。「facing the camera and looking into the lens」と書けば3本中3本が正面を向くので、制御可能な癖として配布用READMEに明記しました。

上3行:向きを書かない全身の遠景。3本中2本が背中を向けて立ちます。下3行:「facing the camera and looking into the lens」を足した同じseed。3本とも正面。癖は消えていませんが、言えば聞きます
上3行:向きを書かない全身の遠景。3本中2本が背中を向けて立ちます。下3行:「facing the camera and looking into the lens」を足した同じseed。3本とも正面。癖は消えていませんが、言えば聞きます

学習を2倍速くした話

前回、1ステップ14.5秒、2000ステップで8時間と書きました。これだとデータを直して結果を見るまでに1日かかり、v3とv4のような反復は回りません。ベンチマークを取りました。

同じ条件(768×448、161フレーム、rank 32、音声つき)で設定だけ変えて12ステップずつ計測。片方向スワップの1本で33%速くなり、それ以上はほぼ伸びません
同じ条件(768×448、161フレーム、rank 32、音声つき)で設定だけ変えて12ステップずつ計測。片方向スワップの1本で33%速くなり、それ以上はほぼ伸びません

効いたのは1つだけで、ブロックスワップを片方向にする設定(--block_swap_h2d_only)でした。ブロックスワップはVRAMに収まらない層をCPU側に退避させる仕組みで、標準ではGPUで計算した層をCPUへ書き戻します。ところがLoRA学習ではベースモデルの重みは凍結されていて変わらない。書き戻しは丸ごと無駄でした。片方向にすると15.3秒が10.3秒。VRAMは変わりません。

面白いのは、片方向にした後は退避する層の数が速度に効かないことです。20層退避しても8層でも0層でも10秒前後。スワップの税金は片方向化でほぼ消え、残りの差は勾配チェックポイントとfp8のオーバーヘッドでした。なので、VRAMに余裕を残せる20層のまま。cuDNNの注意機構を使う設定でさらに3%。KV再計算の抑止やパディング除去、DataLoaderのピン留めは効果なしでVRAMだけ増えたので不採用です。

本番の実測。v2の14.5秒/ステップが、v3で7.3秒、v4で6.4秒に。v4はv2より1200ステップ多く、サンプル数も2倍以上なのに、時間はv2より短い
本番の実測。v2の14.5秒/ステップが、v3で7.3秒、v4で6.4秒に。v4はv2より1200ステップ多く、サンプル数も2倍以上なのに、時間はv2より短い

本番ではv3で7.3秒、v4で6.4秒でした。ベンチより速いのは、クリップが短めなのと、静止画のステップが軽いからです。2000ステップ8時間が、3200ステップ5時間42分になりました。

速度以外で反復を回すために変えたのは、運用のほうです。前回Claudeが落ちたら学習も止まった件は、タスクスケジューラ経由の起動で解決していましたが、今回はさらに、生成・検品・キャッシュ・学習・評価をそれぞれ切り離したプロセスとして起動し、ログの伸びを監視して次に進む形にしました。Claudeの1回のコマンド実行には10分の上限があり、24本の生成やキャッシュ作成はそれを超えます。長い処理は自分のプロセスから切り離して、結果が増えるかで判定する。これでv4は、朝にデータ生成を始めて、昼に学習、夕方に評価と、1日で1周しました。

正直、気になっていること

  • 顔の一致が0.03下がった。自己蒸留のカメラクリップが原因なら、別モデル(Wan2.2-S2V、LTX-2.5)で作るか、顔ゲートをもっと厳しくする手があります。20本のうち顔が小さい場面を減らすだけでも変わるかもしれません
  • 「話しながらカメラが動く」学習クリップは、まだ作れていません。v4のカメラ移動は台詞なしで教えたもので、生成時には喋りながらでも動いてくれましたが、台詞を書かないと無音になったり意味のない発話が入ったりします。台詞つきのカメラ移動クリップを作れる生成手段(LTX-2.5やWan2.2-S2V)ができれば、ここも学習で押さえられるはずです
  • 後ろ向きの癖。向きを書けば従いますが、書き忘れると背中を向けます。正面の全身クリップを足すか、背中から始まるクリップの比率を下げるかで消えるはずです
  • ズームを拾えないゲート、末尾で退場するクリップ。自動検品の穴は塞いだそばから次が出てきます

人間がやったこと、AIに任せたこと

工程人間(私)Claude Code
疑問の提起「1640ステップは動きの汎用性を失っていないか」「キャプションはレビューしたのか」日常動作8種×5ステップの検証、キャプション104本の全文レビュー
v3の設計「次はv3にしよう」修正項目の設計、非正面クリップの生成、ローマ字表記の比較、学習と評価
判断v3 2144を既定にする。切り替え運用は面倒なので、カメラはv4で解決する3経路の下調べと4通りの生成実験
v4の設計──台詞なしT2Vへの方針転換、3段ゲート、55本の生成と20本の選別、学習と評価
判断v4 2848を既定にする──
速度「GPUに遊びがある。公開事例と比べて速くする余地を探せ」7設定のベンチマーク、片方向スワップの発見、運用の切り離し

今回、私の仕事はほぼ「疑問を投げる」と「どちらにするか決める」の2つでした。投げた疑問は2つとも当たっていたのが、人間の側の唯一の手柄です。数値上は合格していたキャプションの矛盾も、ステップとは無関係なカメラの焼き付きも、聞かれなければ調べられていません。AIは聞かれたことには徹底的に答えますが、聞かれていないことを疑うのは、まだ人間の仕事のようです。

まとめ

  • キャプションは生成後に全文を読む。視覚言語モデルは「書くな」は守るが事実を7%間違え、静止画用の文を動画に流用すると時間的に矛盾する。v2はそれで学習していました
  • 焼き付けたくない要素は、書くだけでなく散らす。全クリップに「static camera」と書いても、動くカメラの例がなければ剥がれない。2割の対照データで剥がれた
  • 非正面の静止画は効く。音声なしの静止画を2割混ぜても声は落ちず、向きの指示に従うようになった
  • 台詞つきの生成は正面の会話に収束する。動きの素材は台詞なしで作って、声と分けて教える
  • 自己生成データは顔ゲートと目視を必ず通す。それでも顔は少し下がる
  • LoRA学習のブロックスワップは片方向にする。それだけで33%速くなり、退避する層の数は気にしなくてよくなる
  • 長い処理はAIエージェントのプロセスから切り離し、監視で次に進む。これで1日1周まわる

かくして、この世に存在しない人は、こちらに歩いてきたり、カメラに回り込まれたり、肩越しに振り返ったりできるようになりました。次こそ線画のOYAJIくんです。ここで得た教訓のほとんどは、そのまま持っていけるはずです。動きの素材は台詞なしで作る、自己生成データはゲートを通す、そして書くだけでは焼き付きは剥がれない。

五十路の実験は、まだ続く。

コメント

タイトルとURLをコピーしました