Files
Robot_Arm/docs/本机执行清单.md
T

223 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 本机执行清单(给本地 AI 逐条执行)
本文件是 Hark 对本机计算的唯一要求清单。按顺序执行,每一步把「回传」里的文件或输出原样交给用户,不要跳步,不要自行改代码。
所有命令在仓库根目录(G:\Robot_v2\机器人手臂)的 Git Bash 里运行。完成的条目由 Hark 在下一次提交里删掉。
## 已知结论(截至 2026-10-19 05:35 回传)
- 现有模型 `ml/runs/base/last.pt` 闭环 0% 到达:1 段采样碰撞 99.6%;4 段采样 94%;4 段 + 仿真安全层碰撞 0.78%,到达仍 0%。consist / value / first 三种选法结果几乎一样,问题出在候选本身,不在挑哪条。
- 三份代码审查逐行核对了滚动索引、前缀、提交、标签与执行的对齐,没有找到错位;但之前没有任何测试真正走过 `rollout()`。下面第 1 步的 H 段把「仿真错了」「前缀照抄」「子目标切换规则」「多峰」几种解释逐个分开。
- 之前「前 1 s 速度比 2.31×」按 6 轴角度直接相加,被 J5/J6 抖动和 pos 任务冻结的 J6 放大。H 段改为分轴、净位移、TCP 三种口径。
## 第 0 步:同步代码
```bash
git status --short # 有未提交的改动先 commit(git add -A && git commit -m "本机改动"),不要丢
git pull --rebase gitea main
git log --oneline -1 # 应是 Hark 的「diag: H 段(老师 oracle / 前缀消融 / 子目标规则 / 分轴指标)…」
```
- 训练控制台若开着,先点「停止」,确认没有 python 训练进程在跑。
- 不要启动训练、DAgger、M5。
## 第 1 步:闭环失败定位 H 段(约 35–50 分钟)
```bash
PYTHONUTF8=1 python -m ml.eval.diag_cl --ckpt ml/runs/base/last.pt --n 256 --out ml/runs/diag_cl.json
```
- 专用显存超过 22 GB 就 Ctrl+C,回传终端最后 30 行和已写出的 `ml/runs/diag_cl.json`(每段跑完就写一次,中断也保留已完成的段)。
- 现有 checkpoint 没有 EMA、没有 `act_scale`:脚本按原始权重、动作尺度 1.0 载入(输出里 `weights`=`model`、`act_scale_ckpt`=1.0),与之前各轮同口径。
- 回传:`ml/runs/diag_cl.json`。
### 输出键
| 键 | 内容 |
|---|---|
| `A_*`、`B_act_diff_deg` | 起点特征 Python 与数据集逐组差;两份特征下的动作差(与之前相同) |
| `C` | 旧部署口径(1 段采样、子目标旧规则 timeout)的失败形态。到达与碰撞改为只计每题自己的时限内,数字可能比上一轮略低 |
| `H1_oracle` | 老师当策略走完整 `rollout()`。`oracle` 字段:`max_dev_deg_before_dls`(DLS 接管前与老师轨迹的最大关节偏差,p50 / p99 / max)、`reach`、`collision`、`finish_minus_teacher_s`(完成时刻 − 老师时长)、`dls_used` |
| `H1_oracle_noise_0.05` / `_0.1` / `_0.2` | 老师动作每次规划加 N(0, σ²)(σ 以 STEP 为单位) |
| `H2_open_loop` | r = 3 的 val 行:`s{1,4}_prefix_orig`(前缀原样,执行窗口 3..5 的误差,另含 `prefix_copy_err_deg_mean`)vs `s{1,4}_prefix_zeroed`(前缀置零) |
| `H2_replan_empty_s1` / `_s4` | 队列空了才规划(每次 r = 0),其余同新部署默认 |
| `H3_headsub_cross_s{1,4}` | 子目标头 + 越过顶点规则(新部署默认) |
| `H3_headsub_timeout_s{1,4}` | 子目标头 + 旧规则(< 5° 或 1.5 s 超时,旧部署) |
| `H3_teachersub_cross_s{1,4}` / `H3_teachersub_timeout_s{1,4}` | 老师真实途经点全表,两种切换规则 |
| `H3_nosub_s{1,4}` | 不用子目标 |
| `H4_open_loop` | 按前缀长度 r = 0..3 分组的执行窗口误差 \|Σ(act − Y)·STEP\|(度),1 段与 4 段采样 |
每个闭环变体(H1–H3)都带同一组指标:`reach`、`collision`(cat ≠ D、时限内)、`goal_ratio_2s_p50`、`end_goal_err_mm_p50`、`first_hit_s_p50`、`t_done_over_teacher_p50`、`brakes_p50`、`joint_amp_ratio`(6 轴前 1 s 关节行程 策略/老师)、`joint_net_ratio`(6 轴前 1 s 净位移 策略/老师)、`j6_pos_amp_deg_p50`、`tcp_path_ratio_p50`、`tcp_net_ratio_p50`、`sign_flip_rate` 与 `sign_flip_rate_teacher`(6 轴前 2 s 相邻 3 步块变号比例)、`by_cat_mode`(各类别 n / reach / collision / goal_ratio_2s_p50)、`D`(D 类单列)。`_s1` = 1 段采样(部署),`_s4` = 4 段采样。
### 判读
| 现象 | 结论 |
|---|---|
| `H1_oracle` 的 reach < 0.95、collision > 0.01、或 `max_dev_deg_before_dls.p99` > 0.1° | 仿真 / 滚动本身有错,之前所有闭环 0% 都不可信。先修仿真,不看下面各项 |
| `H1_oracle` 全部正常 | 仿真没问题,失败在策略输出。再对照 `H1_oracle_noise_*`:σ = 0.05 时 reach 就大幅下降,说明闭环对残差噪声极其敏感,单靠降噪不够 |
| `H2_open_loop` 的 `prefix_zeroed` 执行窗口误差明显小于 `prefix_orig`,或 `H2_replan_empty` 明显好于同段数的 `H3_headsub_cross`(reach > 0,或 `goal_ratio_2s_p50` 明显更低、`sign_flip_rate` 明显更低) | 前缀照抄(copycat)是主因 |
| `H3_teachersub_cross` 明显好于 `H3_teachersub_timeout`(或 `H3_headsub_cross` 好于 `H3_headsub_timeout`) | 子目标切换规则是主因之一 |
| `H3_teachersub_*` 明显好于 `H3_headsub_*` | 子目标头给的途经点不可用 |
| `H3_nosub` 不比 `H3_headsub_cross` 差 | 子目标通道可以整体去掉 |
| `by_cat_mode` 里 `A/pos`(老师就是一条直线)reach 也是 0 | 失败与多峰无关 |
| `joint_amp_ratio` 远大于 `joint_net_ratio`,且 `sign_flip_rate` 远高于 `sign_flip_rate_teacher` | 「动得多、走得少」是来回抖,不是速度律学快了 |
重新打包和重训(`FRESH_FROM=prep`)要等 Hark 看完这一步的结果再定,这一步之后不要自行启动。
## 回传汇总
| 步骤 | 回传内容 |
|---|---|
| 1 | ml/runs/diag_cl.json |
| 任一步出错 | 终端最后 30 行输出 |
---
## 执行回传(2026-10-19 19:55,本地 AI)
### 第 0 步:同步代码
`ml/eval/diag_collision.py` 归档提交(本机改动 `7e063eb`);根目录用户个人 html 为个人文件未入仓,原位保留。log 顶部 = `406f180`「diag: H 段 …」✓。无训练进程。
### 第 1 步:H 段(完整 JSON 已更新到 ml/runs/diag_cl.json;weights=model、act_scale_ckpt=1.0,同口径;H_tasks 256、missing_teacher 0)
**判读表逐行核对:**
1. **`H1_oracle`:仿真完全正常。** reach **1.0**(243/243)、collision **0.0**、`max_dev_deg_before_dls` p50 6.9e-5° / p99 4.6e-4°(阈值 0.1°)、`finish−teacher` p50 −0.02 s、`dls_used` 94.9%。→ **滚动/仿真没有错,之前所有闭环 0% 都可信,失败在策略输出本身。**
2. **`H1_oracle_noise`:对残差噪声极其敏感。** σ=0.05 时 reach 1.0→**0.218**(碰撞 9.1%);σ=0.1→0.058;σ=0.2→0.012。→ 单靠降采样噪声不够(判读表第二行命中)。
3. **`H2_open_loop`:前缀照抄排除。** prefix_orig vs zeroed:s1 2.315° vs **2.375**(置零不更好);s4 0.251° vs **0.705**(置零明显更差)。`H4` 按 r=0..3 分组误差持平(2.31–2.33°)。`H2_replan_empty`:s1 0%/79.4%/0.836、s4 0%/84.8%/0.603——不比同段数 `H3_headsub_cross` 好。
4. **`H3`:子目标三个变体逐位相同(新异常)。** `headsub_cross` / `headsub_timeout` / `nosub` 在 s1、s4 下从 reach 到 end_err 到 flip 数组**完全一致**(s1: 0% / 96.3% / 0.7504 / 414.2091;s4: 0% / 79.8% / 0.5869 / 428.0032)。`teachersub_*`(真值途经点)仅微动(s1 95.9%/0.726、s4 79.4%/0.578)。→ **子目标头通道在这条闭环里零响应**——比「可以整体去掉」更强;可能是 need 概率全程 <0.5 从不触发,或子目标输入对旧模型输出无影响,建议核一下(D0 曾测过 need 标签占比 28.1%)。
5. **`by_cat_mode`:A/pos(老师直线)reach 也是 0**(s1 碰撞 94%)→ **失败与多峰无关**。
6. **分轴指标:s1 的"动得多"含抖、s4 后基本消抖。** J5/J6 幅度/净位移:s1 3.08/2.57、2.55/2.16;s4 1.83/1.84、0.69/0.69,`sign_flip_rate` 从 0.026–0.062 降到 0.0006–0.0013(≈老师 0.0005–0.004 水平)。→ 4 段采样把来回抖消掉了,但净位移仍 J5 1.8×,且到达仍 0%。
**C 段**(新时限口径):0% 到达 / 96.5% 碰撞 / 2 s 误差比 0.755。
### 本轮无出错,无终端报错段。
---
## 本地自主排查(2026-10-19 20:40,用户授权「继续排查」)
### 1. 闭环噪声容忍阈值(老师动作 + N(0,σ²),σ 以 STEP 为单位,n=256,其余同 H1_oracle)
| σ | 0 | 0.005 | 0.01 | 0.02 | 0.03 | 0.04 | 0.05 |
|---|---|---|---|---|---|---|---|
| reach | 1.0 | 1.0 | 0.971 | 0.716 | 0.457 | 0.309 | 0.218 |
| collision | 0 | 0.8% | 2.5% | 4.9% | 6.2% | 7.4% | 9.1% |
| ratio2s | 0.047 | 0.049 | 0.049 | 0.054 | 0.059 | 0.063 | — |
→ **闭环能容忍的每步噪声上限 ≈ 0.01–0.02×STEP**(约 0.02–0.04°/步)。策略 s1 残差 ~0.77°/步、s4 ~0.05–0.08°/步,都在崩溃区右侧。
### 2. 8 段采样闭环(steps=8,同 H3_headsub_cross 口径)
reach **0%** / collision **79.0%** / ratio2s 0.574 / end 408 mm;`sign_flip_rate` 0.0004–0.0015(≈老师 0.0005–0.004,抖已完全消掉)、`amp ≈ net`(1.00/1.19/0.97/1.19/1.36/0.76,无抖动成分)。
→ 对比 s4(reach 0 / 79.8% / 0.587):**s4→s8 几乎无改善**。按上表的白噪声口径,s8 的残差幅度(16 步 0.56° ≈ 0.035°/步,σ_eff≈0.0175)应给出 reach≈0.75——实测 0。**策略误差不是白噪声,是有方向的系统偏差**:幅度不大但同向、闭环里逐步累积,重规划抵消不掉。降采样噪声(1→4→8 段)已到天花板。
### 3. 子目标通道:need 头恒不触发(新发现,修正「子目标排除」的理由)
- 冷启动(子目标特征抹零,与闭环同口径)need 概率:mean 0.0048、p50 0.0030、p90 0.0079、**max 0.0819**、>0.5 占比 **0**;43 道 need=True 题召回 **0/43**。(D0 的 0.71875 准确率恰等于"全预测 False"基线,当时已有此暗示。)
- 因此闭环里 `sub_flag` 恒 0、子目标从不激活——这才是 H3 三变体逐位相同的直接原因。
- 但模型对子目标特征**高度敏感**(同一噪声下真值子目标 vs 置零:|Δact| mean 0.177、max 3.09)——训练时 80% 样本 sf=1,而闭环 100% 是 sf=0,属训练/闭环分布错配。
- 不过 H3_teachersub(强制真值 need + 真值途经点)仍 0% / 95.9%——**子目标不是闭环全灭的主因**,但 need 头失效 + 闭环恒走少数分支值得修。
### 4. 汇总判断
- 仿真正常(H1_oracle 已证);采样噪声已压到老师抖动水平仍 0% 到达 → **剩余障碍是策略的系统性动作偏差 + 闭环对误差的极低容忍度(误差复利)**。
- 继续调采样段数、子目标规则、候选选择都无解;正确方向是**在闭环状态上训练(DAgger)**,让老师纠正分布偏移,或提高闭环鲁棒性。
- 未自行启动 DAgger / 重训,等指示。
### 5. 补充:系统偏差的方向结构(4096 行开环 + 256 题闭环,4 段采样)
**开环动作误差(deg,有符号)**:
- 每轴均值 [0.010, −0.012, −0.001, −0.029, 0.034, 0.018],|mean|/std ≤ 0.17 → **无固定轴向偏置**(不是某轴恒偏)。
- 每轴标准差 0.16–0.21°;每步平均 |误差| 0.016–0.018°,**16 步内不随步数增长**。
- **lag-1 自相关 0.931–0.967(极高)** → 误差是**慢变/连贯**的,不是白噪声。这解释了为什么白噪声 σ 扫描会低估策略误差的危害:闭环重规划抵消不掉持续同向的偏差。
- 误差与老师动作方向:cos mean 0.046 / p50 0.072(不超调也不欠调);投影比 e·Y/|Y|² mean −0.038 / p50 0.006(无系统性缩放)。
**闭环误差增长(s4,n=256,done=0)**,goal_err / 起点误差:
| t (s) | 0.25 | 0.50 | 0.75 | 1.00 | 1.50 | 2.00 |
|---|---|---|---|---|---|---|
| p50 | 0.959 | 0.880 | 0.811 | 0.741 | 0.645 | 0.591 |
| p90 | 1.024 | 1.072 | 1.119 | 1.162 | 1.222 | **1.318** |
→ p50 缓慢靠近(2 s 缩 41%),**p90 持续发散**——≥10% 的题误差随时间增长(误差复利进碰撞轨道),其余也远不够快。
**补充结论**:策略每步误差很小(~0.017°)但**时间相关性极强(0.93–0.97)**,闭环对"慢变误差"的敏感度远超等幅白噪声;失败是「慢变误差 × 闭环误差复利」。推理侧降噪(段数/选择器)已无空间,训练侧需要降低慢变误差(DAgger / 闭环状态训练)。
### 6. 「2 s 误差比 >1 的发散题」能否提前筛掉(per-task 分组,s4,n=256;明细 ml/runs/task_divergence.json)
| 组(2 s 误差比) | 题数 | 碰撞 | 到达 | cat/mode | 起点误差 p50 | 老师时长 p50 | need 率 | 老师到达 |
|---|---|---|---|---|---|---|---|---|
| 发散 r2>1.0 | 48 | 81% | 0% | A/pos 14、A/pose 14、C/pose 5、C/pos 5、B/pos 3、B/pose 3、D/pos 2、Dr/pos 2 | 374 mm | 1.80 s | 21% | 96% |
| 平 0.7–1.0 | 48 | 83% | 0% | 混合 | 539 mm | 2.12 s | 27% | 90% |
| 收敛 ≤0.7 | 160 | 79% | 0% | 混合 | 642 mm | 2.18 s | 31% | 96% |
- **三组碰撞率相同(79–83%)、到达全 0**——不存在"一小撮可提前去掉的坏题";发散题散布在所有类别,老师都能到达。
- r2 与起点误差秩相关 **−0.384**(起点误差小 → 比值易大),是**分母效应**:短任务(老师 1.8 s、e0 374 mm)比值波动大,不代表题目特殊;r2 与老师时长/行程几乎无关(−0.09 / −0.03)。
- 结论:误差放大是**全体题目上的普遍行为**,筛题无效(只让指标好看),必须训练侧修正。
### 7. DAgger 小样本试跑(用户授权;未跑全量、未微调)
**链路实测**(ckpt `ml/runs/base/last.pt`,旧口径 act_scale=1.0):
| 步骤 | 规模 | 实测 |
|---|---|---|
| `ml.dagger.collect`(16 题,parts=2) | 16 题 | **12.7 s**(含加载),29 个起点(全撞,拒 1 个 gap) |
| `ml.dagger.collect --n 64`(显存采样) | 64 题 | 成功,112 个起点(拒 10 gap),**显存峰值 7.98 GB**(24 GB 卡,无 OOM) |
| `node ml/gen/gen_dataset.cjs --tasks tasks_01.jsonl` | 15 个起点 | **7.6 s**,shard 含 qPrev / v0 / traj / cert |
| `ACT_SCALE=1.0 node ml/prep/build_dataset.cjs …` | 13 题 | **2.3 s**,453 样本(175 增广),meta `act_scale:1, data_ver:2` |
**关键口径提醒**:`build_dataset.cjs` 现在默认 **ACT_SCALE=1.25**(DATA_VER 2),而现有主数据 `ml/data/samples` 无 meta → 训练按 **1.0** 读。两者不一致时训练直接报错(README 第 120 行)。全量 DAgger 前二选一:
1. 打包 DAgger 时显式 `ACT_SCALE=1.0`(与旧主数据、旧 ckpt 兼容);
2. 先按新流程 `FRESH_FROM=prep` 重打主数据为 1.25、重训后再跑 DAgger。
本次试跑全部用 1.0;产物在 `ml/data/dag_try*/`(gitignored)。
**全量耗时外推(估算,以首次实测为准)**:collect 8000 题约 0.8–1 小时(单进程);老师重规划 1.6 万起点 / NPROC≈12 约 10 分钟;打包约 3 分钟;微调 15000 步未试。
**结论**:DAgger 收集链路可用、显存安全(峰值 8 GB),可以全量启动——但先定 act_scale 口径。
### 8. 「加大数据能否力挽狂澜」——闭环状态到训练分布的距离(s4,n=256,9408 个闭环状态)
方法:闭环轨迹每 10 步取一个 q(9408 点),对训练集 191 万老师状态求最近邻(6 维关节角 L∞,±360 回绕);对照 = 每题起点(老师分布内)。
| 状态 | p10 | p50 | p90 | p99 |
|---|---|---|---|---|
| 闭环轨迹状态 | 12.10° | **21.46°** | 32.50° | 44.56° |
| 每题起点(老师) | 8.71° | 13.21° | 17.91° | 21.53° |
- 闭环状态离最近老师状态中位 **21.5°**(起点 13.2° 的 1.6×;p90 32.5°、p99 44.6°)。
- 训练集本身在关节空间稀疏:连老师起点最近邻都有 13.2°——数据是"轨迹线"而非密集体。
- 按密度缩放(6 维 d∝N^(−1/6)):数据翻 4 倍最近邻仅降 ~21%(21.5°→~17°),而策略误差尺度是 0.02°;差距三个数量级,且同类数据不改变误差的时间相关结构(0.94)。
- **结论:扩大同类老师数据救不了闭环**;需要「不同的数据」——在策略实际到达的状态上标注(DAgger),把 21.5° 这些分布外点变成训练样本。
### 9. 方案 A 实测:合成扰动状态样本微调(两轮配方)
做法:从训练任务老师轨迹的 15–85% 处取状态,加 N(0,σ²) 关节扰动(σ 混合 0.5/1/2/4°;实测起点偏移 p50 1.5°),老师重规划(**2000/2000 到达**、cert 1951/2000),打包 36k 样本(act_scale=1.0,为主数据的 1.9%),从 `base/last.pt` 微调 3000 步,2000 步时以 EMA 权重做 512 题闭环评估。
| 配方 | success | collision | goal_ratio_2s | ol_fk_mm | ol_best_mm | ol_div |
|---|---|---|---|---|---|---|
| base/last.pt(基线) | 0 | 0.996 | 0.755 | 5.98 | 2.92 | 0.655 |
| +扰动样本 lr 3e-4 | 0 | **0.484** | 0.927 | **15.27** | 10.32 | 0.966 |
| +扰动样本 lr 1e-4 | 0 | 0.604 | 0.893 | **16.42** | 11.45 | 0.980 |
- 碰撞率首次大幅下降(99.6%→48–60%),但 **success 仍 0**;开环精度退化 2.5–2.7 倍(6→15/16 mm)、多样性升高——小步微调在两种分布间折中,把主分布带偏了。
- **结论**:1.5° 量级的合成扰动 + 3000 步微调不能解决闭环。若继续这条线,需从**预训练开始**按课程混入扰动样本(并监控开环不退化),成本高;或转向结构改动(方案 B:绝对目标参数化/参考轨迹跟踪)或真实 DAgger。
- 产物:`ml/data/samples_perturb/`、`ml/runs/base_perturb/`、`ml/runs/base_perturb2/`(均在 gitignored 目录)。
### 10. 方案 B 判别实验:模型预测的"累计目标"是否指向参考轨迹
方法:2000 个扰动起点(原轨迹状态 + σ 0.5–4° 扰动,L∞ 实测 p50 **3.19°**),模型预测 16 步增量并累积为绝对目标 `Z_model = q_off + cumsum(â·STEP)`,对比原老师轨迹未来 16 步绝对位置 `Z_ref`;`ρ = |Z_model − Z_ref| / |q_off − q_ref|`(ρ≈1 = 目标随状态平移、无纠偏;ρ≈0 = 目标稳定指向轨迹)。
| 模型 | 状态偏移 p50 | 目标误差 p50 | ρ p50 |
|---|---|---|---|
| base/last.pt | 3.19° | 4.86° | **1.54** |
| base_perturb(扰动微调 lr 3e-4) | 3.19° | 5.85° | 1.90 |
| base_perturb2(lr 1e-4) | 3.19° | 6.25° | 1.97 |
| 对照:未扰动行开环 | — | **0.46°** | — |
- 未扰动时 16 步累计目标误差仅 0.46°;状态偏移 3.19° 后目标偏离 4.86°(ρ=1.54)——**当前模型是"从当前状态外推增量",不是"指向参考位置"**。扰动微调让 ρ 更差(1.9–2.0),与开环退化一致。
- **结论:方案 B 不能靠改执行层实现,必须改训练标签**——把标签从"16 步增量"改为"16 步绝对目标关节角(参考轨迹位置)",让模型学"目标在哪"而不是"从这怎么走"。执行层每步朝目标走,偏移状态下即天然纠偏。
- 实施成本:改 `build_dataset.cjs` 标签口径(Y = 绝对目标),同步 FK/平滑/价值等基于增量的辅助损失、rollout 与 `ik-policy.js` 的增量假设,然后从头训练(约 1 小时)。属结构性改动,未擅自开始。