Commit Graph
85 Commits
Author SHA1 Message Date
coolguyandCodex 102f8cc91d Support average strategy in interleaved traversal
Co-Authored-By: Codex <codex@openai.com>
2026-05-07 23:07:47 +09:00
coolguyandCodex 240ef552c6 Add non-default interleaved traversal scheduler
Co-Authored-By: Codex <codex@openai.com>
2026-05-07 22:49:38 +09:00
coolguyandClaude Opus 4.7 6c9babe769 Validate strategy-memory flags under external sampling
OpenSpiel's Deep CFR records strategy samples at opponent nodes during
the traverser's tree walk; storing on traverser nodes under external
sampling drops the ρ_p reach factor and biases the average-policy
estimate. Reject that config combination at load time and add a research
note deriving why outcome sampling is unaffected while external is not.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 20:56:57 +09:00
coolguy 6c976f468a Wire AMP into Deep CFR trainer behind run.use_amp flag (default off)
Adds torch.autocast(fp16) + GradScaler around _train_advantage and
_train_strategy when run.use_amp=true and device=cuda. CPU/non-CUDA
falls back to fp32 no-op. Mitigations:
- scaler.unscale_(optimizer) before grad_clip.
- nonfinite-loss guard skips overflowing batches and counts them.
- diff.float().square() in advantage loss to avoid fp16 overflow.
- strategy mask/log_softmax kept in fp32.

New metrics: amp/grad_scale, amp/nonfinite_loss_count.

Tests: AMP CUDA smoke + CPU fallback in test_deep_cfr_trainer.py.

Bench: scripts/bench_amp_trainer.py micro-benches train phases under
synthetic replay memory. smoke.yaml result is fp32 3.22ms / AMP 3.92ms
(0.82×, regression). 100-iter A/B on default.yaml deliberately
skipped: smoke regression mirrors the 2026-05-07 torch.compile
regression dynamic (dispatch overhead > kernel benefit at this model
size) and re-confirming on the same size adds no information.

Default stays run.use_amp: false. Re-enable trigger documented in
docs/performance.md: hidden_size >= 1024 or num_layers >= 6, then run
the bench script + 100-iter A/B before flipping default.
2026-05-07 20:21:17 +09:00
coolguyandClaude Opus 4.7 a7ab94e096 Add batched traversal inference server (Option A) behind opt-in flag
Implements the central inference server pattern: a dedicated GPU
process owns advantage/strategy/league networks, batches policy
requests across traversal workers via shared-memory tensor pool, and
returns logits. Workers route forward calls through InferenceClient /
NetworkProxy when traversal.inference_backend == "server".

Default remains traversal.inference_backend: local. The server
backend regresses iter time ~3.8× on the inspected default config
(small-model dispatch + sync-blocking traversal capping realized
batch at ~num_workers=8 instead of the bs=64-256 needed to amortize
IPC overhead). Keeping the implementation behind the flag lets us
re-enable when (a) model size grows, (b) per-worker interleaved
traversal lands, or (c) eval becomes dominant — see
docs/performance.md "Option A Bench Result and Structural Ceiling"
for the full diagnosis.

Plumbing included:
- inference_buffers.py: shared-memory tensor pool with slot
  management.
- inference_client.py: per-worker client + NetworkProxy adapter for
  the existing traversal.pyx call sites.
- inference_server.py: spawn-context server process with
  batch-window aggregation, weight sync, shutdown sentinel.
- bench_inference_backend.py: A/B between local and server backends
  with eval/checkpoint disabled.
- test_inference_server.py: round-trip and integration tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 20:05:16 +09:00
coolguyandClaude Opus 4.7 05de0e2a81 Port safe-heuristic bots to Cython with Python reference fallback
Cython implementation in heuristic_cy.pyx achieves ~2.55× speedup on
opponent_act_seconds (200-game eval: 59.20s → 23.24s). Original Python
implementation preserved verbatim in heuristic_py.py as the equivalence
reference. Action-sequence equivalence is verified by
test_safe_heuristic_equivalence.py against seeded game corpora.

