amer224 commited on
Commit
d142123
·
verified ·
1 Parent(s): 0563f73

Add brains/sovereign-v3/train_notes.md

Browse files
Files changed (1) hide show
  1. brains/sovereign-v3/train_notes.md +161 -0
brains/sovereign-v3/train_notes.md ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SOVEREIGN v3 — Training Doctrine (~272M dense)
2
+
3
+ Exact recipe for **2× T4 (16 GB)**, shared shard format
4
+ `rl/shards_v2/*.npz`. Memory ≈9.4 GB/GPU at bs 16 + fp16 (see
5
+ ARCHITECTURE.md §3). Everything is implemented by `model.py` +
6
+ `data_adapters.py`.
7
+
8
+ ---
9
+
10
+ ## Stage A — Return-conditioned filtered BC + dynamics (offline, ~2–3 epochs)
11
+
12
+ ### A.1 Sample preparation (`ShardPrepper`)
13
+
14
+ 1. **Returns / RTG**: per-episode `R_t = r_t + γR_{t+1}`, γ=0.995;
15
+ +2 survive / +5 win terminal bonuses; z-scored per shard. **rtg = R̄** is
16
+ the conditioning input; `rtg_next` shifts within the episode (last
17
+ frame repeats).
18
+ 2. **Weights** `w = clip(exp(R̄/τ), 0.2, 8)` τ=1; ×4 survivor episodes;
19
+ ×2 ±2-frame kill windows; mean-normalized. (AWR soft filtering.)
20
+ 3. **Free-label targets**: `lab64`, `lab64_next` (majority-vote 64×64),
21
+ `threat`/`expand` intent mirrors, `gate_mask`/`gate_valid`,
22
+ `win_lab` (survived=1), `nums_next`.
23
+ 4. **Arena filtering**: drop >85%-water episodes.
24
+ 5. Frame stacks / sequence windows: opt-in (`stack=`, `build_sequences`).
25
+
26
+ ### A.2 Loss (exact)
27
+
28
+ ```
29
+ L = w · [ λk CE(kind; ls=0.05)
30
+ + λc CE(cell_logits[·,kind], cell)
31
+ + λp −logBeta(α,β; pct)·1[kind≠bank]
32
+ + λv Huber(value, R̄)
33
+ + λw CE(win_logits, win_lab; ls=0.05)
34
+ + λg BCE(gate, gate_mask)·1[valid]
35
+ + λs CE(seg64, lab64)
36
+ + λd CE(next_seg, lab64_next) # dynamics
37
+ + λt BCE(threat, threat) + λx BCE(expand, expand) # intent mirrors
38
+ + λe smoothL1(econ, cat(nums_next, rtg_next))
39
+ − λent (H(kind)+H(cell)+H(pct)) ]
40
+ λ = (0.5, 1.0, 0.25, 0.1, 0.1, 0.5, 0.5, 0.4, 0.2, 0.2, 0.05, 0.003)
41
+ ```
42
+
43
+ **Value option (IQL-expectile)**: for the value head only, replace Huber
44
+ with the τ=0.9 expectile loss `|τ−1[δ<0]|·δ²` — more robust to the weak
45
+ farmer buffer. Both are supported; ablation #6 decides.
46
+
47
+ ### A.3 Optimizer & schedule
48
+
49
+ - AdamW lr **3e-4 → 3e-5** cosine, **300-step warmup** (cortex), wd 1e-4
50
+ (Linear only), grad clip 5.0, **AMP fp16**, bs **16/GPU × accum 2**.
51
+ - 2–3 epochs. Smoke test first: `python model.py` (prints the 272M
52
+ breakdown), `python data_adapters.py` (adapter shapes).
53
+
54
+ ---
55
+
56
+ ## Stage B — RPO: return-conditioned PPO (online, in sim)
57
+
58
+ ### B.1 Rollouts
59
+
60
+ - `model.act(..., rtg=rtg_actual)` per tick; store `logprob`, `value`,
61
+ `win_prob`. **8 envs/GPU × 256 ticks** on CPU workers (2×T4 ⇒ ~2048
62
+ samples/round).
63
+ - Memory mode (optional): carry `state` through each episode
64
+ (truncated-BPTT); the env wrapper sketch:
65
+
66
+ ```python
67
+ # env wrapper sketch (mem mode)
68
+ s = None
69
+ for step in range(ep_len):
70
+ rgb_t, nums_t = env.obs()
71
+ a = model.act(rgb_t, nums_t, rtg=rtg_est, state=s)
72
+ s = a["state"] # (1, B, 768)
73
+ obs, r, done = env.step(a["kind"], a["cell"], a["pct"])
74
+ ```
75
+
76
+ ### B.2 RPO specifics
77
+
78
+ - **RTG-consistent advantages**: `A_t = R_t − V(s_t, R_t)` (value is
79
+ rtg-conditioned — that is the whole point; the critic never has to
80
+ guess the aspiration).
81
+ - GAE(γ=0.995, λ=0.95) over `A_t`; z-normalize; clip ε=0.2 on the full
82
+ action logprob.
83
+ - Value loss: 0.5×clipped Huber (double clip ±0.2 in return space) +
84
+ **win head CE on episode outcomes** + optional cell-value auxiliary
85
+ (Huber vs per-cell utility bootstrap — PPO-friendly spatial critic).
86
+ - 4 epochs/round, minibatch 64/GPU, AdamW lr 3e-4 + cosine tail, grad
87
+ clip 5.0, **AMP fp16 + fp32 master**.
88
+ - **KL-to-pretrain guard β=0.1** (frozen Stage-A prior); roll-back if mean
89
+ KL > 0.15 for 3 rounds (β→0.02). ICLR 2025 evidence: pretrain-init +
90
+ guard, no offline replay retention — do NOT mix shards into the PPO
91
+ batches.
92
+
93
+ ### B.3 Aspiration at play time
94
+
95
+ Eval/deploy with `rtg = +1.5` z-units (above-survival ambition; tune over
96
+ {0.5, 1.0, 1.5, 2.0} — ablation #1). The BC stage never saw rtg>2σ, so
97
+ stay inside the trained range.
98
+
99
+ ### B.4 Reward shaping (flag the sim edit)
100
+
101
+ `+0.004/tick alive, +0.4/kill, +2 survive timeout, +8 win`. Keep
102
+ intermediates small; the win is the judged objective.
103
+
104
+ ### B.5 League-lite (fictitious self-play, cheap)
105
+
106
+ Keep the top-3 checkpoints by win-rate. Every 10 rounds, evaluate the
107
+ current policy against the pool; promote if it wins >55%. Once promoted,
108
+ the sim runs our policy vs 7 bots + 2 frozen past selves — the only
109
+ "league" a 2×T4 budget can afford, and it directly targets the weakness
110
+ of the last-survivor objective (myopic bot-exploit policies).
111
+
112
+ ---
113
+
114
+ ## Stage C — Evaluation + wake-sleep loop
115
+
116
+ - 100+ episodes vs **9 mixed bots**, fixed seeds; metric **win-rate +
117
+ mean rank**; save best on rank; report binomial CI.
118
+ - **Wake-sleep distill**: after PPO plateaus, distill the 272M policy into
119
+ a ~30M dense student (same heads, distilled heat/kind/pct/value with KL;
120
+ `return_all=True` provides all teacher targets). Use the student for
121
+ 2× faster rollouts and richer league self-play data; the big teacher
122
+ trains from it. Repeat (cap 3 cycles).
123
+
124
+ ## Curriculum
125
+
126
+ Epoch 1 of Stage A on early-game frames (tick_frac < 0.35) → full data →
127
+ ×1.5 weight on tick_frac > 0.6 in the final pass.
128
+
129
+ ## Ablations (run before believing anything)
130
+
131
+ | # | Question | Change | Resolves |
132
+ |---|---|---|---|
133
+ | 1 | Aspiration rtg at play time | {0.5, 1.0, 1.5, 2.0} | the RPO knob |
134
+ | 2 | Return conditioning itself | rtg≡0 (frozen) vs conditioned | Bet 1's real value |
135
+ | 3 | Intent mirrors | λt=λx=0 vs default | opponent modeling |
136
+ | 4 | Dynamics head | λd=0 vs default | world-model value |
137
+ | 5 | Memory | GRU off vs on (seq BPTT) | temporal credit |
138
+ | 6 | Value objective | Huber vs τ=0.9 expectile | robustness |
139
+ | 7 | Win head | on/off in Stage B loss | endgame behavior |
140
+ | 8 | League-lite | pool vs no pool | self-play payoff |
141
+ | 9 | Wake-sleep | 0 vs 3 distill cycles | scaling loop |
142
+
143
+ ## Expected compute (2× T4, fp16)
144
+
145
+ - Stage A: ~8–14 h for the current GB-scale shard set (272M, bs 16/accum 2).
146
+ - Stage B: ~2–3 updates/min at minibatch 128 → one full experiment per
147
+ ~1–2 days. That is the honest cost of the mandate; the sanctioned trims
148
+ (in order): `head_hidden` 3072→2048, `cortex_layers` 6→4, `enc_ch` top
149
+ 832→640. Each keeps the total >200M.
150
+
151
+ ## Risk register
152
+
153
+ | Risk | Mitigation |
154
+ |---|---|
155
+ | fp16 NaN in attention | fp32 master, grad clip 5, warmup; fall back fp32 for Stage A |
156
+ | Unlearning the BC prior | KL guard + roll-back (B.2); no offline replay retention |
157
+ | Aspiration OOD (rtg>2σ) | clamp rtg to ±2.5; ablation #1 |
158
+ | Threat/expand labels are imbalanced | BCE weights 8:1 positive:negative |
159
+ | GRU rollout complexity | default off; env sketch included |
160
+ | Activation memory at bs 16 | `grad_ckpt=True` halves the heavy stages |
161
+ | Color-identity prior (red=me) | sim-specific; documented |