Document JAX PPO model capacity experiment
This commit is contained in:
@@ -0,0 +1,100 @@
|
|||||||
|
# Plan: JAX PPO Model-Size A/B
|
||||||
|
|
||||||
|
**Status:** Ready to execute
|
||||||
|
**Priority:** Low — 진단상 용량은 병목이 아닐 가능성이 높다. 그러나 PPO 스택에서
|
||||||
|
한 번도 측정된 적이 없어 정황증거뿐이다. 이 A/B의 목적은 **스케일링 라인을 열지,
|
||||||
|
닫을지 확정**하는 것이다.
|
||||||
|
**Background:** [docs/reports/jax-ppo-model-capacity-2026-07-12.md](../reports/jax-ppo-model-capacity-2026-07-12.md)
|
||||||
|
|
||||||
|
> 이 계획은 은퇴한 Deep CFR/PyTorch 스택용
|
||||||
|
> [model_size_experiment.md](model_size_experiment.md)를 **대체하지 않는다** —
|
||||||
|
> 그쪽은 다른 스택(`input_dim=365`, `configs/deep_cfr/`) 이야기다. 서로 무관하다.
|
||||||
|
|
||||||
|
## 가설
|
||||||
|
|
||||||
|
`hidden_size=512, num_layers=3` (808K 파라미터)은 구 스택에서 복사돼 온 상속값이며
|
||||||
|
PPO에서 검증된 적이 없다. 셀프플레이 샘플:파라미터 비가 약 2,028:1이므로
|
||||||
|
용량을 키우면 **응수 품질(expert 앵커)은 오르지만, exploitability 바닥(~0.54)은
|
||||||
|
움직이지 않을 것**이다.
|
||||||
|
|
||||||
|
이 예측이 맞으면 → 병목은 용량이 아니라 셀프플레이 스킴이며, 스케일링 라인을
|
||||||
|
닫고 리그/착취 구조 쪽에 투자한다.
|
||||||
|
틀리면 (exploitability가 유의하게 내려가면) → 스케일링이 열린다.
|
||||||
|
|
||||||
|
## 실험 설계
|
||||||
|
|
||||||
|
**2점 A/B. 그리드 아님.** 그리드는 이 우선순위에 비해 과하다.
|
||||||
|
|
||||||
|
| 이름 | hidden_size | num_layers | 파라미터 |
|
||||||
|
| --- | ---: | ---: | ---: |
|
||||||
|
| `size-512x3` (baseline) | 512 | 3 | 808,033 |
|
||||||
|
| `size-1024x4` (treatment) | 1024 | 4 | 3,714,145 |
|
||||||
|
|
||||||
|
- 두 config는 `network` 블록과 `run.experiment_name`만 다르고 **나머지는
|
||||||
|
final candidate와 byte-identical**이어야 한다. 기준 config:
|
||||||
|
`/mnt/2tbhdd/coolrl-lost-cities-artifacts/final-cycles/2026-07-05/main_ppo_config.json`
|
||||||
|
- **같은 `run.seed`**, 순차 실행 (AGENTS.md "Comparing two runs" 규약).
|
||||||
|
같은 GPU에서 두 학습을 병렬로 돌리지 말 것.
|
||||||
|
- 리그 **1 사이클**, 500 updates.
|
||||||
|
|
||||||
|
## 판정 기준 (중요)
|
||||||
|
|
||||||
|
**H2H로 판정하지 말 것.** 더 큰 모델이 더 작은 모델을 이기는 건 거의 자명하고,
|
||||||
|
그건 우리가 알고 싶은 게 아니다. 두 축으로만 본다:
|
||||||
|
|
||||||
|
1. **Expert 앵커** — `heuristic_expert` 상대 duplicate 평가
|
||||||
|
(shuffle bank seed 20260704, 2,000쌍). *응수 품질*을 본다.
|
||||||
|
2. **Exploitability** — 각 체크포인트에 대해 exploiter를 새로 학습시켜 승률 측정.
|
||||||
|
`long_random_shaping` 프로토콜(1200 updates, shaping anneal, warm start
|
||||||
|
`random`) 하나로 충분하다.
|
||||||
|
[diminishing-returns-2026-07-05.md](../reports/diminishing-returns-2026-07-05.md)의
|
||||||
|
기존 측정과 **같은 프로토콜 안에서만** 비교할 것 — 프로토콜이 다르면 섞지 않는다.
|
||||||
|
|
||||||
|
### 결정 트리
|
||||||
|
|
||||||
|
| Expert 앵커 | Exploiter 승률 | 결론 | 조치 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 유의하게 상승 | **변화 없음** (~0.54 유지) | **예측대로.** 용량은 병목이 아니다 | 스케일링 라인 종료. 리그/착취 구조로 이동. 1024×4를 default로 올릴지는 비용 대비 선택 사항 |
|
||||||
|
| 유의하게 상승 | **유의하게 하락** | 가설 기각. 용량이 실제로 제약이었다 | `network` default를 1024×4로 올리고, 2048×4까지 한 점 더 확장 |
|
||||||
|
| 변화 없음 | 변화 없음 | 용량 무관 확정 | 스케일링 라인 종료 |
|
||||||
|
| 하락 | — | 최적화 문제 (LR/KL 등이 큰 모델에 안 맞음) | default 유지. 스케일 재시도 전에 하이퍼파라미터 점검 |
|
||||||
|
|
||||||
|
"유의하게"는 Wilson CI(승률) / score CI(점수차) 비중첩 기준. 기존 리포트들이
|
||||||
|
쓰는 것과 동일하다.
|
||||||
|
|
||||||
|
## 비용
|
||||||
|
|
||||||
|
리포트 기준 리그 1사이클 ≈ 1.5시간 GPU (512×3). 1024×4는 파라미터 4.6배이나
|
||||||
|
병목이 롤아웃(엔진 시뮬)이라 학습 시간이 4.6배가 되지는 않는다.
|
||||||
|
exploiter 학습이 별도로 붙는다.
|
||||||
|
|
||||||
|
`.compute.lock`을 잡고 돌릴 것 (AGENTS.md "Compute Lock"):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flock -n .compute.lock <train command>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Non-goals
|
||||||
|
|
||||||
|
- 그리드 스윕(768×4, 1536×8 등) — 2점으로 충분하다. 결과가 애매할 때만 확장.
|
||||||
|
- 아키텍처 변경 (residual, transformer, per-color 공유 인코더 등) — 별도 주제.
|
||||||
|
- 인코딩 변경 (`OBS_DIM=454` 고정).
|
||||||
|
- 하이퍼파라미터 동시 변경 — 한 번에 하나만 바꾼다.
|
||||||
|
|
||||||
|
## Definition of done
|
||||||
|
|
||||||
|
산출될 파일 (아직 존재하지 않음):
|
||||||
|
|
||||||
|
```text
|
||||||
|
configs/jax_ppo/size-512x3.yaml
|
||||||
|
configs/jax_ppo/size-1024x4.yaml
|
||||||
|
docs/reports/jax-ppo-model-size-ab-<YYYY-MM-DD>.md
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] 위 두 config 추가 (final candidate config 기준, `network` /
|
||||||
|
`run.experiment_name`만 차이)
|
||||||
|
- [ ] 두 학습 순차 실행, 같은 seed, `.compute.lock` 사용
|
||||||
|
- [ ] 두 체크포인트 expert 앵커 duplicate 평가
|
||||||
|
- [ ] 두 체크포인트 exploiter 학습 + 승률 측정 (`long_random_shaping`)
|
||||||
|
- [ ] 결과표 + 결정 트리 적용 결과를 위 dated 리포트에 기록
|
||||||
|
- [ ] 결정 트리에 따라: `network` default 갱신 **또는** 스케일링 라인 종료를 문서화
|
||||||
@@ -1,5 +1,12 @@
|
|||||||
# Plan: Model-Size Experiment (Keystone for Model-Scale Optimizations)
|
# Plan: Model-Size Experiment (Keystone for Model-Scale Optimizations)
|
||||||
|
|
||||||
|
> **⚠️ 스택 주의 — 이 문서는 Deep CFR / PyTorch 스택 전용이다.**
|
||||||
|
> `input_dim=365`, `configs/deep_cfr/`, `DeepCFRMLP` 기준으로 쓰였다.
|
||||||
|
> 현행 JAX PPO 스택(`OBS_DIM=454`, `configs/jax_ppo/`, `ActorCritic`)에는
|
||||||
|
> **적용되지 않는다.** PPO 쪽 모델 크기 문제는
|
||||||
|
> [jax-ppo-model-size-ab.md](jax-ppo-model-size-ab.md)와
|
||||||
|
> [../reports/jax-ppo-model-capacity-2026-07-12.md](../reports/jax-ppo-model-capacity-2026-07-12.md)를 볼 것.
|
||||||
|
|
||||||
**Status:** Ready to execute
|
**Status:** Ready to execute
|
||||||
**Owner:** Operator (runs grid on `home`); Codex (adds configs and runner script)
|
**Owner:** Operator (runs grid on `home`); Codex (adds configs and runner script)
|
||||||
**Background:** See `docs/performance.md` → "Post-A Optimization Calculus",
|
**Background:** See `docs/performance.md` → "Post-A Optimization Calculus",
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
# JAX PPO Model-Capacity Diagnostic - 2026-07-12
|
||||||
|
|
||||||
|
"MLP를 더 키우면 아직 얻을 게 남아 있나?"에 대한 진단이다.
|
||||||
|
|
||||||
|
신규 학습 없이 기존 체크포인트, `league_metrics.jsonl`, 소스만 읽어 작성했다.
|
||||||
|
새로 실행한 학습·평가·벤치마크는 없다.
|
||||||
|
|
||||||
|
Subject: final candidate
|
||||||
|
`/mnt/2tbhdd/coolrl-lost-cities-artifacts/final-cycles/2026-07-05/final_candidate`
|
||||||
|
Metrics: `.../final-cycles/2026-07-05/league/2026-07-05_191933_jax-ppo-final-cycle-c01/league_metrics.jsonl` (500 updates)
|
||||||
|
|
||||||
|
## 요약
|
||||||
|
|
||||||
|
용량이 **현재의 병목일 가능성은 낮다.** 다만 PPO 스택에서 모델 크기는
|
||||||
|
**한 번도 검증된 적이 없으므로**, 이 판단은 아직 측정으로 뒷받침되지 않았다.
|
||||||
|
단발 A/B로 결론을 확정할 것을 권한다 —
|
||||||
|
[docs/plans/jax-ppo-model-size-ab.md](../plans/jax-ppo-model-size-ab.md).
|
||||||
|
|
||||||
|
## 1. 현재 크기는 근거 없는 상속값
|
||||||
|
|
||||||
|
`configs/jax_ppo/` 의 실 학습 config는 **전부** `hidden_size: 512, num_layers: 3`
|
||||||
|
이다 (`smoke.yaml`만 64×2). final candidate도 동일하다
|
||||||
|
(`main_ppo_config.json` → `network: {hidden_size: 512, num_layers: 3}`).
|
||||||
|
|
||||||
|
`hidden_size`를 다룬 기존 문서는 전부 은퇴한 Deep CFR/PyTorch 스택 것이다
|
||||||
|
(`input_dim=365`, `configs/deep_cfr/` 기준). 특히
|
||||||
|
[docs/plans/model_size_experiment.md](../plans/model_size_experiment.md)는
|
||||||
|
**현 JAX PPO 스택과 무관하다.**
|
||||||
|
|
||||||
|
→ 512×3은 실험으로 고른 값이 아니라 구 스택에서 복사돼 온 값이다.
|
||||||
|
|
||||||
|
## 2. 데이터 대비 모델이 매우 작다 (스케일링에 유리한 신호)
|
||||||
|
|
||||||
|
| 항목 | 값 |
|
||||||
|
| --- | ---: |
|
||||||
|
| `OBS_DIM` (`types.py:27`) | 454 |
|
||||||
|
| `N_ACTIONS` | 96 |
|
||||||
|
| 512×3 파라미터 수 | **808,033** |
|
||||||
|
| 1024×4 파라미터 수 | 3,714,145 |
|
||||||
|
| 2048×4 파라미터 수 | 13,719,649 |
|
||||||
|
| 최종 사이클 소비 transition | **1,638,400,000** |
|
||||||
|
| 샘플 : 파라미터 | **약 2,028 : 1** |
|
||||||
|
|
||||||
|
transition 수는 `rollout_steps=400 × batch_games=8192 × updates=500`.
|
||||||
|
|
||||||
|
셀프플레이라 데이터는 사실상 무한하다. 샘플:파라미터 2,000:1은 **데이터 제약이
|
||||||
|
아니라 용량/최적화 제약** 구간의 전형이며, 보통 이런 영역에서 스케일링이 먹힌다.
|
||||||
|
0.8M 파라미터는 절대적으로도 작다.
|
||||||
|
|
||||||
|
여기까지만 보면 "키우면 이득"이다. 그러나 3절이 반대 방향을 가리킨다.
|
||||||
|
|
||||||
|
## 3. 학습 로그에 용량 부족의 지문이 없다
|
||||||
|
|
||||||
|
최종 사이클 500 업데이트 구간 평균:
|
||||||
|
|
||||||
|
| update | value_loss | entropy_mean | approx_kl | return_mean | return_std |
|
||||||
|
| --- | ---: | ---: | ---: | ---: | ---: |
|
||||||
|
| 0–50 | 0.0468 | 1.1159 | 0.0433 | 0.2696 | 0.6299 |
|
||||||
|
| 50–100 | 0.0462 | 1.1167 | 0.0438 | 0.2799 | 0.6275 |
|
||||||
|
| 100–200 | 0.0461 | 1.1241 | 0.0441 | 0.2822 | 0.6316 |
|
||||||
|
| 200–300 | 0.0459 | 1.1143 | 0.0437 | 0.2857 | 0.6306 |
|
||||||
|
| 300–400 | 0.0460 | 1.1239 | 0.0424 | 0.2900 | 0.6323 |
|
||||||
|
| 400–500 | 0.0463 | 1.1163 | 0.0423 | 0.2916 | 0.6340 |
|
||||||
|
|
||||||
|
세 가지를 읽을 수 있다.
|
||||||
|
|
||||||
|
**(a) 크리틱은 이미 잘 맞춘다.** `value_loss`는 순수 MSE다
|
||||||
|
(`ppo.py:624`: `masked_mean((mb_returns - value) ** 2, active_weight)`).
|
||||||
|
`return_std ≈ 0.634` → 에피소드 리턴 분산 ≈ 0.402. MSE 0.0463과 비교하면
|
||||||
|
**설명분산 ≈ 0.88**.
|
||||||
|
|
||||||
|
> 주의 — 이 0.88은 **상한 추정치**다. `return_std`는 에피소드 리턴의 표준편차이고
|
||||||
|
> (`ppo.py:1072`: `episode_return = jnp.sum(transitions.reward, axis=0)`),
|
||||||
|
> `value_loss`의 타깃은 GAE 리턴(`mb_returns`)이다. final candidate는 shaping이
|
||||||
|
> 0이고 `gamma=1.0`이라 두 분포가 가깝지만, `gae_lambda=0.95`의 부트스트랩이
|
||||||
|
> 타깃 분산을 축소시키므로 실제 설명분산은 이보다 낮을 수 있다.
|
||||||
|
|
||||||
|
용량이 모자란 네트워크는 loss가 **높은 지점에서** 정체한다. 여기는 **낮은
|
||||||
|
지점에서** 정체한다. 잔여 오차 상당 부분은 불완전정보 + 덱 셔플에서 오는
|
||||||
|
**환원 불가능한 분산**으로 보인다.
|
||||||
|
|
||||||
|
**(b) 엔트로피는 계수가 잡아둔 평형이다.** `entropy_mean`이 1.114–1.124에서
|
||||||
|
500 업데이트 내내 미동도 없다. `entropy_coef=0.01`과 정책 그래디언트가 이룬
|
||||||
|
평형이지 용량 한계가 아니다. **파라미터를 늘려도 이 값은 안 변한다.**
|
||||||
|
(불완전정보에서 혼합 전략은 정상이므로 이 자체가 결함은 아니다.)
|
||||||
|
|
||||||
|
**(c) 죽은 게 아니라 느린 것이다.** `return_mean`은 0.2696 → 0.2916으로
|
||||||
|
여전히 오르고 있다. `approx_kl`도 0.042–0.044로 유지되어 정책이 계속 움직인다.
|
||||||
|
수렴해서 멈춘 상태가 아니다.
|
||||||
|
|
||||||
|
## 4. 실제 천장은 exploitability이고, 이건 용량 문제가 아니다
|
||||||
|
|
||||||
|
[diminishing-returns-2026-07-05.md](diminishing-returns-2026-07-05.md) 기준,
|
||||||
|
final 계열을 상대로 새로 학습시킨 exploiter가 **여전히 승률 0.539–0.549로 이긴다**
|
||||||
|
(`repair_c01_update_500`, 3개 프로토콜).
|
||||||
|
|
||||||
|
불완전정보 게임에서 이 잔여 착취가능성은 **게임이론적 문제**다. PPO 셀프플레이는
|
||||||
|
내쉬로 수렴하지 않고 전략공간을 순환한다. MLP를 키우면 *같은 순환 역학 안에서
|
||||||
|
더 나은 응수*를 찾을 뿐, 이 0.54 바닥 자체를 무너뜨리지는 못한다.
|
||||||
|
|
||||||
|
## 판정
|
||||||
|
|
||||||
|
- 스케일링이 **소폭 이득**을 줄 가능성은 있다 (2절: 샘플:파라미터 2,000:1).
|
||||||
|
- 그러나 **용량 부족의 직접 증거는 없다** (3절: 낮은 지점에서 평평한 value_loss,
|
||||||
|
계수가 고정한 엔트로피).
|
||||||
|
- 그리고 **모델을 실제로 가두고 있는 것은 exploitability**이며, 이건 스케일로
|
||||||
|
풀리지 않는다 (4절).
|
||||||
|
|
||||||
|
따라서 우선순위는 낮다. 다만 **한 번도 측정한 적이 없다**는 사실 때문에 위
|
||||||
|
판단은 전부 정황증거다. 결론을 확정하려면 단발 A/B가 필요하다 →
|
||||||
|
[docs/plans/jax-ppo-model-size-ab.md](../plans/jax-ppo-model-size-ab.md).
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- 이 작업에서 신규 학습, config 변경, 체크포인트 수정은 없었다.
|
||||||
|
- 파라미터 수는 `ActorCritic(hidden, layers).init()` 후 리프 크기 합으로 계산했다
|
||||||
|
(`ppo.py:104`).
|
||||||
|
- GUI 영향 참고: 현재 CPU 추론 약 50ms/수. 1024×4로 키워도 150–200ms 수준이라
|
||||||
|
`lost-cities-play` 대국에는 지장이 없다.
|
||||||
Reference in New Issue
Block a user