サーバー学習手順¶
更新日: 2026-07-11
この文書は、サーバーまたは長時間実行環境で self-play 収集、Policy/Value 学習、評価前チェックを回すための現行 runbook である。古い version 固有の script ではなく、pca
コマンドと configs/default.yaml を入口にする。
方針¶
現行の標準パイプラインは Belief-Guided Neural ISMCTS self-play -> unified Policy/Value 学習 である。
- self-play は
configs/default.yamlのselfplay-trainに定義された最新 config を使う。 - Policy/Value checkpoint は unified model を前提にし、aux prize heads と integrated belief heads も同じ checkpoint に含める。
- standalone BeliefNet は互換用または個別実験用であり、通常の反復学習では必須ではない。
- 長時間 run は chunk に分け、
--resumeで再開できるようにする。 - 学習後は固定デッキの promotion benchmark を実行する。既定では直前Championとの直接対戦、またはrule-poolの非回帰評価のどちらかを通過したcandidateでlatest aliasを更新する。
前提¶
repo root で実行する。環境は Python 3.12 と uv を前提にする。
uv sync
source .venv/bin/activate
pca commands
direnv を使っている場合は、direnv allow 後に pca をそのまま実行できる。
direnv allow
pca commands
必要な asset の目安:
pokemon-tcg-ai-battle/EN_Card_Data.csv
decks/own/
decks/opponents/
checkpoints/policy_value_latest_best.pt
現在のデフォルトは configs/default.yaml にまとまっている。コマンドごとの実体は次の通り。
| Command | Default |
|---|---|
pca selfplay |
configs/v14/selfplay-gumbel-sh-ismcts.yaml |
pca train |
configs/v13/train-policy-unified-selfplay.yaml |
pca eval |
configs/v14/evaluate-gumbel-sh-vs-rule.yaml |
pca selfplay-train |
scripts/run_selfplay_train.sh |
| 初期 checkpoint | checkpoints/policy_value_latest_best.pt |
| 固定 model deck | configs/benchmarks/model-decks-v1.yaml |
| champion 対戦条件 | configs/benchmarks/evaluate-model-head-to-head.yaml |
標準 self-play は root Gumbel sequential halving、4 determinizations、各120 simulations(1
decision あたり合計480
simulations)を使う。過去runの再現やA/B比較では、v13のvisit設定を明示的に指定する。ローカルCPUではworker間の推論競合を避けるため既定を1
workerとし、GPUサーバーでは --workersを実測に合わせて上書きする。
実行内容だけ確認したい場合は --print-command を使う。
pca --print-command selfplay-train --games 10 --workers 2
推奨する実行単位¶
長時間 self-play は、1つの巨大ファイルを一気に作るのではなく、chunk に分けて実行する。1000 games を 100 games x 10 chunk で収集してから 1 回学習する例:
pca selfplay-train \
--run-name ismcts-selfplay-1000g \
--chunks 10 \
--games-per-chunk 100 \
--workers 8 \
--train-device mps \
--resume
Linux/CUDA サーバーでは --train-device cuda、CPU 検証では --train-device cpu
を使う。self-play は multiprocessing と安定性を優先し、デフォルトで CPU を使う。必要な場合だけ
--selfplay-device を上書きする。
pca selfplay-train \
--run-name cuda-selfplay-1000g \
--chunks 10 \
--games-per-chunk 100 \
--workers 16 \
--train-device cuda \
--resume
反復学習¶
「N 試合 self-play するたびに学習し、その best
checkpoint を次の self-play に使う」場合は、--total-games と --games-per-cycle を使う。
合計 10,000 games を 1,000 games ごとに学習する例:
pca selfplay-train \
--checkpoint checkpoints/policy_value_latest_best.pt \
--run-name ismcts-iterative-10k \
--total-games 10000 \
--games-per-cycle 1000 \
--chunks 10 \
--workers 8 \
--train-device mps \
--resume
この例では、各 cycle が 1,000 games で、--chunks 10 によって 1 cycle が 100 games x 10
chunk に分割される。cycle 1 の学習が終わると、cycle 2 の self-play は cycle 1 の best
checkpoint から始まる。各candidateは同じbenchmarkから二段階で判定する。完了試合勝率52%以上なら正式Champion、50%以上ならTraining
Championとして次cycleのself-playとtrainだけを前進させる。既定のOR判定では、rule-poolの回帰条件だけを満たした場合も正式Championへ昇格する。直接対戦とrule-poolのどちらも満たさない場合にだけ同じdataからretryを学習し、retryも不合格ならseriesを停止する。
学習入力は、直近cycleを全件使用したうえで、過去のpromotion済みcycleを追加する。既定値は次の通り。
recent: 直近のtrain対象gameを100%使用
history: 過去3 promoted cycleからrecent game数の25%を追加
history weights: 最新 / 中間 / 最古 = 50% / 30% / 20%
例えば直近が1,000 gamesなら、過去から最大250 gamesをgame単位で選び、合計1,250 games相当を学習する。試合長によりrecord数の比率は多少変わる。既定では直近gameの5%をvalidationとして分離し、残りのtrain gamesを100%使用する。validationは履歴replayを含まないため、各cycleで新たに生成した対戦への汎化を確認できる。
pca selfplay-train \
--replay-history-cycles 3 \
--replay-history-ratio 0.25 \
--replay-history-weights 0.5,0.3,0.2 \
...
train終了時には logs/selfplay-train/<run-name>-<run-id>.train-metrics.json にfinal/bestのtrain
lossとvalidation lossを保存する。best checkpointは val_loss が最小のepochを選ぶ。
--validation-ratio 0 を指定するとvalidationを無効化できる。
学習の再試行¶
既定profileは--train-attempts 3を使う。状態遷移は次の通り。
- attempt 1をTraining Championから学習し、固定の正式Championに対してpromotionを実行する。
- 直接対戦の正式基準52%、またはrule-poolの非回帰基準を満たせば両Championを更新する。どちらも満たさず、直接対戦の学習継続基準50%だけを満たす場合はTraining Championだけを更新し、retryせず次cycleへ進む。
- 両基準で不合格ならattempt 2と3を、同じtrain/validation splitと同じTraining Championから独立に学習する。
- retry群は
val_loss最小の1候補だけを選び、promotionを一度だけ再実行する。 - 再度両基準で不合格ならaliasを維持し、既定の
--promotion-reject-action stopで次cycleへ進まない。
既定recipeはattempt 2でlearning rateを5e-6へ下げ、attempt 3ではさらに
policy-target-temperature=1.5まで上げてGumbel
targetをsoftenする。全attemptは不合格candidateではなく同じChampionから開始するため、失敗した更新を累積しない。設定は次で上書きできる。
pca selfplay-train \
--train-attempts 3 \
--train-attempt-learning-rates default,0.000005,0.000005 \
--train-attempt-policy-temperatures default,1.25,1.5 \
--promotion-reject-action stop \
...
train-attempts.jsonには全candidateの条件とvalidation
score、選択attemptを保存する。複数candidateを同じpromotion
benchmarkへ順番に当てないため、52%を偶然超えるまで試す選択バイアスを抑えている。
正式昇格またはTraining Champion昇格したcycleだけが data/replay/<run-name>/promoted.yaml
に登録される。両基準で却下されたcycleや、過去sampleを混ぜた出力そのものは登録しない。比較実験で直近だけを使う場合は
--no-replay を指定する。
既定の promotion gate は次を行う。
- 固定7デッキで candidate と直前 champion を同一 deck、同一 seed で対戦する。
- player 0 / player 1 を入れ替え、先後の偏りを相殺する。
- candidate と champion を同じ rule-agent pool に当て、deck ごとの macro win rate を比較する。
- 既定の
--promotion-criteria-mode anyでは、完了試合勝率52%以上、またはrule win rate・unfinished・pokemon-out lossの全回帰条件が許容範囲なら正式昇格する。 - 正式基準をどちらも満たさず、完了試合勝率が50%以上ならTraining Championへ昇格する。
--promotion-criteria-mode allを指定すると、直接対戦とrule-poolの両方を正式昇格とTraining
Champion昇格に必須とする。判定結果はpromotion-benchmark.jsonのpromotion_gateに保存され、
head_to_head_passed、rule_pool_passed、criteria_modeから通過経路を確認できる。
Training
Championはcheckpoints/policy_value_training_latest_best.ptへ保存し、反復run内では次cycleのself-playとwarm
startに使う。正式なpolicy_value_latest_best.ptは52%を満たすまで更新しない。benchmarkの比較対象も正式Championに固定するため、50%の小さな更新を積み重ねながら正式基準への到達を確認できる。
固定7デッキ、rule-agent 16デッキ、既定値では、初回評価は次の364試合になる。
Candidate vs Champion: 7 x 10 x 2 directions = 140
Candidate vs rule pool: 7 x 16 x 1 = 112
Champion vs rule pool: 7 x 16 x 1 = 112
Champion の rule-pool 結果は data/eval/promotion-gate/cache/ に保存する。2
cycle 目以降は、前 cycle の promoted
Candidate または据え置かれた Champion の結果を再利用するため、通常は140 + 112 =
252試合になる。--promotion-seed は self-play seed と分離され、既定値0で固定される。
cache は checkpoint、deck、config、評価実装、試合数、worker、device、seedのfingerprintが一致する場合だけ使う。再計測したい場合は
--no-promotion-rule-cache を指定するか、別の --promotion-seed を使う。
評価 artifact は data/eval/promotion-gate/<run-name>-<run-id>-attemptNNN/
に保存される。短い疎通確認などで評価を省略する場合は --no-promotion-gate
を明示する。この場合は学習完了後に latest
alias が無条件更新されるため、通常の長時間学習には使わない。
MPS/CUDA で self-play 推論だけを軽くしたい場合は --selfplay-precision fp16
を追加する。各 cycle の train は直前 cycle の fp32 best checkpoint を warm start に使い、self-play
stage だけ checkpoints/quantized/<run_name>/*_fp16.pt に変換した checkpoint を読む。CPU
self-play では fp16 が速くならないことが多いため、基本は --selfplay-device mps または cuda
と組み合わせて使う。
複数の NVIDIA GPU があるサーバーでは、--selfplay-devices auto を指定すると visible な CUDA
device をすべて検出し、self-play worker を cuda:0,cuda:1,...
へ round-robin に割り当てる。明示したい場合は --selfplay-devices cuda:0,cuda:2
のようにカンマ区切りで指定する。
途中で止まった場合は、同じ --run-name、--run-id、--resume で再実行する。run
id を固定しておくと再開しやすい。
pca selfplay-train \
--checkpoint checkpoints/policy_value_latest_best.pt \
--run-name ismcts-iterative-10k \
--run-id 20260705-120000 \
--total-games 10000 \
--games-per-cycle 1000 \
--chunks 10 \
--workers 8 \
--train-device mps \
--resume
再開時の挙動:
- chunk JSONL と summary CSV がそろっている chunk は skip する。
--resume付きで best checkpoint が既にある train stage は skip する。- train途中ではattemptごとの
*.train-state.ptからmodel、optimizer、RNG、epoch内batch位置を復元する。V14は3,000 micro-batchごとに保存する。MPSではmps_driverが22,000 MiBへ達した場合もoptimizer更新境界で保存し、その直後にtrain processを自動で置き換えてMPSGraph memoryを解放する。CUDA/CPUではprocessを置き換えない。 - streaming stateにはJSONL byte cursorとshuffle buffer referenceを含むため、新形式stateからの再開で巨大なtrain入力を先頭から読み直さない。旧stateからの初回再開だけはprefix replayが必要になる。
- cycle 実行では、次 cycle の checkpoint が直前の promoted best checkpoint に自動で切り替わる。
.promotion-statusがpromoted/training_promoted/rejectedとして残り、--resume時は完了済み判定を再利用する。- retryごとのcheckpoint、metrics、promotion statusもattempt suffix付きで残り、完了済みattemptはskipする。
出力¶
主な生成物:
| 生成物 | パス |
|---|---|
| chunk JSONL | data/selfplay/<run-name>-<run-id>/<run-name>-partNNN.jsonl |
| merged JSONL | data/selfplay/<run-name>-<run-id>.jsonl |
| agent summary | *.agent-summary.csv |
| agent matchup summary | *.agent-matchup.csv |
| deck summary | *.deck-summary.csv |
| search diagnostics | *.search-diagnostics.csv |
| final checkpoint | checkpoints/policy_value_<run_name>_<run_id>_final.pt |
| best checkpoint | checkpoints/policy_value_<run_name>_<run_id>_best.pt |
| run manifest | logs/selfplay-train/<run-name>-<run-id>.manifest.yaml |
| run ledger | logs/selfplay-train/<run-name>-<run-id>.ledger.yaml |
| live metrics | logs/selfplay-train/<run-name>-<run-id>.metrics.jsonl |
| train attempts | logs/selfplay-train/<run-name>-<run-id>.train-attempts.json |
| per-game metrics | data/selfplay/<run-name>-<run-id>.game-metrics.jsonl |
| MLflow run ID | logs/selfplay-train/<run-name>-<run-id>.mlflow-run-id |
| logs | logs/selfplay-train/<run-id>-*.log |
| promotion benchmark | data/eval/promotion-gate/<run-name>-<run-id>-attemptNNN/ |
| promotion rule cache | data/eval/promotion-gate/cache/ |
| promotion status | <best-checkpoint>.promotion-status |
| replay registry | data/replay/<run-name>/promoted.yaml |
| replay sample | data/replay/<run-name>/<run-id>-history.jsonl |
| replay summary | data/replay/<run-name>/<run-id>-history-summary.json |
学習が完了し promotion gate に合格すると latest alias が更新される。却下された candidate checkpoint と評価結果も削除されず、調査用 artifact として残る。
train-compareなどpipeline外で作ったcheckpointは、promotion-runが合格しても自動ではaliasを更新しない。評価済みCandidateを正式採用するときは
pca promote-checkpointを使う。このコマンドは評価artifactのhashと現在Championを確認し、latest
alias、cycle manifest、run ledger、replay registryを同じ採用単位で同期する。
| Alias | Meaning |
|---|---|
checkpoints/policy_value_latest_best.pt |
最後に完了した学習 run の best checkpoint。 |
checkpoints/policy_value_latest_final.pt |
最後に完了した学習 run の final checkpoint。 |
checkpoints/policy_value_<run_name>_latest_best.pt |
同じ run name 内の latest best checkpoint。 |
checkpoints/policy_value_<run_name>_latest_final.pt |
同じ run name 内の latest final checkpoint。 |
checkpoints/policy_value_latest.yaml |
latest alias が指す実体、run name、run id、config、run manifest。 |
run manifest には、初期 checkpoint、self-play config、train
config、chunk 数、train 入力、checkpoint 出力、promotion gate、latest
alias 更新状態が残る。途中停止後は、同じ --run-name と --run-id で再実行する前に manifest の
selfplay.status、training.status、latest.status を見る。
uv sync --group mlops済みの環境では、通常のpca selfplay-trainがMLflowへ試合単位と集計metric、15秒間隔のsystem
metrics、stage/validation/代表・異常gameのtraceを自動記録する。
mise run mlflow:uiを起動し、http://127.0.0.1:5050から同じrun
IDの全cycleを親runの推移グラフと子run一覧で確認できる。子runではcycle内のloss、selfplay/game/*の試合時系列、探索統計、promotion結果を確認し、Tracesから処理時間や異常gameを調査する。詳細はMLOps Pipelineを参照する。
反復runでは、個別manifestを横断しなくてもよいようにrun ledgerも更新される。champion.best_cycle と
champion.best_checkpoint が現在の最良checkpointを示し、cycles
には各cycleのpromotion判定、head-to-head勝率、rule-pool macro勝率、Replay追加ゲーム数が並ぶ。
次の self-play、eval、submission bundle では、基本的に checkpoints/policy_value_latest_best.pt
を使う。
pca selfplay \
--checkpoint checkpoints/policy_value_latest_best.pt \
--output data/selfplay/latest-smoke.jsonl \
--games 4 \
--workers 2
小さな疎通確認¶
大量実行の前に、同じ入口で小さく動かす。
pca selfplay-train \
--run-name smoke-selfplay-train \
--games 4 \
--workers 2 \
--train-device cpu \
--resume
コマンド展開だけ見る場合:
pca --print-command selfplay-train \
--run-name smoke-selfplay-train \
--games 4 \
--workers 2 \
--train-device cpu
self-play だけ確認したい場合:
pca selfplay \
--output data/selfplay/smoke.jsonl \
--games 2 \
--workers 2 \
--device cpu
確認するログ:
fallback=0
search begin > 0
ismcts dec > 0
nn calls > 0
depth avg が 2 以上
reach attack_reached / prize_reached が出る
fallback が連続して出る場合、その JSONL は teacher
search として弱い。大量学習に進む前に例外、checkpoint load、card metadata、belief
source を確認する。
Policy・Value学習だけを再実行する¶
self-play JSONL が既にある場合は train stage だけ実行できる。
pca selfplay-train \
--skip-selfplay \
--selfplay-output data/selfplay/ismcts-selfplay-1000g-20260705-120000.jsonl \
--run-name ismcts-selfplay-1000g \
--run-id 20260705-120000-retrain \
--checkpoint checkpoints/policy_value_latest_best.pt \
--train-device mps
より直接的に学習する場合:
pca train \
--input data/selfplay/ismcts-selfplay-1000g-20260705-120000.jsonl \
--init-checkpoint checkpoints/policy_value_latest_best.pt \
--output checkpoints/policy_value_retrain_final.pt \
--best-output checkpoints/policy_value_retrain_best.pt \
--device mps
大きな JSONL では config 側の streaming を使う。CLI で明示する場合:
pca train \
--input data/selfplay/large-selfplay.jsonl \
--output checkpoints/policy_value_large_final.pt \
--best-output checkpoints/policy_value_large_best.pt \
--streaming \
--device cuda
Belief学習¶
通常の unified self-play / train では integrated belief heads を使うため、別 checkpoint の BeliefNet 学習は必須ではない。standalone belief checkpoint を別実験で使う場合だけ実行する。
pca belief-train \
--input data/selfplay/example.jsonl \
--output checkpoints/belief_final.pt \
--best-output checkpoints/belief_best.pt \
--device mps
No usable belief records found が出る場合は、self-play 収集時に full-observation
targets が入っているか、JSONL が壊れていないかを確認する。
評価¶
学習後は小さな評価で動作確認してから、games / workers を増やす。
pca eval \
--checkpoint0 checkpoints/policy_value_latest_best.pt \
--games 20 \
--workers 4 \
--device cpu \
--output data/eval/latest-smoke.json \
--csv-output data/eval/latest-smoke.csv
rule agent pool 相手のデフォルト評価:
pca eval \
--checkpoint0 checkpoints/policy_value_latest_best.pt \
--games 100 \
--workers 8 \
--device cpu \
--output data/eval/latest-vs-rule.json \
--csv-output data/eval/latest-vs-rule.csv
探索方式や config の変更を比較する場合:
pca eval-ab \
--set games=100 \
--set workers=8 \
--set device=cpu
pca eval-ab は baseline / experiment の evaluation config を同じ override で順番に実行し、
data/eval/ab/<run-name>/eval-ab.metrics.csv に差分を保存する。片側だけ条件を変える場合は
--baseline-set KEY=VALUE または --experiment-set KEY=VALUE を使う。
評価で見る指標:
normal_winsavg_prizes_takenavg_attacksavg_first_attack_stepavg_first_prize_stepdeck_out_lossesunfinishedattack_ready_count
deck-out 勝ちだけ増える場合は、teacher search または value target がサイド取得に十分寄っていない可能性がある。
ログの読み方¶
self-play ログの重要部分:
search begin=... step=... end=... full_obs=... fallback=...
nn calls=... cache=hit/miss total=... fwd=...
[local-policy-batcher] requests=... batches=... avg_batch=... req/s=...
ismcts dec=... sim=... hidden=... time=...
depth avg=... max=... hist=...
reach turn_advance=... attack_reached=... prize_reached=...
root-actions sel play=... attach=... attack=... choice=...
prize-delta events=... taken=... value=...
perf elapsed=... speed=... progress=... remaining=... eta=...
見る順番:
fallback- 0 が望ましい。増える場合は search が落ちて NN-only fallback になっている。
depth avg- 2 以上を目安に見る。1 台だとほぼ root 付近しか見ていない。
reachattack_reached/prize_reachedが極端に低いと、探索が攻撃・サイド取得に届いていない。nn fwd- 最大ボトルネックになりやすい。
local-policy-batchingを使う場合は[local-policy-batcher] avg_batchも見る。 perf progress/remaining/eta- 並列 self-play では一番遅い worker の
etaが全体完了の目安になる。 taken/remain- サイド取得が増えているかを見る。deck-out や pokemon-out だけで終わるデータは品質が低い。
training ログで見る項目:
loss policy value aux belief policy_w aux_cov belief_cov lr grad
[memory] rss mps_alloc mps_driver mps_limit
Wrote best checkpoint ...
Wrote checkpoint ...
MPSのmps_allocが横ばいなのにmps_driverだけが継続的に増える場合、live tensorではなく可変input
shapeに対応するMPSGraph
cacheが増えている可能性がある。V14はbatch-padding-mode=mps_stableで通常範囲のshapeを固定し、
mps-restart-driver-memory-mb=22000でOOM前に自動再起動する。ログにrestarting process ... because MPS driver memory ...、続いてexec restartが出た後、同じstateから再開すれば正常である。watermark無効化はsystem
memoryを使い切る危険があるため標準手順にはしない。
JSONL の保全¶
長時間実行後は、生成された JSONL と summary CSV を消さないようにする。最低限、行数と先頭 record を確認する。
wc -l data/selfplay/ismcts-selfplay-1000g-20260705-120000.jsonl
head -n 1 data/selfplay/ismcts-selfplay-1000g-20260705-120000.jsonl
別環境へ移す場合は、JSONL と対応する checkpoint manifest を一緒に残す。
data/selfplay/<run>.jsonl
data/selfplay/<run>/*.csv
checkpoints/policy_value_<run>_best.pt
checkpoints/policy_value_latest.yaml
推奨サイクル¶
pca selfplay-train --games 4で smoke。pca selfplay-train --chunks 10 --games-per-chunk 100で 1,000 games 収集と学習。pca eval --checkpoint0 checkpoints/policy_value_latest_best.ptで rule agent pool と評価。- 問題なければ
--total-games/--games-per-cycleで反復学習に進む。 - 良い checkpoint は run-name scoped alias と manifest を残す。
1 回で大きく強くするより、teacher search と value head を少しずつ改善しながら反復する。