Pokémon TCG AI Battle — Train Config Reference
Every field of TrainConfig and every CLI flag of bc_train_mlx.py: type, default, semantics, current baseline, deprecations. Config hierarchy: CLI > --config file > configs/train_config.json > defaults.
Pokémon TCG AI Battle — Train Config Reference
Boundary
Every value that steers the trainer scripts/bc/bc_train_mlx.py. This page is exhaustive for the current schema (no historical fields, no ghosts). Cross-refs use pokemon_tcg_glossary for term meaning and pokemon_tcg_training_pipeline for how the values are consumed.
Current source correction at 20d7d0d
The field meanings below remain useful, but the runtime dtype contract changed after the August 7 snapshot. The current trainer sets model parameters and forward activations to strict FP32 and validates every model leaf. The current PyTorch inference converter also requires FP32. Historical FP16 defaults and artifacts remain documented in pokemon_tcg_torch_inference.
The exact scratch-register count is configuration-dependent: the dataclass default is 16, while the session JSON and some ablation runs use 32. A checkpoint's arch_config and resolved run manifest are authoritative for that run.
Config hierarchy
CLI args > --config file > configs/train_config.json > hardcoded defaults
Any CLI flag left as None falls back to the JSON config, which falls back to the dataclass default. All fields on TrainConfig are overridable via CLI. When both a CLI flag and a config JSON provide a value, CLI wins.
The default JSON at configs/train_config.json is a session file — it captures the last-used training strategy, not the recommended defaults. The recommended defaults are in the dataclass TrainConfig at rl/train_config.py. Ablations override strategy values from the CLI.
Model architecture
| flag / field | type | default | description |
|---|---|---|---|
--d-model / d_model | int | 128 | Transformer hidden dim. enum [64, 128, 256, 512]. 128 ≈ 1M params, 256 ≈ 3.5M, 512 ≈ 20M. Current baseline: 128. |
--nhead / nhead | int | 4 | Attention heads per layer; must divide d_model. |
--nlayers / nlayers | int | 3 | Stacked encoder layers. Current session JSON runs 4. Range 1–12. |
--ff / ff_dim | int | 512 | FFN width. Typically 4 × d_model. |
--static / static | bool | true | Enable static card features from EN_Card_Data.csv (learned linear projection). Table is a buffer, not trainable. |
--split-heads / split_heads | bool | true | Dedicated VALUE_TOK + SUBMIT_TOK with separate heads. |
--structured / structured | bool | false | Verb-conditioned action head with per-OptionType query and bias embeddings. Off in BC baseline. |
--scratch-registers / scratch_registers | int | 16 (dc default) / 32 (session JSON) | Learned workspace tokens between state and options. Carry inter-decision memory when TBPTT is on. Range 0–64. See pokemon_tcg_agent_architecture. |
--value-atoms / value_atoms | int | 51 | Categorical value head atom count. Only used when the model is instantiated with value_categorical=True. |
--value-vmax / value_vmax | float | 1.0 | Support half-width for the categorical value head. |
Training loop
| flag / field | type | default | description |
|---|---|---|---|
--epochs / epochs | int | 10 | Epochs for THIS invocation. When resuming, run_end_epoch = start_epoch + epochs. |
--batch / batch_size | int | 128 (dc) / 1024 (session) | Row budget per temporal batch under TBPTT; classic batch size otherwise. |
--accum-steps / accum_steps | int | 1 | Gradient accumulation microbatches per optimizer step. Effective batch = batch_size × accum_steps. FP32 accumulation, clip and update once. |
--lr / lr | float | 5e-4 (dc) / 8.7e-5 (session) | Peak learning rate. |
--lr-schedule / lr_schedule | choice | cosine | cosine | linear | none. |
--warmup-steps / warmup_steps | int | 1500 (dc) / 150 (session) | Linear warmup from 0 → peak over N optimizer steps. Clamped to max(total_steps/5, 1). |
--lr-min-ratio / lr_min_ratio | float | 0.1 (dc) / 0.2 (session) | LR floor after decay = lr × lr_min_ratio. |
--max-grad-norm / max_grad_norm | float | 1.0 | Post-accumulation clip. 0 disables. |
--seed / seed | int | 0 (dc) / 13 (session) | Seeds numpy AND mx.random. Both must be seeded — an older bug where only numpy was seeded caused untracked variance across runs. |
--optimizer / optimizer | choice | muon_adamw | Only value supported. Routes matrix params to Muon and everything else to AdamW. See pokemon_tcg_training_pipeline. |
--optimizer-state / optimizer_state | choice | reset | reset | resume. resume requires an identical optimizer contract in the checkpoint. |
--scheduler-state / scheduler_state | choice | reset | reset | resume. resume restores scheduler_phase_step and the checkpoint horizon. |
--scheduler-total-steps / scheduler_total_steps | int | 0 | Explicit horizon override for the scheduler phase. 0 = use the current run's optimizer-step count. Resume ignores this and keeps the checkpoint horizon. |
--muon-momentum / muon_momentum | float | 0.95 | Hidden-matrix Muon momentum. |
--muon-weight-decay / muon_weight_decay | float | 0.01 | Hidden-matrix Muon decay. |
--adamw-betas / adamw_betas | 2×float | [0.9, 0.999] | AdamW first- and second-moment coefficients. |
--adamw-eps / adamw_eps | float | 1e-8 | AdamW epsilon. |
--adamw-weight-decay / adamw_weight_decay | float | 0.01 | AdamW decoupled decay for the non-matrix leaves. |
structured_weight_decay (config-only) | float | 0.1 | Higher decay applied specifically to type_query / type_bias. Only relevant when --structured true. |
TBPTT and aux losses
| flag / field | type | default | description |
|---|---|---|---|
--tbptt-chunk / tbptt_chunk | int | 0 (dc) / 64 (session) | Decisions per chunk. 0 disables. Typical values: 8/16/32. Requires episode_id/side metadata (always present in current Parquet). See pokemon_tcg_tbptt_training_contract. |
--aux-ko-weight / aux_ko_weight | float | 0.5 | Weight of the ko_head_aux BCE loss added to CE. 0 disables. Target: aux_ko masked by aux_valid. |
--aux-prize-weight / aux_prize_weight | float | 0.5 | Weight of the prize_head_aux MSE loss. Target: aux_prize_delta. |
--aux-terminal-weight / aux_terminal_weight | float | 0.5 | Weight of the terminal_head_aux BCE loss. Target: aux_terminal. |
--aux-return-weight / aux_return_weight | float | 1.0 (dc) / 0.5 (session) | Weight of the return_head_aux MSE loss. Target: aux_return. Bumped to 1.0 in the current ablation baseline. |
Data selection (all CLI-only, no config fallback)
| flag | type | description |
|---|---|---|
--days | str | Comma-separated ISO dates: 2026-07-30,2026-08-01. |
--last-n-days | int | N most recently registered days in the SQLite datasets catalog. |
--all-days | flag | Every day in the catalog. |
--db | path | Override the SQLite catalog path. Default model/results.db. |
--max-rows-per-day | int | Cap rows PER DAY, rounded down to the nearest episode boundary. 0 = off. |
--top-elo | int | Filter to episodes where BOTH player_name and opponent_name are in the day's top-N agents by agent_elo_daily WHERE source='remote'. 0 = off. See pokemon_tcg_top_elo_curriculum_filter. |
--max-rows / max_rows | int | Global row cap across all resolved days. 0 = no cap. |
--val-frac / val_frac | float | Fraction reserved for validation. Split falls on episode boundary (deterministic given seed). |
--val-batch-size / val_batch_size | int | Max rows per validation temporal batch. |
Would-KO / dataset contract
| flag / field | type | default | description |
|---|---|---|---|
--bc-would-ko / bc_would_ko | bool | false (dc) / true (session) | Require or disable the would-KO contract on the dataset (aux_valid etc.). Startup fails if the dataset does not match. |
--bc-wk-nvar / bc_wk_nvar | int | 10 | Would-KO variable-attack determinizations. Higher = more accurate, more expensive at build time. |
--zero-wouldko | flag | off | Zero out the would-KO trio at load time (useful for ablating the signal). |
--dedup | flag | off | Load the opt_group column and collapse equivalent options at training time. |
bc_workers | int | 8 | Dataset builder parallelism (not used by trainer). |
bc_flush | int | 200 | Episodes per builder shard (not used by trainer). |
bc_ep_timeout | int | 60 | Per-episode build timeout in seconds. |
bc_both_sides | bool | true | Encode both sides per episode. Present in the current corpus. |
bc_self_aliases | list[str] | ["FitaLabs","Alef Oliveira"] (dc) / +["Fitalabs","aleffita"] (session) | Names that mark a row as is_self=1. Provenance only; not a model feature. |
Output and resume
| flag | type | default | description |
|---|---|---|---|
--out | path | (required at run time) | Best-checkpoint output path. |
--resume | path | none | Resume from this checkpoint pickle. Loads model weights and, when --optimizer-state resume / --scheduler-state resume, restores the optimizer and scheduler state too. |
--phase-id | str | none | Stable orchestration phase identity stored in every checkpoint (used by tcg-train-sequence). |
--export-final | path | none | Explicit copy of the best checkpoint to this path at end of run. Without this, no implicit model/bc_model/ write happens. |
--checkpoint-every-epochs / checkpoint_every_epochs | int | 1 | Save a numbered snapshot every N epochs. The final epoch is always saved regardless. A rolling _latest.pkl is written every epoch. |
Trainer runtime
| flag / field | type | default | description |
|---|---|---|---|
--compile / compile | bool | false | mx.compile the loss function. First call takes minutes; steady-state faster. Incompatible with dynamic clip fallbacks. |
--log-interval / log_interval | int | 100 | Print training stats every N optimizer steps. -1 disables the running printout (tensorboard remains live). |
Deprecated / removed
--prefetch/prefetch(field, schema, CLI flag) — removed 2026-08-07. The pyarrow Scanner reads ahead intrinsically, and cross-batch retention is owned by the hierarchical KV cache. See pokemon_tcg_kv_cache_hierarchical.--slab-rows/slab_rows— removed 2026-08-07. The MLX trainer has no fixed-size mmapped slabs anymore; each pyarrow batch is its own I/O unit and cache retention is by row group. The concept still exists in the historical PyTorch trainer atscripts/bc/bc_train.py, which is not part of the current runtime.model_dirfield — removed 2026-08-07. Nothing read it. Best-model export is explicit via--export-final.- The positional
dataCLI argument — hidden withargparse.SUPPRESS. Use--days/--last-n-days/--all-daysinstead. Kept in argparse so old invocations show the SUPPRESSED help rather than a hard error.
Non-trainer fields
Kept on TrainConfig because the dataset builder and data_manager consume them:
data_dir— where day-partitioned Parquet files live. Defaultdata/bc_data.replay_zip_dir— where downloaded Kaggle replay zips live. Defaultdata/bc_replay_zip.checkpoint_dir— where the trainer writes checkpoints. Defaultmodel/checkpoint.kaggle_competition— competition slug for submission uploads.kaggle_episodes_prefix— dataset name prefix for daily episode datasets.bc_workers,bc_flush,bc_ep_timeout,bc_would_ko,bc_wk_nvar,bc_both_sides,bc_self_aliases,max_episodes— all consumed by the dataset builder.
Current recommended baseline (BC curriculum ablation regime)
uv run tcg-train --days 2026-07-28,2026-07-29,2026-07-30,2026-07-31,2026-08-01 \
--max-rows-per-day 30000 --epochs 10 \
--batch 1024 --tbptt-chunk 16 --val-batch-size 1024 \
--lr 2.46e-4 --warmup-steps 20 --aux-return-weight 1.0 \
--out model/checkpoint/<tag>/<tag>.pkl \
--checkpoint-every-epochs 999
Rationale for each non-default:
--max-rows-per-day 30000— cap for ablation parity across scales. Not a training preference. See pokemon_tcg_bc_curriculum_ablation for why. Larger scaled-up training will raise or drop it.--batch 1024+--tbptt-chunk 16— TBPTT row budget and chunk size that fit comfortably in 24 GiB unified memory with the hierarchical cache.--warmup-steps 20— small run length: with ~150–1400 optimizer steps a longer warmup wastes the schedule.--aux-return-weight 1.0— restored from the smoke config after an earlier experiment lowered it to 0.5 (which appeared to weaken the terminal-return signal). Not tuned formally.--checkpoint-every-epochs 999— the rolling_latest.pklis what resumes actually need; numbered per-epoch checkpoints just waste disk during ablations.
Cross-references
- pokemon_tcg_glossary — meaning of
chunk,gstep,opt_step,warmup,source='remote' - pokemon_tcg_training_pipeline — how these fields flow through the trainer
- pokemon_tcg_kv_cache_hierarchical — why
--prefetchand--slab-rowsare gone - pokemon_tcg_top_elo_curriculum_filter — semantics of
--top-elo - pokemon_tcg_tbptt_training_contract — how
--tbptt-chunkinteracts with--batchandaccum-steps - pokemon_tcg_agent_architecture — where
--d-model/--nlayers/--scratch-registersland structurally - pokemon_tcg_bc_curriculum_ablation — the ablation the baseline command above ran