diff --git a/docs/探索日志.md b/docs/探索日志.md new file mode 100644 index 0000000..ea1adce --- /dev/null +++ b/docs/探索日志.md @@ -0,0 +1,82 @@ +# 探索日志:Transformer 机械臂闭环控制 + +长期锚点:`docs/Transformer轨迹拟合训练方案.md` §9.2(部署形态 = 策略 + 安全层)。 +验收口径(§9.2):实际执行碰撞 = 0;held-out 可达任务到达率 ≥ 98%;到达用时 ≤ 老师 ×1.3;关节行程 ≤ 现有规划器 ×1.10;冷启动 < 10 ms;每次推理 + 安全认证 P99 < 20 ms;刹停发生率 < 2% 的推理周期;策略单独(关安全层)碰撞率 < 3%。 + +评测约定:val 任务、部署节奏(r = 3 重规划、1 段采样、K=8);「纯策略」= 关安全层;「部署」= 开安全层。时延:桌面 RTX 3090 上 `sample_k(B=64, K=8)` 墙钟均值(均值,非 P99);浏览器 ONNX P99 以 §9.2 R4 的独立测量为准。 + +## 轮次 0:基线(2026-10-18,main) + +- **假设**:模型开环已拟合老师(末端 ~6 mm),闭环失败另有原因。 +- **判据**:reach = 0 且碰撞 ≈ 100% 即失败;需同时报告碰撞 / 到达 / 精度 / 时延。 +- **配方**:`ml/runs/base/last.pt`(step 14000,旧配方、act_scale=1.0),n=256。 +- **对照**:老师回放 reach 1.0 / 碰撞 0;H1_oracle(老师提线走 rollout)reach 1.0、碰撞 0、轨迹偏差 p99 4.6e-4°。 +- **指标**:到达 **0%**;碰撞 **99.6%**;精度 ol_fk 5.98 mm / ol_best 2.92 mm / ol_div 0.655,2 s 误差比 0.755;时延未测。 +- **结论**:仿真/滚动无误,失败在策略输出。闭环对每步残差极敏感(老师动作加 σ=0.05×STEP 即 reach 1.0→0.218)。 + +## 轮次 1:数据规模能否救闭环(main,负结论) + +- **假设**:训练数据不足导致分布外状态无覆盖。 +- **判据**:若闭环状态到训练集最近邻距离大,且密度缩放无法在误差尺度内缩小差距,则加大同类数据无效。 +- **配方**:191 万老师状态最近邻分析;6 维密度缩放 d∝N^(−1/6)。 +- **对照**:起点(老师分布内)最近邻。 +- **指标**:闭环状态最近邻 p50 **21.5°**(起点 13.2°);数据翻 4 倍仅降 ~21%,与 0.02° 误差尺度差三个量级。 +- **结论**:加大同类老师数据无效;需要「不同的数据」(闭环状态标注)。 +- **下一步**:DAgger 或状态扰动数据。 + +## 轮次 2:合成扰动状态微调(main,负结论) + +- **假设**:偏移 1.5° 状态的老师标注可补足闭环状态覆盖。 +- **判据**:若 success 仍 0 或开环精度退化,则配方不成立。 +- **配方**:2000 个扰动起点(σ 混合 0.5/1/2/4°)→ 老师重规划(2000/2000 到达)→ 36k 样本 → 从 base/last.pt 微调 3000 步(lr 3e-4 / 1e-4 两轮)。 +- **对照**:base/last.pt。 +- **指标**:碰撞 99.6%→**48.4% / 60.4%**;到达仍 **0%**;开环 6→**15.3 / 16.4 mm**(退化 2.5×);ratio2s 0.927/0.893。 +- **结论**:只学会了「保守避撞」,开环精度被带偏,success 仍 0;此配方不成立。 +- **下一步**:改训练标签(绝对目标)或真实 DAgger。 + +## 轮次 3:绝对目标参数化(exp: `feat/abs-target`,负结论) + +- **假设**:模型从当前状态外推增量(判别 ρ=1.54),改为绝对目标标签可让输出指向参考位置。 +- **判据**:一步采样开环误差需回到 <10 mm,闭环 success > 0;否则参数化不可行。 +- **配方**:`ABS_TARGET=1` 重打主数据(201 万样本,Y=16 步绝对目标/180),train/rollout/ckpt 适配;从零训练 9950 步(p_neq 预热 5000)。过程中修复前缀噪声增广把 eps 直接加到绝对目标(≈18° 污染)的 bug。 +- **对照**:base/last.pt(ol_fk 5.98 mm、reach 0%)。 +- **指标**:一步采样动作误差 **31°**(4/8 段 2.3°/2.8°);ol_fk 4000/6000/8000 步 = 74.6/140.4/139.0 mm;闭环 **0% / 100%**(1 段与 4 段皆然);时延未测。 +- **结论**:绝对目标的一步流匹配在 MeanFlow 头上学不动(过预热后 5000 步无下降趋势);此配方不成立。分支已推送远端 `217a70b`(本地分支可删,远端保留可复现)。 +- **下一步**:回归增量口径,上真实 DAgger。 + +## 轮次 4:真实 DAgger 1 轮(main,部分有效) + +- **假设**:策略自己走到的状态(离训练集 21.5°)+ 老师重标注,可让模型学会在偏移状态上行动。 +- **判据**:reach 是否从 0 抬头;同时看碰撞、开环精度、时延。 +- **配方**:`ACT_SCALE=1.0 DAG_ROUNDS=1 DAG_N=2000 bash ml/dagger/run.sh base ml/runs/base/last.pt`(采集 2000 题 → 老师重规划 → 打包 → 微调 15000 步,lr 3e-4;主数据 + DAgger 混合)。 +- **对照**:base/last.pt。 +- **指标**:碰撞 99.6%→**40.2%**(8000 步 36.9%,10000 步 58.8%);到达 **0%**,仅微调 12000 步时出现 **0.4%(2/512)**;开环退化 6→**15.7 mm**;ratio2s 0.87–0.92;时延未测。 +- **结论**:DAgger 数据确实教会避撞,但微调把主分布带偏(开环退化),到达仍近 0;单独 DAgger 不是终点。 +- **下一步**:在 DAgger 模型上加目标反馈(模型前馈 + DLS 反馈)。 + +## 轮次 5:模型前馈 + DLS 目标反馈(exp: `feat/fb-mix`,历史最佳) + +- **假设**:模型擅长开环轨迹/避撞,但不指向目标;把 DLS 朝目标的反馈叠加到候选动作上,可把「走偏」拉回目标。 +- **判据**:部署口径(+安全层)reach 显著 > 0 且碰撞 < 3%(§9.2 策略单独碰撞线)、刹停可控;否则不成立。 +- **配方**:`closed_loop.rollout(fb_gain=...)`:`inc += fb_gain · DLS(qe→T,R, n=1)`(加在所有候选上,安全层评估带反馈的候选)。模型 `ml/runs/base_dag1/best.pt`(DAgger 轮 4 的 best,12000 步)。n=128,val。 +- **对照**:base/last.pt + 同反馈;DAgger 模型 + 无反馈。 +- **指标(n=128)**: + +| 配置 | 到达 | 碰撞 | 精度 ratio2s | 刹停/题 | 时延 | +|---|---|---|---|---|---| +| DAgger 模型, gain 0 | 0% | 44.5% | 0.873 | 0 | — | +| DAgger 模型, gain 1.0, 关安全层 | 29.7% | 73.4% | 0.370 | 0 | — | +| **DAgger 模型, gain 1.0, 开安全层** | **20.3%** | **2.3%** | **0.480** | **21.9** | **12.58 ms/次**(B=64,K=8,桌面 3090) | +| base 模型, gain 1.0, 关安全层 | 0% | 94.5% | 0.554 | 0 | — | + +(另测 n=32 复核:gain 1.0 + safety → reach 25.0%、碰撞 6.2%、ratio2s 0.588。) + +- **结论**:**反馈混合是首个把到达率从 0 拉到 20%+ 的机理**;安全层把碰撞从 73% 压到 2.3%(部署口径),代价是刹停 21.9 次/题(远超 §9.2 的 <2%/周期)。精度 ratio2s 0.48(2 s 时误差缩一半),时延 12.58 ms/次接近 §9.2 的 20 ms(推理+认证)门槛。 +- **与历史最佳/基线对比**:reach 0→20.3%、碰撞 99.6→2.3%、ratio2s 0.755→0.480;开环精度仍退化(DAgger 微调导致 15.7 mm vs 基线 5.98 mm)。 +- **漂移检查**:main = 70654e4(无新提交);工作区仅用户个人 html 未跟踪;数据口径 act_scale=1.0 与 ckpt 一致;`feat/abs-target` 已推送远端;本次实验在独立分支 `feat/fb-mix`。 +- **下一步**:扫更大 gain(1.2–2.0)与增益衰减;目标是把刹停次数降下来、到达率再提升,并测 ONNX/浏览器时延。 + +## 轮次统计 + +- 连续无实质进展轮数:0(轮次 5 出现实质进展:reach 0→20.3%)。 +- 历史最佳(部署口径):轮次 5,`ml/runs/base_dag1/best.pt` + `fb_gain=1.0` + safety:reach 20.3%、碰撞 2.3%、ratio2s 0.480、brakes 21.9/题、时延 12.58 ms/次(B=64,K=8)。 diff --git a/ml/sim/closed_loop.py b/ml/sim/closed_loop.py index 4823a82..d56b84e 100644 --- a/ml/sim/closed_loop.py +++ b/ml/sim/closed_loop.py @@ -141,7 +141,7 @@ class TeacherOracle: @torch.no_grad() def rollout(model, kin, tasks, device, K=8, safety=False, seed=0, max_sec=None, return_traj=False, use_sub=True, sub_override=None, - qp0=None, steps=1, z_scale=1.0, select='consist', oracle=None, replan='r3', sub_rule='cross'): + qp0=None, steps=1, z_scale=1.0, select='consist', oracle=None, replan='r3', sub_rule='cross', fb_gain=0.0): """use_sub=False:不用子目标(sf=0);sub_override=(subs [B,M,6] 绝对关节角, n [B] 个数 或 need [B] bool):冷启动时用给定途经点代替子目标头; qp0 [B,6]:起点的上一帧(默认 = q0,即静止起步)。steps:MeanFlow 采样段数;z_scale:噪声缩放; select:consist(部署口径:冷启动价值前瞻、之后与上一条已提交计划的一致性)/ value(每次都价值前瞻)/ first(不选,取第 0 条)。 @@ -190,6 +190,8 @@ def rollout(model, kin, tasks, device, K=8, safety=False, seed=0, max_sec=None, z = torch.randn(B * K, H, 6, device=device, generator=g) * z_scale act, val, sub = model.sample_k(feat, K, z, steps=steps) inc = act.float().clamp(-1, 1) * astep + if fb_gain > 0: # 实验(2026-10-20):目标反馈加在所有候选上(安全层也评估带反馈的候选) + inc = inc + fb_gain * dls_steps(kin, qe, T, R, n=1)[:, :, None, :] if cold: need = sub[:, 12] > 0.5 subs = q[:, None] + sub[:, :12].float().view(B, 2, 6) * 180