コンテンツにスキップ

ルールエージェントを利用した初期学習

目的

notebooks/rule-ai-agent/ にある rule-based agent を Python module として移植し、CSV 登録した deck と組み合わせて bootstrap 用 self-play JSONL を集める。

このデータは policy/value と belief の両方に使う。rule agent は最終 teacher ではなく、最初に「合法手を選び、盤面を進め、攻撃やサイド取得を経験する」ための補助 teacher として扱う。

実装方針

  • src/pca/rule_agents/base.py
  • BaseRuleAgentRuleDecision を定義する。
  • legalize_selection() で min/max/count を守る。
  • setup active では Basic Pokemon 以外を選ばない safety guard を入れる。

  • src/pca/rule_agents/agents/<agent_id>/

  • agent ごとにディレクトリを分ける。
  • main.py に notebook の %%writefile main.py 相当を移植する。
  • agent.pyBaseRuleAgent / PortedRuleAgent を継承した class を置く。
  • deck.csv にその agent の主 deck を置く。
  • 実行時に notebook を読む方式ではない。
  • 提出形式に近い obs -> selected の構造を保つ。

  • configs/rule_agents.yaml

  • agent class、agent-local の主 deck CSV、互換 deck CSV、archetype、policy weight を登録する。
  • enabled: false の agent は明示的に無効化される。
  • match_weight で self-play に出す頻度を調整できる。0 は完全除外、0.25 は通常の約 1/4、1.0 は通常頻度として扱う。
  • policy_weight_scale で policy imitation の強さを agent ごとに調整できる。
  • train_policy / train_value / train_belief で、その agent の record をどの学習に使うかを個別に制御できる。
  • decks/rule_agents/<agent_id>.csv があれば --rule-deck-dir で追加登録できる。

  • configs/rule/selfplay-rule-bootstrap-500g.yaml

  • rule-agent-deck-pool: true により、configs/rule_agents.yamldeck_csv を両プレイヤーの deck pool として使う。
  • これにより、rule agent と紐づいた deck 同士で bootstrap self-play を集める。
  • self-play 終了時に agent ごとの勝敗、通常勝ち、deck-out、サイド取得、攻撃回数を表示する。
  • agent-summary-output で同じ agent 別集計を CSV に保存する。
  • deck-summary-output で deck ごとの勝率、通常勝ち、deck-out、サイド取得などを CSV に保存する。

JSONLのメタデータ

rule-pool self-play の record には次を保存する。

  • teacher_type: rule_agent
  • teacher_id
  • teacher_main_pokemon
  • teacher_deck_csv
  • teacher_compatibility
  • teacher_policy_weight
  • teacher_policy_weight_scale
  • teacher_match_weight
  • teacher_train_policy
  • teacher_train_value
  • teacher_train_belief
  • teacher_result_side: win|loss|unfinished
  • teacher_source_notebook
  • own_deck_card_ids

学習での扱い

Policy は teacher_policy_weight を掛ける。初期値は次の通り。

  • 勝ち側: 0.40
  • 負け側: 0.15
  • 未完了: 0.10

Value target は下げない。負け record は負けとして、勝ち record は勝ちとして学習する。つまり「負けた側の手を完全に捨てる」のではなく、value では悪い結果として学び、policy imitation では弱く扱う。

Belief は --full-observation-targets で hidden state label を保存し、同じ JSONL から belief_train.py を実行する。

agent ごとの品質差は次の2段階で扱う。

  • enabled: false: agent と deck を完全に self-play pool から外す。明らかに壊れている、または学習に入れたくない agent に使う。
  • match_weight: self-play での出現頻度を下げる。弱いが belief/value 用の局面や負け方として少し残したい agent に使う。match_weight: 0 は完全除外として扱う。
  • policy_weight_scale: policy imitation の重みを倍率で下げる。勝敗による teacher_policy_weight にさらに掛かる。
  • train_policy: false: policy imitation には使わない。value / belief は train_value / train_belief が true なら残す。
  • train_value: false: policy とは別に、勝敗 value の教師からも外す。
  • train_belief: false: hidden state 推定の belief 教師から外す。

低品質な rule agent は、基本的には match_weight を下げ、train_policy: falsetrain_value: truetrain_belief: true とする。これにより「悪い手を真似る」ことは避けつつ、負け局面や hidden state label は学習に残せる。明らかに壊れている agent は enabled: false で完全に外す。

実行例

