From e7d1a395190822b02fe140f875431a36c7a6886a Mon Sep 17 00:00:00 2001 From: cbb <2625274797@qq.com> Date: Tue, 20 Oct 2026 21:51:54 +0800 Subject: [PATCH] =?UTF-8?q?exp:=20=E8=BD=AE=E6=AC=A138=E2=80=94=E2=80=94?= =?UTF-8?q?=E4=B8=A4=E6=AE=B5=E6=8E=A8=E7=90=86=E5=BC=80=E7=8E=AF=E6=9B=B4?= =?UTF-8?q?=E8=B4=B4=E8=80=81=E5=B8=88=E3=80=81=E8=A1=8C=E7=A8=8B=E6=AF=94?= =?UTF-8?q?=E6=9B=B4=E8=BF=911=EF=BC=8C=E4=BD=86=E9=97=AD=E7=8E=AF?= =?UTF-8?q?=E5=88=B0=E8=BE=BE=E9=99=8D14.8pp=EF=BC=9A=E7=93=B6=E9=A2=88?= =?UTF-8?q?=E7=A7=BB=E5=88=B0=E5=AE=89=E5=85=A8=E5=B1=82=E6=8B=92=E7=BB=9D?= =?UTF-8?q?=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/experiment_round36_steps2_cap0.json | 73 ++++++++++++++++++++++++ docs/experiment_round36_steps2_cap1.json | 73 ++++++++++++++++++++++++ docs/探索日志.md | 24 ++++++++ 3 files changed, 170 insertions(+) create mode 100644 docs/experiment_round36_steps2_cap0.json create mode 100644 docs/experiment_round36_steps2_cap1.json diff --git a/docs/experiment_round36_steps2_cap0.json b/docs/experiment_round36_steps2_cap0.json new file mode 100644 index 0000000..303c234 --- /dev/null +++ b/docs/experiment_round36_steps2_cap0.json @@ -0,0 +1,73 @@ +{ + "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/round36_steps2_cap0_rows.json", + "out": "docs/experiment_round36_steps2_cap0.json", + "trace": null, + "select": "endpoint", + "replan": "empty", + "safety": 1, + "partial": 1, + "inc_cap": 0, + "gap_margin": 0.0, + "cert_batch": 0, + "steps": 2, + "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.42578125, + "collision_free_success": 0.42578125, + "time_ok_1p3": 0.35546875, + "collision_rate": 0.0, + "collision_steps_mean": 0.0, + "travel_ratio_median": 1.5711719989776611, + "time_mean_s": 1.6664220094680786, + "brakes_mean": 86.30859375, + "start_fail": 0.0, + "goal_ratio_2s": 0.29959768056869507, + "err_fail_med": 405.61505126953125, + "err_success_med": 0.24314510822296143, + "dls_share": 0.453125, + "time_budget": "teacher×2(≥3 s)", + "speed_ratio_p50": 1.6600004434585571, + "speed_ratio_p95": 1.6600035429000854, + "speed_ratio_max": 1.660003662109375, + "over_vmax_rate": 0.91015625, + "accel_ratio_p95": 1.0188239812850952, + "accel_ratio_max": 1.4423871040344238 + }, + "simulation_wall_s": 304.77464890001283 +} diff --git a/docs/experiment_round36_steps2_cap1.json b/docs/experiment_round36_steps2_cap1.json new file mode 100644 index 0000000..10f6f9a --- /dev/null +++ b/docs/experiment_round36_steps2_cap1.json @@ -0,0 +1,73 @@ +{ + "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/round36_steps2_cap1_rows.json", + "out": "docs/experiment_round36_steps2_cap1.json", + "trace": null, + "select": "endpoint", + "replan": "empty", + "safety": 1, + "partial": 1, + "inc_cap": 1, + "gap_margin": 0.0, + "cert_batch": 0, + "steps": 2, + "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.39453125, + "collision_free_success": 0.39453125, + "time_ok_1p3": 0.296875, + "collision_rate": 0.0, + "collision_steps_mean": 0.0, + "travel_ratio_median": 1.8436782360076904, + "time_mean_s": 1.9299010038375854, + "brakes_mean": 86.15625, + "start_fail": 0.0, + "goal_ratio_2s": 0.384182870388031, + "err_fail_med": 376.4237976074219, + "err_success_med": 0.2933140993118286, + "dls_share": 0.4453125, + "time_budget": "teacher×2(≥3 s)", + "speed_ratio_p50": 1.0000016689300537, + "speed_ratio_p95": 1.0000038146972656, + "speed_ratio_max": 1.0000101327896118, + "over_vmax_rate": 0.0, + "accel_ratio_p95": 0.8507659435272217, + "accel_ratio_max": 0.9923425912857056 + }, + "simulation_wall_s": 319.5858334999939 +} diff --git a/docs/探索日志.md b/docs/探索日志.md index 2925cab..61d478b 100644 --- a/docs/探索日志.md +++ b/docs/探索日志.md @@ -796,6 +796,30 @@ - **收敛阶分开"有偏"与"无偏"**(区间长度 0.2→0.1→0.05,σ=2 的相对偏差):`sq`(按方案抄的 (1−λ)²/λ²)0.426→0.133→0.057,比值 ≈0.4 ⇒ **只有线性收敛 = 结构性少修一半**;`lin`(换成系数和为 1 的线性权重)0.042→0.015→0.004、`mid`(整条修正移到中点)0.147→0.042→0.010,比值 ≈0.25 ⇒ 二次收敛,只剩积分误差。 - 跨整段 (0,1) 时**所有**单点导数写法都不可信(σ=2:sq 1.92、lin 1.84、mid 4.15 倍偏差),跨半段就降到 0.44–0.85 ⇒ 与 E1-b 的实测同向:**一步跨完本身难,两段就便宜一个量级**。这不是训练的毛病,是写法本身的量级。 - 测试 35→38 项(缩步档 3 项)+ 新文件 `tests/test_meanflow_targets.py` 3 项 ⇒ 共 41 项。 +- **目标写法开关已落地但默认不启用**(`ml/model/meanflow.py` 新增 `avg_velocity_target(..., target='mf'|'lin'|'sq'|'mid', lam)`,`ml/train.py:162` 从配置读 `mf_target`/`mf_lam`): + - 默认 `mf` 分支与原实现**逐位相同**(测试用同一批输入把老写法重构出来对拍 `u`、`u_tgt`、`z` 三个张量,rtol=atol=0)。 + - 接线自证:把解析高斯场做成桩喂进 `avg_velocity_target`,float32 下三种写法的偏差与 float64 解析值逐位到小数四位一致(sq 0.4262→0.1332→0.0567、lin 0.042→0.0149→0.0038、mid 0.1465→0.0422→0.0104)⇒ z_c、切向量、r 槽换位没接错。 + - 加这个开关不是为了训它,是为了"E2 若要训,先有一条不改默认路径的口子"。要不要付这次训练,等 #21 的判别结果(见轮次 38)。 + +## 轮次 38:把 `--steps` 打通之后,闭环反而变差——瓶颈从"动作质量"移到了"安全层拒绝率" + +- **动机**:E1-b 实测同一个模型的一步输出比它自己的两段采样离老师远 **10 倍**(4.33 vs 0.43)。那就先别急着训练——直接把推理段数当自变量,量闭环。`ml/eval/eval_cl.py` 加 `--steps`(默认 1,发布口径不变),同一 256 题、同 seed、同配方只改段数: + + | 口径 | 到达 | 时限内(≤1.3×老师) | 刹车/题 | 到点耗时 | 行程比(中位) | 成功题末态误差 | DLS 接管份额 | + |---|---|---|---|---|---|---|---| + | steps=1 cap=0(=轮次33 base) | 0.5742 | 0.3906 | 19.25 | 2.31 s | 2.445 | 0.189 mm | 0.625 | + | steps=2 cap=0 | 0.4258 | 0.3555 | **86.31** | 1.67 s | **1.571** | 0.243 mm | 0.453 | + | steps=1 cap=1(=轮次33 cap) | 0.5234 | 0.2656 | 19.55 | 2.49 s | 2.616 | 0.218 mm | 0.613 | + | steps=2 cap=1 | 0.3945 | 0.2969 | 86.16 | 1.93 s | 1.844 | 0.293 mm | 0.445 | + + (`docs/experiment_round36_steps2_cap{0,1}.json`;steps=4/8 同批续跑) +- **反直觉但自洽的一组数**:两段推理**开环更贴老师**(E1-b:0.43 vs 4.33)、**行程比更接近 1**(1.571 vs 2.445)、**到了的题还更快**(1.67 vs 2.31 s),但闭环到达掉 14.8 个百分点。逐题对照:108 题两者都到、**39 题只有 1 步能到、只有 1 题是 2 步独有** ⇒ 不是"换了一批题",是同一批题里 1 步原本能做对的那部分被卡住了。 +- **卡点在安全层不在策略**:刹车从 19.25 → 86.3/题(4.5 倍),未到达组的刹车中位数从 45 → 176(几乎每步都被拒 ⇒ 原地冻结,末态误差 p50 也从 230 → 406 mm)。也就是说**发布的那 57.4% 是与"一步那套偏置且被削弱过的动作"共同标定出来的**:策略、反馈增益、认证口径、DAgger 采集分布四者都围着它。 +- **两种解释必须分开,否则下一步会走错**: + - (A) 两段动作确实更危险(位移更大 ⇒ 真的穿模); + - (B) 认证过度保守(界随位移线性放大 ⇒ 明明安全的更大步也被拒)。 + 判别实验:`--safety 0` 的 steps=1 vs steps=2 对照 + 候选多样性探针(两段积分是否把 K 条候选吸到一起,让安全层没有备选可退)+ steps 的 B=1 代价实测。脚本 `ml/runs/_safetyoff_ab.sh`,结果见下面补记。 +- **对 K-MF 那条训练路线的直接含义**:把角点"训准"会让动作分布变成现在两段那样 ⇒ 按当前认证口径,到达率可能**先降**。所以训练不是下一步,先做 (A)/(B) 判别;若是 (B),收紧认证(细分/更紧的界)比训模型便宜得多,而且是 50 Hz 也必须的那块。 ## 分支清理(2026-10-20)