Key implementation notes:
- File-local wraparound=True override required for negative discard
  indexing; Cython global wraparound=False would segfault.
- annotation_typing=False preserves verbatim Python semantics.
- _CachedState materializes hands/expeditions/discards/deck once per
  act() call — this is the dominant performance win.

Further C-array optimization of _card_value_for_me /
_card_value_for_opponent / _color_commitment / _bonus_potential is
deferred. The current 2.55× delivers most of the dense-eval future
benefit; further work is gated on actually adopting denser eval
schedules (eval_every=5, games=1000).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 20:03:53 +09:00
coolguyandClaude Opus 4.7 7c7c582c46 Slash-namespace logged metric keys for W&B grouping
Adopt a 5-namespace scheme so wandb groups related metrics in the
sidebar and capture-group regex (eval/(random|safe_heuristic)/win_rate0
vs eval/(?:random|safe_heuristic)/win_rate0) controls panel splitting:

- loss/{advantage,strategy}
- samples/{advantage,strategy,advantage_player_N}
- memory/{advantage,strategy,advantage_player_N}
- time/{iteration_seconds,traversal_seconds,advantage_train_seconds,
  strategy_train_seconds,evaluation_seconds,memory_add_seconds,
  checkpoint_seconds,batch_tensor_seconds,nodes_per_second,
  advantage_player_N_sample_seconds,strategy_sample_seconds}
- traversal/{nodes,terminals,depth_cutoffs,node_limit_cutoffs,
  max_depth_reached,endpoints,avg_endpoint_depth,
  endpoint_depth_bucket_*,regret_fallback_*,sampled_actions}
- eval/<opponent>/<metric> (3-level so opponent can be the capture group)

