diff --git a/docs/探索日志.md b/docs/探索日志.md index f114404..ce39a32 100644 --- a/docs/探索日志.md +++ b/docs/探索日志.md @@ -399,6 +399,26 @@ - 准确率与规划频率的 trade-off:commit1 42.2%(不可 50Hz)、commit3 36.3%、commit6 14.8%。 - **下一步**:① 在 commit=3/4 的实时节奏下找准确率提升(候选平均、dag3_fe 冻结编码器、更高 gain);② 把 gm_groups 同步到 JS(gapMatrix 只算 8 组);③ 降低 JS 安全层拒绝率(margin/认证预算调参)。 +## 轮次 25:实时节奏下的准确率探索 + 推理提速(exp: `exp/dagger-deploy`) + +- **目标**:在 50 Hz 可行的节奏(commit=3,60 ms 周期)下提升准确率。 +- **效率优化(有效)**: + - `Kin.gm_groups`:特征只算 8 组间隙(数值 diff 0),features 10.4→**7.1 ms**; + - **onnxruntime CPU 推理 3.9 ms**(PyTorch 11.1 ms,部署端本来就是 ONNX); + - 单次规划 ≈ 7.1(features)+3.9(推理)+11(DLS)+8(安全)+2 ≈ **32 ms p50 / ~45 ms p99**; + - 异步部署下 tick(执行步 + 碰撞检查)2–3 ms → **50 Hz 控制可行**;commit=3(60 ms 队列)可覆盖规划 p99。 +- **准确率尝试(n=256,commit=3,gain1.8,safety_partial)**: + +| 方法 | 到达 | time_ok | 碰撞 | ratio2s | 刹停 | +|---|---|---|---|---|---| +| dag2 + consist(基线) | **36.3%** | 16.4% | 1.6% | 0.277 | 14.3 | +| dag2 + 候选平均(select=average) | 29.7% | 20.3% | 0.4% | 0.432 | 55.9 | +| 冻结编码器模型(dag3_fe) | 34.4% | 14.8% | 2.0% | 0.332 | 15.8 | +| dag2 + commit=4 | 28.9% | 8.2% | 3.5% | 0.339 | 10.5 | + +- **结论**:候选平均、冻结编码器、更稀疏规划**均未超过 36.3%**。**50 Hz 节奏下的最佳配置 = dag2 + commit=3 + consist + gain1.8 + safety_partial:到达 36.3% / 碰撞 1.6% / ratio2s 0.277**(相对非实时的 42.2% 差 5.9 pp)。 +- **下一步**:若要把实时准确率再拉高,需要把单次规划再压到 ~22 ms 以支持 commit=2(40 ms 周期,预计 ~39%);或提升模型本身精度(训练侧)。 + ## 分支清理(2026-10-20) - `feat/fb-mix`(8e5431c):反馈混合方案的中间分支,**已验证是 `exp/dagger-deploy` 的祖先**(所有提交都在后者历史里),本地/远端分支删除,内容保留在 exp/dagger-deploy。 diff --git a/ml/sim/closed_loop.py b/ml/sim/closed_loop.py index 721b870..f064216 100644 --- a/ml/sim/closed_loop.py +++ b/ml/sim/closed_loop.py @@ -237,6 +237,11 @@ def rollout(model, kin, tasks, device, K=8, safety=False, seed=0, max_sec=None, score = torch.where(last_ok[:, None], -(d2 * w).sum(-1), torch.zeros_like(d2[..., 0])) order = torch.sort(score, dim=-1, descending=True, stable=True).indices pick = order[:, 0] + if select == 'average': # 2026-10-20:候选平均(平滑误差)——所有候选置为 K 条动作的均值 + inc = inc.mean(1, keepdim=True).expand_as(inc).contiguous() + K_eff = 1 + else: + K_eff = K commit = inc[ar, pick, r:r + commit_n] if collect is not None: # 反馈蒸馏:收集与部署完全一致的 (特征, 复合动作=模型输出+目标反馈) collect.append((feat.detach().float().cpu(), inc[ar, pick].detach().float().cpu())) @@ -244,7 +249,7 @@ def rollout(model, kin, tasks, device, K=8, safety=False, seed=0, max_sec=None, if safety and safety_partial: # 2026-10-20:允许「部分安全前缀」——执行到第一个不安全步为止,而不是全拒刹停 maxlen = torch.zeros(B, dtype=torch.long, device=device) chosen = torch.zeros(B, commit_n, 6, device=device); chosen_k = pick.clone() - for kk in range(K): + for kk in range(K_eff): ck = inc[ar, order[:, kk], r:r + commit_n] pts = qe[:, None] + torch.cumsum(ck, 1) mids = torch.cat([qe[:, None], pts[:, :-1]], 1) + 0.5 * ck @@ -263,7 +268,7 @@ def rollout(model, kin, tasks, device, K=8, safety=False, seed=0, max_sec=None, elif safety: ok_any = torch.zeros(B, dtype=torch.bool, device=device) chosen = torch.zeros(B, commit_n, 6, device=device); chosen_k = pick.clone() - for kk in range(K): + for kk in range(K_eff): ck = inc[ar, order[:, kk], r:r + commit_n] pts = qe[:, None] + torch.cumsum(ck, 1) mids = torch.cat([qe[:, None], pts[:, :-1]], 1) + 0.5 * ck