プレイ動画から「次に取る行動」を提案するAI(続編:行動候補UIの安定化と次の一手)
本記事は、以下の Qiita 記事の続編です。
- 前編:行動提案モデルをゼロから作る:batch1 → class-weight までの実験ログ
https://qiita.com/y4o4/items/f9cb895e4e3164a9a9c3
前編では、
- プレイ動画 → 行動候補UI推定 → 行動抽出 → state/role データセット化
- MLP による「次のアクション(role)」予測
- batch1 / batch2 による初期検証
までを整理しました。
本記事では、その後に直面した実務的なボトルネック と、それに対する設計・実装・評価の記録をまとめます。
1. 課題:batch3 で精度が伸びない
新規試合のみからなる batch3 を作成し、既存モデルを評価したところ、次の結果になりました。
- accuracy_top1 ≒ 0.25
- accuracy_top3 ≒ 0.54
batch2 と比較してデータ量を増やしても精度がほとんど伸びない 状況でした。
原因を切り分けるため、まず「モデル」ではなく「入力データ」を疑うことにしました。
2. ボトルネックは「行動候補UI推定の揺れ」だった
行動候補UI 推定ログを詳細に確認すると、
- 本来は常に 固定スロット数(本記事では4) あるはずの行動候補UIが
- フレームによって 3 枚 / 5 枚 / 重複 などに揺れている
という問題が判明しました。
これは、
- 各スロットを独立に分類している
- EMPTY / UNKNOWN / 重複カードが混ざる
という設計によるものでした。
この揺れは、そのまま
- state ベクトルのノイズ
- actions 抽出漏れ
に直結し、下流モデルの学習を不安定にしていました。
3. 解決策:4スロット整合性制約(unique-card enforcement)
発想
「行動候補UIは必ず ACTION_1〜ACTION_8 の中から重複なしで4枚」
という構造的制約を、推論時に明示的に使うことにしました。
実装概要
- 各スロットの softmax 出力(確率)を保持
- 8 枚から 固定スロット数(本記事では4)を割り当てる全探索(8P4 = 1680 通り)
-
sum(log(prob))が最大になる割当を採用 - 異常時は従来挙動にフォールバック
これを --enforce-unique-cards オプションとして実装しました。
さらにデバッグ用途として、
- 各スロットに割り当てられた card_id をそのまま出力する
--emit-slots
も追加しました。
4. PowerShell 運用の改善(regen_one.ps1)
動画1本ごとに
- infer_hand
- extract_actions
- build_state_role_dataset
を回す処理は PowerShell スクリプト(regen_one.ps1)にまとめています。
ここで、
- 追加フラグを安全に渡したい
- クォート崩れを避けたい
という理由から、
-
InferArgsをstring[]として受け取る設計
に変更しました。
これにより、
-InferArgs "--enforce-unique-cards","--emit-slots"
のように、安全に拡張オプションを渡せるようになりました。
5. batch3 を再生成(10Hz + enforced)
上記改善を入れた上で、batch3 を 10fps で再生成しました。
- enforced なし:約 500 件
- enforced + 10fps:約 3155 件
行動候補UIは 100% 常に4枚 になり、actions 抽出数も大幅に増加しました。
6. 再評価結果(正直なところ)
enforced データを用いて、既存モデルを再評価しました。
- accuracy_top1 ≒ 0.246
- accuracy_top3 ≒ 0.542
分かったこと
- データ量・品質は大きく改善した
- しかし 精度はほぼ横ばい
つまり、
問題は「学習が壊れていた」ではなく、「情報が足りない / role が曖昧」
という段階に到達したことが分かりました。
これは失敗ではなく、設計判断を進めるための重要な到達点です。
7. 次の課題:「どこに出すか」をどう扱うか
YouTube 録画ではクリック座標が取れないため、
- 直接回帰
- 教師付き座標学習
は使えません。
そこで次の方針を採ります。
7.1 差分ベースの配置位置推定
- 自分がカードを使った
t_ms前後のフレームを切り出す - before / after の差分を計算
- 新しく出現した局所的な差分から重心を取得
- 盤面をグリッド化して cell_id に量子化
7.2 アクション種別ごとの扱い
- ユニット:差分重心(高精度)
- 建物:差分重心(さらに安定)
- スペル:初期段階では位置ラベル無し
同時に敵がスペルを使った場合などは、
- 広域差分
- 瞬間的ピーク
を検知して 位置ラベルを付けない 方針を取ります。
8. アクション属性をクラスで管理する
位置推定や将来拡張を見据えて、
- ACTION_id
- kind(unit / spell / building)
- 位置ラベリング方針
をまとめた ACTIONSpec を定義する設計にしました。
これにより、
- 「どのアクションに位置ラベルを付けるか」
- 「どの検出器を使うか」
をコード上で一元管理できます。
9. 現在地とロードマップ
現在地
- 行動候補UI推定:安定化完了
- 行動抽出:安定化完了
- 次に出すカード予測:情報不足が判明
次の一手
- 時間文脈を入れた v3 特徴量の検証
- role 定義の再設計(曖昧な role の統合 / 階層化)
- 差分ベースで「どこに出すか」を自動ラベリング
おわりに
ここまで来て分かったのは、
- 精度が伸びない原因を「モデル」ではなく「設計」で説明できる段階に来た
- 評価が信頼できる状態を作ることが、何より重要だった
という点です。