PYTHONPATH=src uv run python -m pca.training.selfplay \
  --config configs/rule/selfplay-rule-bootstrap-500g.yaml

Model vs Rule の self-play 収集

pca.training.selfplaypolicy0 / policy1 を指定すると、左右で異なる policy を使える。未指定の場合は従来通り policy 1本を両プレイヤーに使う。

v13 model を p0、filtered rule agent pool を p1 にして JSONL を集める場合は次を使う。

PYTHONPATH=src python -m pca.training.selfplay \
  --config configs/v13/selfplay-v13-ismcts-vs-rule.yaml

p0 のデッキは deck0-dir から選ばれ、p1 のデッキは rule-agent-deck-pool1: true により configs/rule_agents_v13_filtered.yaml の有効な deck_csv から選ばれる。逆向きで rule を p0、model を p1 にする場合は次を使う。

PYTHONPATH=src python -m pca.training.selfplay \
  --config configs/v13/selfplay-rule-vs-v13-ismcts.yaml

この形式の JSONL は、model 側 record には model/search の policy target、rule 側 record には teacher_type: rule_agentteacher_policy_weight を保存する。したがって、学習時には rule 側 imitation を弱くしつつ、model 側の search target と同じファイルで混ぜられる。

macOS で CABT libcg.dylib が使える場合は、Docker なしで rule-pool self-play を回せる。

bash scripts/collect_rule_selfplay_local.sh

Docker で CABT 上の rule-pool self-play を回す場合は次を使う。

bash scripts/collect_rule_selfplay_docker.sh

10,000 試合などを chunk 単位で回す場合は、手書きループではなく次を使う。

bash scripts/run_rule_bootstrap_chunks.sh

デフォルトは 500 games x 20 chunks = 10,000 games である。各 chunk は個別 JSONL / summary CSV として保存され、最後に data/selfplay/rule-bootstrap-10k.jsonl へ結合される。デフォルト runtime は互換性のため docker のまま。Mac ローカル実行では --runtime local を付ける。

主な上書き例:

bash scripts/run_rule_bootstrap_chunks.sh \
  --runtime local \
  --chunks 20 \
  --games-per-chunk 500 \
  --workers 8 \
  --resume

-- 以降はそのまま pca.training.selfplay に渡る。

bash scripts/run_rule_bootstrap_chunks.sh \
  --runtime local \
  --run-name rule-bootstrap-10k-v2 \
  --output-dir data/selfplay/rule-bootstrap-10k-v2 \
  --merged-output data/selfplay/rule-bootstrap-10k-v2.jsonl \
  -- --no-color

短い smoke run は次のように上書きする。

bash scripts/collect_rule_selfplay_docker.sh \
  --games 20 \
  --workers 4 \
  --output data/selfplay/rule-bootstrap-smoke.jsonl \
  --deck-summary-output data/selfplay/rule-bootstrap-smoke.deck-summary.csv
PYTHONPATH=src uv run python -m pca.training.belief_train \
  --config configs/rule/train-belief-rule-bootstrap.yaml
PYTHONPATH=src uv run python -m pca.training.train \
  --config configs/rule/train-policy-rule-bootstrap.yaml

10,000 試合 JSONL は大きいため、merged JSONL を一括で読むより chunk ごとに checkpoint を引き継ぐ方が安全である。Belief と Policy/Value を両方学習する場合は次を使う。

bash scripts/train_rule_bootstrap_chunks.sh --resume

デフォルトでは次の順で進む。

  1. rule-bootstrap-10k-part000.jsonl で Belief を学習し、次 chunk の初期値にする。
  2. 同じ chunk で Policy/Value を学習し、次 chunk の初期値にする。
  3. part019 まで繰り返す。
  4. 最後に以下の stable checkpoint 名へコピーする。
checkpoints/belief_rule_bootstrap_10k_best.pt
checkpoints/belief_rule_bootstrap_10k_final.pt
checkpoints/policy_value_rule_bootstrap_10k_best.pt
checkpoints/policy_value_rule_bootstrap_10k_final.pt

短い smoke は次。

bash scripts/train_rule_bootstrap_chunks.sh \
  --chunks 1 \
  --checkpoint-prefix rule_bootstrap_smoke \
  --no-final-aliases

注意点

notebook 由来 agent は特定 deck 前提の実装が多い。相性が低い deck は割り当てない。暗黙の generic_advanced_heuristic fallback は使わないため、互換 deck / archetype / required cards の登録を明示的に整える。