diff --git a/docs/experiment_round48_pre_h4.json b/docs/experiment_round48_pre_h4.json new file mode 100644 index 0000000..b80dca7 --- /dev/null +++ b/docs/experiment_round48_pre_h4.json @@ -0,0 +1,109 @@ +{ + "config": { + "ckpt": "ml/runs/base_dag2_dag1/best.pt", + "samples": "ml/data/samples", + "tasks": null, + "split": "val", + "n": 256, + "K": 8, + "commit": 2, + "fb": 2.2, + "ki": 0.0, + "fb_scale": 0.0, + "fb_near": 0.2, + "fb_fallback": 0.0, + "kdecay": 0.9, + "kimax": 0.5, + "fb_every": 1, + "safety_try": 0, + "sel_w": 0.1, + "dls_safety": 1, + "fb_clear": 0.0, + "fb_cmin": 0.3, + "sub_refresh": 0, + "fb_block_gain": 0.5, + "dump": "ml/runs/round48_pre_h4_rows.json", + "out": "docs/experiment_round48_pre_h4.json", + "trace": null, + "select": "pre", + "replan": "empty", + "safety": 1, + "partial": 1, + "inc_cap": 1, + "gap_margin": 0.0, + "cert_batch": 1, + "steps": 1, + "z_scale": 1.0, + "len_w": 0.0, + "tie": 0, + "pre_h": 4, + "backoff": 0, + "max_sec": null, + "seed": 0, + "dls": "analytic", + "device": "cuda" + }, + "batch_size": 256, + "batch_seed_rule": "same seed per batch", + "checkpoint_sha256": "f7f686fd8ee92fb6948fbcc4ee954636065ad87bb54f661c4f8f575bc16c2ce1", + "tasks_sha256": "249bd93457825cda98c59e64d9a096d3473c69aeb3553de1dea6d9e56be71772", + "kin_fp": "2ebcbf17", + "act_scale": 1.0, + "metrics": { + "n": 256, + "n_ref": 256, + "success": 0.5390625, + "collision_free_success": 0.5390625, + "time_ok_1p3": 0.3046875, + "collision_rate": 0.0, + "collision_steps_mean": 0.0, + "travel_ratio_median": 2.5618672370910645, + "time_mean_s": 2.4820291996002197, + "brakes_mean": 20.40625, + "start_fail": 0.0, + "goal_ratio_2s": 0.23497404158115387, + "err_fail_med": 199.24868774414062, + "err_success_med": 0.33005011081695557, + "dls_share": 0.62890625, + "time_budget": "teacher×2(≥3 s)", + "speed_ratio_p50": 1.0000016689300537, + "speed_ratio_p95": 1.0000101327896118, + "speed_ratio_max": 1.0000101327896118, + "over_vmax_rate": 0.0, + "accel_ratio_p95": 1.0000016689300537, + "accel_ratio_max": 1.0000101327896118, + "reverse_p50": 0.24242424964904785, + "reverse_mean": 0.24662044644355774, + "reverse_moving_p50": 0.30327868461608887, + "moving_share_p50": 0.9583333134651184, + "brake_rate_mean": 0.1046474277973175, + "brake_rate_p50": 0.0051282052882015705, + "brake_rate_p90": 0.3589743673801422, + "stuck_share": 0.24609375, + "n_plans_mean": 195.0, + "success_reachable": 0.5679012537002563, + "by_cat": { + "A": [ + 128, + 96 + ], + "B": [ + 74, + 22 + ], + "C": [ + 32, + 13 + ], + "D": [ + 13, + 0 + ], + "Dr": [ + 9, + 7 + ] + } + }, + "simulation_wall_s": 349.25640099999146 +} diff --git a/docs/experiment_round48_pre_h8.json b/docs/experiment_round48_pre_h8.json new file mode 100644 index 0000000..e774b76 --- /dev/null +++ b/docs/experiment_round48_pre_h8.json @@ -0,0 +1,109 @@ +{ + "config": { + "ckpt": "ml/runs/base_dag2_dag1/best.pt", + "samples": "ml/data/samples", + "tasks": null, + "split": "val", + "n": 256, + "K": 8, + "commit": 2, + "fb": 2.2, + "ki": 0.0, + "fb_scale": 0.0, + "fb_near": 0.2, + "fb_fallback": 0.0, + "kdecay": 0.9, + "kimax": 0.5, + "fb_every": 1, + "safety_try": 0, + "sel_w": 0.1, + "dls_safety": 1, + "fb_clear": 0.0, + "fb_cmin": 0.3, + "sub_refresh": 0, + "fb_block_gain": 0.5, + "dump": "ml/runs/round48_pre_h8_rows.json", + "out": "docs/experiment_round48_pre_h8.json", + "trace": null, + "select": "pre", + "replan": "empty", + "safety": 1, + "partial": 1, + "inc_cap": 1, + "gap_margin": 0.0, + "cert_batch": 1, + "steps": 1, + "z_scale": 1.0, + "len_w": 0.0, + "tie": 0, + "pre_h": 8, + "backoff": 0, + "max_sec": null, + "seed": 0, + "dls": "analytic", + "device": "cuda" + }, + "batch_size": 256, + "batch_seed_rule": "same seed per batch", + "checkpoint_sha256": "f7f686fd8ee92fb6948fbcc4ee954636065ad87bb54f661c4f8f575bc16c2ce1", + "tasks_sha256": "249bd93457825cda98c59e64d9a096d3473c69aeb3553de1dea6d9e56be71772", + "kin_fp": "2ebcbf17", + "act_scale": 1.0, + "metrics": { + "n": 256, + "n_ref": 256, + "success": 0.51953125, + "collision_free_success": 0.51953125, + "time_ok_1p3": 0.28125, + "collision_rate": 0.0, + "collision_steps_mean": 0.0, + "travel_ratio_median": 2.6749093532562256, + "time_mean_s": 2.445413589477539, + "brakes_mean": 20.26953125, + "start_fail": 0.0, + "goal_ratio_2s": 0.2660874128341675, + "err_fail_med": 201.30308532714844, + "err_success_med": 0.22553904354572296, + "dls_share": 0.6328125, + "time_budget": "teacher×2(≥3 s)", + "speed_ratio_p50": 1.0000016689300537, + "speed_ratio_p95": 1.0000101327896118, + "speed_ratio_max": 1.0000101327896118, + "over_vmax_rate": 0.0, + "accel_ratio_p95": 1.0000016689300537, + "accel_ratio_max": 1.0000101327896118, + "reverse_p50": 0.25132274627685547, + "reverse_mean": 0.25476565957069397, + "reverse_moving_p50": 0.31292515993118286, + "moving_share_p50": 0.9629629850387573, + "brake_rate_mean": 0.10394632816314697, + "brake_rate_p50": 0.0051282052882015705, + "brake_rate_p90": 0.34871795773506165, + "stuck_share": 0.2578125, + "n_plans_mean": 195.0, + "success_reachable": 0.547325074672699, + "by_cat": { + "A": [ + 128, + 92 + ], + "B": [ + 74, + 20 + ], + "C": [ + 32, + 14 + ], + "D": [ + 13, + 0 + ], + "Dr": [ + 9, + 7 + ] + } + }, + "simulation_wall_s": 338.30686029999924 +} diff --git a/docs/探索日志.md b/docs/探索日志.md index dadd3ac..41b3b59 100644 --- a/docs/探索日志.md +++ b/docs/探索日志.md @@ -38,7 +38,8 @@ | 2 | ~~全拒时缩步顶上~~(`--backoff`) | 四臂实测:转化率 7.7%→37%(能救回停步),但到达 0.5234→0.5156 **不赚**;且它单独把 `brake_rate` 改善 16% 而行为没变好 ⇒ **可以绕过 §9.2 的刹停判据**,这是仪表漏洞不是收益 | **已判掉**(轮次 43);同时把 §9.2 的刹停口径标记为"不可由缩步单独满足" | | 3 | ~~白费比例惩罚~~(`select=ep_waste --len_w`) | 三臂实测行程比不降反升,给出原因:**罚的是没被执行的那段地平线**(16 步打分地平线 vs 实际提交 2 步) | **已判掉**(轮次 42);其诊断直接引出 #29(把打分地平线换成真会执行到的位置) | | 3c | **#29 打分地平线 = 被执行的前缀**(`select=pre`:用 `fut[:,:,commit_n]` 的终点误差代替 `fut[:,:,-1]`) | 两 seed 独立复现:2 s 误差比符号检验 192:64(p=5e−16)/ 191:65(p=1.5e−15),时限内 +6.64/+4.30 pp,行程比 −0.171/−0.171,**碰撞仍 0**;到达只 +5/+3 题(McNemar p=0.42/0.68 ⇒ 噪声);代价是到达题末态误差 0.22→0.42 mm(判据壳内但余量 4.6×→2.4×) | **正向(时限/进度显著、到达未显著)**,作可选口径入库,不改默认。下一试 #30 | -| 3d | **#30 前瞻长度曲线**(把打分步长做成 `pre_h`,扫 h=2/4/8/16,16=现 endpoint) | 若时限收益随 h 增大而塌、精度随 h 增大而恢复 ⇒ 形态应是"前瞻长度随剩余距离收缩",而不是二选一 | 待实现(`pre` 已落,只差把 `commit_n` 换成参数) | +| 3d | ~~#30 前瞻长度曲线~~(`pre_h`,h=2/4/8/16) | 轮次 48 四点实测:时限内 0.2656/0.2813/0.3047/**0.3320**,2 s 误差比符号检验随 h 缩短单调增强(p=2.4e−6/1.8e−12/4.9e−16),**到达四点全在噪声内**;末态误差 0.2175/0.2255/**0.3301/0.4151** ⇒ 代价集中在 h≤4;h=8 是坏点(行程比 2.6749 反而最差) | **已完成**:形状=进度单调、精度阶跃在 h≤4。作废 #26,派生 **#31** | +| 3e | **#31 门控地平线**(远端用短前瞻、近终段用整条地平线,一个阈值参数) | 轮次 48 的曲线直接给出机制:时限收益来自短前瞻,精度损失来自"近终段没有终端代价"。若两者能解耦,`time_ok` 与 `err_success_med` 就不必此消彼长 | 待实现(`pre_h` 已在,只差按当前误差选 h) | | 3b | ~~行程惩罚 `ep_len`(罚候选累计行程)~~ | 三臂实测行程比 2.6216/2.6548/2.6719 vs 对照 2.6158 ⇒ **不降反升**,只换来 +2 pp 时限 | **负结论**,被 3 取代 | | 4 | **一步角点的标定**(E1 那条线:`mf_target='mid'` 把自举导数移到中点) | 解析高斯场判据:`sq` 只线性收敛(结构性少修一半)、`mid/lin` 二次收敛;实测部署角偏差 MF 3.851 → `mid` 2.364(0.61×);但**线上一步输出比自身两段采样离老师远 10 倍**(4.326 vs 0.434) | 开关已落、默认关;要付训练,且受"一步与认证/DAgger 共同标定"约束 | | 5 | **认证进 20 ms**(#16/#18) | GPU 周期 P50 33.5 ms,几何宽相位占大头;f32 认证需先抬 eps 到 2e−4 mm | 未解,是验收硬门槛 | @@ -112,6 +113,28 @@ - **对 `backoff` 的预期与判据**:全拒意味着"连第 1 步的端点或中点已经穿进障碍",缩步能不能救取决于**穿得有多深**(穿 0.1 mm 救得回,穿 3 mm 救不回)。这个数转储里没记(只记被选中那条),所以直接由 `backoff_mean`/`reject_all_mean` 来量: `reject_all_mean ≈ 原全拒次数`(=backoff_mean+brakes_mean,与轮次 33 cap 的 19.55 可比),`backoff_mean/(backoff_mean+brakes_mean)` 就是"缩步能救回的比例"。这是补跑(#22)要读的第一个数。 +## 轮次 48:#30 打分地平线四点曲线——进度收益是剂量-反应关系,而精度代价只集中在 h≤4;h=8 是个坏点 + +- **设计**:`select=pre` 加 `--pre_h`(0=commit_n)。同 seed=0、同配方(`K=8/commit_n=2/fb=2.2/inc_cap=1/cert_batch=1`),只改打分取 `fut` 的第几步。h=2 与 h=16 两点已在盘(轮次 46 / 45,且控制臂已证跨窗口逐位复现),本轮补 **h=4、h=8**。 +- **曲线(n=256 全部四点)**: + + | 打分地平线 | 时限内(≤1.3×老师) | 2 s 误差比 | 到达题末态误差中位 | 到达 | 行程比中位 | 刹停/题 | 执行碰撞 | + |---|---|---|---|---|---|---|---| + | h=16(现 `endpoint`) | 0.2656 | 0.2792 | 0.2175 mm | 0.5234 | 2.6158 | 19.55 | **0** | + | h=8 | 0.2813 | 0.2661 | 0.2255 mm | 0.5195 | **2.6749** | 20.27 | **0** | + | h=4 | 0.3047 | 0.2350 | 0.3301 mm | 0.5391 | 2.5619 | 20.41 | **0** | + | h=2(=提交窗口) | **0.3320** | **0.1702** | 0.4151 mm | 0.5430 | **2.4449** | 19.84 | **0** | + +- **逐题配对(对同一控制)**:`goal_ratio_2s` 符号检验 h=8 **166 好/90 差 p=2.4e−6**、h=4 **184/72 p=1.8e−12**、h=2 **192/64 p=4.9e−16**(轮次 46)——三个 h 都显著、显著性随 h 缩短单调增强。到达则全在噪声内:h=8 赢 8 丢 9(净 −1,p=1.0)、h=4 赢 10 丢 6(净 +4,p=0.45)、h=2 赢 15 丢 10(净 +5,p=0.42)。全程末态误差的符号检验 h=8 是 142/114(p=0.091)、h=4 是 130/126(p=0.85)⇒ **末态误差的总体分布没被推动,被推动的是"到达题组内到达那一刻的误差"**。 +- **三条读法(比"哪个 h 最好"有用)**: + 1. **进度/时限关于 h 是单调的**(前瞻越短 ⇒ 时限内越多、2 s 时越贴近目标)。这是**剂量-反应关系**,比单点 A/B 强:不是一次涨落,而是整条轴同向。⇒ §9.2 的"到达用时 ≤ 老师×1.3"这一栏的真瓶颈之一确实是**打分地平线长于执行地平线**。 + 2. **精度代价不是均摊的,几乎全在 h≤4**:h=8 相对控制的末态到达误差只 +3.7%(0.2175→0.2255),h=4 就 +52%(→0.3301)、h=2 +91%(→0.4151)。⇒ 病因不是"前瞻短",而是**近终段没有前瞻**(MPC 缺 terminal cost 的教科书症状)。正确的形态是**前瞻长度随剩余距离收缩**(#31),不是在 h 上挑一个折中值。 + 3. **h=8 是曲线上的坏点**:时限只 +1.56 pp、到达 −1 题、**行程比反而最差**(2.6749 > 控制 2.6158)。⇒ "把地平线砍一半"这种渐进方案被自己的中间点否掉了:要么收到提交窗口附近,要么别动。 +- **按类别**:h=4 时 A 类回到控制水平(96/128),B +2、C +2;h=2 时 A −1、B +2、C +3。⇒ 轮次 45 那个"短前瞻在开阔区纯亏"的担忧在 h=4 上消失(`tie` 是另一码事:它换成的是余量而非进度)。 +- **判据状态**:四点全部 `collision_rate=0`、`over_vmax_rate=0`、`start_fail=0`;`speed_ratio_p50/p95/max` 与 `accel_ratio_max` **四点的值逐位相同**(1.000002/1.000010/1.000010/1.000010)⇒ 收益不是放松安全或超速换来的。成本侧的**实测**(不是推算)证据:`n_plans_mean` 四点都是 **195.0**,即每颗题的规划次数没变 ⇒ 认证与几何调用的次数不变,改变的只是同一批点里取哪一个来排序。`dls_share` 0.613/0.633/0.629/0.637 不单调,暂不作结论。 +- **预注册判读规则的落点**:规则写的是"若 time_ok/2 s 误差比随 h 单调变差 ⇒ 超出提交窗口的前瞻有害,#26 一并作废"。观测正是单调 ⇒ **#26(在前缀口径上再加白费惩罚)作废**;改为 **#31:门控地平线**(远端用 `pre`、近终段用整条地平线),一个参数、机制由本曲线直接给出。 +- **状态**:`pre_h` 作可选口径入库,默认仍是 `endpoint`。§9.2 的"时限内"读数最好的一栏从 0.2969(K=16 endpoint)换到 **0.3320(K=8 h=2)**,但到达没有显著变化,所以**不换主口径**。 + ## 轮次 46–47:#29 把候选打分的地平线换成「这一轮真会执行到的位置」——链上第一个正向杠杆,两个 seed 独立复现 - **诊断(不是新想法,是旧负结论给出的原因)**:`select='endpoint'` 按**整条 16 步地平线末端**的终点误差给 K 条候选排序,而每轮只提交 `commit_n=2` 步。对被安全层截断的候选,那个终点**根本到不了**;对满前缀候选,它是 14 步开环外推。轮次 42 判掉 `ep_len/ep_waste` 时写的就是同一件事——"罚的是没被执行的那段地平线"。`select='pre'` 把打分点换成 `fut[:, :, commit_n-1]`(这一轮真正会走到的位置),**同一次 `goal_err` 只换点集,机制上不增加量级**。