`iteration` keeps no namespace (it's the wandb step axis). Internal
TraversalStats.to_dict() and benchmark.py's standalone result dict
keep their flat names — only the trainer's emitted metrics are
remapped, with the traversal_*→traversal/* translation done at
insertion into runtime_metrics.

analyze.py updated to read the new keys (PlotSpec metrics, color map,
opponent_names parser, _first_existing_eval lookup). Tests updated for
the new eval_metrics dict keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:37:41 +09:00
coolguyandClaude Opus 4.7 5aab84c15f Only record evaluation_seconds when eval actually ran
Previously the timer wrapped every call to _evaluate(), but on iterations
that skip eval (iteration % eval_every != 0) the function returns
immediately and the recorded value was just function-call overhead
(~3 µs), which made W&B show a wildly bimodal "evaluation_seconds"
metric. Now only set the key when eval_metrics is non-empty so
non-eval iterations have no data point.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:26:12 +09:00
coolguyandClaude Opus 4.7 e6b7a41dc0 Show iters_per_hour estimate in iteration summary
Append a rough iters_per_hour estimate (3600/iteration_seconds) to the
console summary so users running long jobs can eyeball ETA without doing
the math.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:12:27 +09:00
coolguyandClaude Opus 4.7 5687435f84 Prefix iteration-scoped log lines with [i=N]
Make traversal progress and iteration-complete summary lines easier to
visually scan during long runs by leading with [i=N]. Drop the redundant
"iteration=N" kv from the body to keep lines short.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:11:34 +09:00
coolguyandClaude Opus 4.7 a1215959a7 Warn when max_iterations is too small for any eval to run
If eval_every is positive but max_iterations falls before the next scheduled
eval iteration (including resume cases where current_iteration is already
past the last eval boundary), log a one-time warning at run start so the
user notices the misconfiguration. We deliberately do not force an
end-of-run eval, which would distort time budgets and reproducibility.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:03:28 +09:00
coolguyandClaude Opus 4.7 54a5fdab2e Add --wandb-notes flag for run purpose description
Exposes wandb.init's notes field through the CLI so each run can carry a
short description of its purpose, visible on the W&B run page alongside
tags and config.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:50:33 +09:00
coolguyandClaude Opus 4.7 abfd7298d9 Surface eval cost in iteration summary
Append eval_seconds and its share of iteration_seconds to the per-iteration
console summary when evaluation actually ran, so users watching the log can
see how much wall time eval is consuming without parsing JSON metrics.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:44:19 +09:00
coolguyandClaude Opus 4.7 acb664c873 Auto-derive run dir from experiment_name + timestamp
Drop checkpoint.directory from config — config defines what an experiment
is, not where its outputs go. The CLI now computes the run directory from
run.experiment_name plus a timestamp, defaulting to runs/tmp/ for
throwaway runs and runs/ when --keep is passed.

- Remove CheckpointConfig.directory and DeepCFRConfig.checkpoint_path
- DeepCFRTrainer takes run_dir: Path explicitly
- CLI: add --keep boolean; --resume requires an explicit path (no shortcut)
- Auto path: runs/[tmp/]<YYYY-MM-DD_HHMMSS>_<experiment_name-kebab>/
- Rename 13 configs to kebab-case; strip directory: lines; kebab their
  experiment_name values
- Rewrite AGENTS.md training/run sections; document
  archive/tmp/<flat> layout, --keep, kebab-case scope
- Update tests for new run_dir flow and dropped --resume shortcut

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:32:44 +09:00
coolguyandClaude Opus 4.7 a177031963 Clean up Deep CFR config schema
Remove legacy aliases, rename max_hours to max_minutes, collapse the
four checkpoint save flags into save_every + save_latest, and change
defaults to safer values (opponent_policy=self_play_league,
device=auto, eval_every=50, max_depth=null). Migrate all archived
yaml configs and tests to the new schema.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:09:19 +09:00
coolguy c2b88d7c9c Use configured train device 2026-05-07 15:58:10 +09:00
coolguy 0fea13786f Use generic train config overrides 2026-05-07 15:53:43 +09:00
coolguyandClaude Opus 4.7 44dd97876e Add optional wandb metrics tracking
Mirror Deep CFR training metrics to W&B via a new WandbRunTracker
wired through CompositeRunTracker; wandb is an optional extra so
default installs and runs stay unchanged. Train CLI gains
--wandb/--wandb-project/--wandb-mode/--wandb-name/--wandb-tag, and
train() now closes the tracker in a finally block so runs finalize
even on early exit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:42:30 +09:00
coolguy b1e77b6db0 Disable default analysis smoothing 2026-05-07 15:28:12 +09:00
coolguy 4c223f76ff Add generic Deep CFR config overrides 2026-05-07 15:26:39 +09:00
coolguy 43507375fc Add external sampling traversal mode 2026-05-07 15:23:40 +09:00
coolguy 712a1eedaf Add eval game record export 2026-05-07 14:13:15 +09:00
coolguyandClaude Haiku 4.5 f398c9fc4c Add opponent_policy=average_strategy support
Strategy network (학습 중인 average policy)를 traversal opponent로 사용하는
새 옵션 추가. Deep CFR 이론적 수렴이 average strategy에 대한 보장이라는
점에 착안 — opponent_policy=network의 발산 문제를 완화할 수 있는지 실증.

구현:
- config: opponent_policy validator에 average_strategy 추가
- traversal.pyx: opponent_policy_id=3, strategy_network 인자, softmax 기반
  policy 도출 (_policy_from_strategy_network)
- workers.py: TraversalWorkerBatch에 strategy_network state_dict 추가
- trainer.py: 직렬/병렬 traversal call에 strategy_network 전달
- 1000-iter 실험 config 추가 (opponent_policy=network와 동일 hyperparam)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-07 14:07:28 +09:00
coolguyandClaude Haiku 4.5 cee8849e04 Add backward-compatible color_shared network architecture
- Add network.kind field to config (mlp/color_shared)
- Implement ColorSharedNetwork that:
  - Splits input into 5 equal color blocks
  - Encodes each block with shared weights
  - Pools with mean/max aggregation
  - Concatenates pooled embeddings with remainder
  - Outputs same action logits as MLP
- Add ColorAttention for optional self-attention over color embeddings
- Add network.color_attention_layers and color_attention_heads config
- Maintain full backward compatibility (default kind=mlp)
- Add 28 comprehensive tests covering all architectures

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-07 09:18:13 +09:00
coolguyandClaude Haiku 4.5 fd99d3bb4a Deep CFR self-play anchor safe 512x3 2x updates 10000 iter config 및 관련 변경
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-07 09:14:23 +09:00
coolguy 6d84745daa Limit Deep CFR traversal futures in flight 2026-05-07 07:11:45 +09:00
coolguy 4712a9af89 Deep CFR LCFR DCFR loss weighting 추가 2026-05-07 06:30:48 +09:00
coolguy e1a5185d4d Deep CFR 아이디어와 분석 플롯 정리 2026-05-07 06:21:19 +09:00
coolguy 080bff517e Deep CFR regret fallback audit metrics 추가 2026-05-07 05:23:23 +09:00
coolguy 690e086738 Improve Deep CFR analysis dashboards 2026-05-07 04:58:27 +09:00
coolguy 4ec784217b Deep CFR legacy 학습 dynamics 정렬 2026-05-07 04:20:11 +09:00
coolguy 6433081ed2 Deep CFR 분석 대시보드 정리 2026-05-07 04:05:31 +09:00
coolguy 5fa4bd65ef Deep CFR 무제한 학습 config 추가 2026-05-07 03:52:59 +09:00
coolguy 148be6e9a0 Deep CFR evaluation 배칭 및 병렬화 추가 2026-05-07 03:42:00 +09:00
coolguy 54347e1e7f Deep CFR evaluation 프로파일링 메트릭 추가 2026-05-07 03:10:19 +09:00
coolguy 9acf9ed261 Deep CFR advantage memory를 player별로 분리 2026-05-07 02:59:03 +09:00
coolguy e411ea4a15 Deep CFR 프로파일링 메트릭 추가 2026-05-07 02:50:35 +09:00
coolguy b5b4f97d41 Deep CFR slot-aware encoding NaN 수정 2026-05-07 02:32:24 +09:00
coolguy ece82fc310 Deep CFR traversal을 Cython 엔진으로 교체 2026-05-07 02:25:33 +09:00
coolguy facd6eb36a Deep CFR traversal 재귀 한도 보강 2026-05-07 02:02:56 +09:00
coolguy 44a96f5b4c Deep CFR checkpoint CLI override 추가 2026-05-07 01:59:16 +09:00
coolguy fc4f0ddfd8 Deep CFR resume 동작 보강 2026-05-07 01:55:10 +09:00
coolguy 1645d22e87 Deep CFR 콘솔 트래킹 출력 정리 2026-05-07 01:47:54 +09:00
coolguy 1420ab76bd Deep CFR run tracking 추상화 2026-05-07 01:44:15 +09:00
coolguy 1b6d98ceeb Deep CFR traversal 운영 로그 보강 2026-05-07 01:23:26 +09:00
coolguy df8f979ce4 Deep CFR 재현 config 실행 보강 2026-05-07 01:12:09 +09:00
coolguy 312cbd3949 Deep CFR evaluation 진단 metric 추가 2026-05-07 01:03:09 +09:00
coolguy 7ef7e5b927 Deep CFR endpoint depth metrics 보강 2026-05-07 00:54:16 +09:00
coolguy 95d0660b0b Deep CFR playability encoding 추가 2026-05-07 00:52:28 +09:00
coolguy 9bcc88c1be Deep CFR legacy 재현 config 기반 추가 2026-05-07 00:46:09 +09:00