README: correct root cause (dynamics NMSE ~0.85 at aug onset), add three tuning arms
Browse files
README.md
CHANGED
|
@@ -39,8 +39,14 @@ in the e2e arm the spread between 1st and 5th place in the top-k heap is ~7%.
|
|
| 39 |
| path | arm | best epoch | val action MSE |
|
| 40 |
|---|---|---|---|
|
| 41 |
| `baseline/` | BC baseline | 60 | **0.003426** |
|
| 42 |
-
| `seq_be/` | sequential CCIL
|
| 43 |
| `e2e/` | end-to-end CCIL | 10 | 0.003215 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
Each directory holds `*_best.pt`, `val_top_k.json` (the full top-k selection
|
| 46 |
record), and where available the hydra `overrides.yaml`.
|
|
@@ -88,16 +94,57 @@ than halved (0.0239 -> 0.0112) — an overfitting signature on 44 training
|
|
| 88 |
episodes. `final_epoch300.pt` is included alongside `best.pt` so the gap between
|
| 89 |
last-epoch and val-selected weights is inspectable.
|
| 90 |
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
|
| 102 |
## Reproducing
|
| 103 |
|
|
|
|
| 39 |
| path | arm | best epoch | val action MSE |
|
| 40 |
|---|---|---|---|
|
| 41 |
| `baseline/` | BC baseline | 60 | **0.003426** |
|
| 42 |
+
| `seq_be/` | sequential CCIL, clean dynamics | 10 | 0.003401 |
|
| 43 |
| `e2e/` | end-to-end CCIL | 10 | 0.003215 |
|
| 44 |
+
| `e2e_fix_stepscale/` | e2e, `aug_step_scale=1.6` | 10 | 0.003260 |
|
| 45 |
+
| `e2e_fix_lossweight/` | e2e, `loss_normalization=fixed`, `lambda_aug=0.3` | 10 | 0.003258 |
|
| 46 |
+
| `e2e_fix_combined/` | e2e, all of the above + `aug_q_threshold=0.8`, `phase1=120` | 10 | 0.003258 |
|
| 47 |
+
|
| 48 |
+
Every arm carries `*_best.pt` (validation-selected) **and** `final_epoch300.pt`
|
| 49 |
+
(last epoch). They differ: best is typically epoch 10, final is epoch 300.
|
| 50 |
|
| 51 |
Each directory holds `*_best.pt`, `val_top_k.json` (the full top-k selection
|
| 52 |
record), and where available the hydra `overrides.yaml`.
|
|
|
|
| 94 |
episodes. `final_epoch300.pt` is included alongside `best.pt` so the gap between
|
| 95 |
last-epoch and val-selected weights is inspectable.
|
| 96 |
|
| 97 |
+
### Why augmentation never helped — the measured cause
|
| 98 |
+
|
| 99 |
+
**The latent dynamics head barely models the dynamics.** `fwd_image_nmse` is the
|
| 100 |
+
normalized one-step prediction error, where **1.0 means no better than predicting
|
| 101 |
+
"no change"**:
|
| 102 |
+
|
| 103 |
+
| epoch | 10 | 50 | 100 | 150 | 200 | 299 |
|
| 104 |
+
|---|---|---|---|---|---|---|
|
| 105 |
+
| e2e | 0.968 | **0.852** | 0.779 | 0.696 | 0.631 | 0.549 |
|
| 106 |
+
|
| 107 |
+
At epoch 50, when augmentation switches on, the head explains roughly **15% of
|
| 108 |
+
the latent displacement variance**; even after 300 epochs it reaches only ~45%.
|
| 109 |
+
Backward-Euler synthesizes `z_g = z_prev - step * fwd_head(z_prev, a_t)` and then
|
| 110 |
+
trains the policy to emit `a_t` at `z_g`. When `fwd_head` is that wrong, `z_g` is
|
| 111 |
+
largely noise and the policy is taught incorrect state-action associations. CCIL
|
| 112 |
+
assumes the dynamics model is good enough to place a corrective label; on 44
|
| 113 |
+
training episodes in a 6921-dim latent space, it is not.
|
| 114 |
+
|
| 115 |
+
**Three tuning arms confirm this and rule out hyperparameters as the cause.**
|
| 116 |
+
Each was run for a full 300 epochs from the same baseline checkpoint:
|
| 117 |
+
|
| 118 |
+
| arm | best | top-5 epochs | post-augmentation checkpoints in top-5 |
|
| 119 |
+
|---|---|---|---|
|
| 120 |
+
| original | 0.003215 | 10, 150, 50, 140, 160 | 150, 140, 160 |
|
| 121 |
+
| stepscale | 0.003260 | 10, 20, 40, 50, 30 | **none** |
|
| 122 |
+
| lossweight | 0.003258 | 10, 20, 40, 50, 30 | **none** |
|
| 123 |
+
| combined | 0.003258 | 10, 20, 40, 50, 70 | **none** |
|
| 124 |
+
|
| 125 |
+
The arm with the *weakest* augmentation — the original — is the only one whose
|
| 126 |
+
post-augmentation checkpoints placed at all. Correcting the displacement
|
| 127 |
+
(`aug_step_scale=1.6`, bringing effective displacement from 0.645 to ~0.98 of
|
| 128 |
+
true), relaxing the mask (`aug_q_threshold=0.8`, verified: `mask_ratio` 0.500 ->
|
| 129 |
+
0.797), reducing the augmentation weight, and delaying warmup to epoch 120 each
|
| 130 |
+
made post-augmentation checkpoints *less* competitive, not more. Amplifying a
|
| 131 |
+
mostly-wrong displacement amplifies the error.
|
| 132 |
+
|
| 133 |
+
Meanwhile training BC loss more than halved in every arm — the policy is
|
| 134 |
+
overfitting 44 episodes, and augmentation does not counteract it.
|
| 135 |
+
|
| 136 |
+
**Secondary issues, real but downstream.** Three advertised quality gates are
|
| 137 |
+
inert in this code path: `aug_cycle_threshold` (its `cycle_error_mean` is
|
| 138 |
+
assigned to zero and never computed), `aug_hardness_min` (`hard_ratio` is
|
| 139 |
+
hardcoded to 1.0), and the mask's quantile filter, which keeps exactly 50% by
|
| 140 |
+
construction regardless of absolute quality — and since `label_err` *is* the
|
| 141 |
+
novelty metric, it keeps the **least**-displaced half, selecting against novelty.
|
| 142 |
+
Worth fixing, but they are not why the method fails here.
|
| 143 |
+
|
| 144 |
+
**What would actually change the result:** gate augmentation on measured
|
| 145 |
+
`fwd_image_nmse` rather than an epoch count (e.g. require < 0.3), and give the
|
| 146 |
+
dynamics head materially more data. A 100-episode session exists and is being
|
| 147 |
+
evaluated separately.
|
| 148 |
|
| 149 |
## Reproducing
|
| 150 |
|