Files
Robot_Arm/docs/ML运行手册审查.md
T
Hark 5591adb39a ml: 第二轮审查 B-1~B-8 处置 + 一键训练控制台
- B-1 运行时投影护栏恢复 5 mm;老师轨迹按认证最小间隙 < 3 mm 剔除(stats/build_dataset,gapDrop)
- B-2 APG 端点+中点 hinge 取均值;B-3 check_r2 空匹配保护、5000×50000、分块 256,pass=false 时 prep 停下
- B-4 R7 按全部 B/C 题统计;B-5 r8 起点贴柱;B-7 pipeline r4(export_onnx --random,训练前测延迟)
- B-8 起步失败 ≤0.2%、column_gap 分块、pipefail、门禁结果先写 .tmp
- 训练控制台:ml/console.bat|sh → ml/monitor.py(开始/停止/进度/日志接口)+ monitor.html;
  pipeline.sh all 支持 FROM/TO,阶段状态写 ml/runs/pipeline.json(ml/pstate.py);训练/APG 日志加 total、t
- 文档:README 一键运行与训练控制台;审查文档追加第三轮处置;方案余量决策与 R4 时点
2026-10-18 06:40:24 +08:00

335 lines
34 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.
# ML 运行手册审查(ml/README.md)
审查对象:`ml/README.md`(12 阶段运行手册)+ `ml/pipeline.sh` + `ml/gen|prep|model|sim|apg|mining|eval` 全部代码。
判据来源:`docs/Transformer轨迹拟合训练方案.md`(方案)。
硬件:本机 CBB-003,RTX 3090 24 GB(driver 617.42)、28 核 CPU、Python 3.12.10 + torch 2.10.0+cu130 + onnxruntime 1.22.0、Node v24.15.0。
方法:代码逐行读 + 在本机真跑第 2/4/5/6 步(两种头)与闭环仿真。**APG 及之后(8–11 步)未跑**,被中断,不声称可用。
结论:流程骨架是通的(对拍 PASS、数据生成、打包、预训练、闭环仿真都实测跑过)。问题集中在**判据自相矛盾**和**指标口径不一致**两类,不是代码写错。
---
## 一、实测记录(可复现)
冒烟产物落在 gitignore 目录 `ml/data/_smoke/`、`ml/runs/_smoke/`,工作树干净,`ml/assets/kin.json` 未重新生成。
| 步 | 命令 | 实测结果 | 手册声称 | 判定 |
|---|---|---|---|---|
| 2 对拍 | `node ml/eval/dump_parity.cjs 300` + `python -m ml.eval.check_parity` | `PASS: true`,fk 3.4e-13 mm、orient 3.3e-16、间隙 2.5e-13 mm、83 维特征 6.0e-8、间隙梯度相对误差 1.4e-6,7.6 s | 2 分钟,须 PASS | 符合 |
| 4 生成 | `node ml/gen/gen_dataset.cjs --n 80 --seed 7` | **1.56 s/条**,80 条 122 s;老师 plan p50 291 ms / p90 1490 ms,认证 p50 247 ms / p90 944 ms | 约 2 秒/核 | 符合(偏乐观余量) |
| 4 统计 | `node ml/gen/stats.cjs`(88 条) | keepRate **0.977**、samplesPerTask 36.5、projectedSamplesFor50k **178.4 万**、exec_s p50 2.3 / p90 3.0 / max 3.7 s、travel p50 350°、**cert.minGap p50 4.4 / p90 5.9 mm**、尾部补零样本占比 14.7% | keepRate≈0.95、projected≈180 万 | 符合,但 minGap 没进检查项(见 P0-2、口径-4) |
| 5 打包 | `node ml/prep/build_dataset.cjs` + `python -m ml.data --index` | 86 任务 → train 3004 / val 136 样本,`index.json` 键名与手册一致;增广 847 提交 / 5 拒绝 | train 170 万 / val 9 万(5 万条口径) | 比例自洽(5% split) |
| 6 预训练 MeanFlow | `python -m ml.train --steps 250 --no-eval --config ml/configs/base.json` | 参数量 **4.92 M**,吞吐 **6 208 样本/s**(step 200,batch=1024) | 1.5–6 小时;方案 R10 要 ≥2 万样本/s | 与 1.5–6 h 自洽(60 000 步 ≈ **2.8 h**),**与 R10 判据冲突** |
| 6 预训练 WTA | `--config ml/configs/wta.json --steps 40` | 跑通,参数量 4.93 M(同骨干换头成立) | 回退约 1 天 | 通路成立 |
| 闭环仿真 | `python -m ml.sim.closed_loop --split val --n 3` | 跑通 9.7 s,按 cat/mode 出 success/collision(未训模型 0/0,符合预期) | — | 通路成立 |
吞吐换算:60 000 步 × 1024 = 6 144 万样本 ÷ 6 200 = **9 910 s ≈ 2.75 h**(不含 eval)。2 万样本/s 意味着 51 分钟跑完 60 000 步——当前配置在 3090 上不可能达到。
---
## 二、P0:会让人在终端前停住或误判
### P0-1 训练吞吐判据自相矛盾(方案 R10 vs 手册)
- 方案 §10.1 R10:`2000 步吞吐 ≥ 2 万样本/s`,缓解写的是"降 epoch 或增大 batch"。
- 实测 6 208 样本/s → 按 R10 判"不达标",但 60 000 步 2.75 h 完全落在手册 1.5–6 h 的预算内。
- 训练是算力受限(MeanFlow 的 `torch.func.jvp` 双前向 + FK 损失),增大 batch 只拉长每步墙钟,samples/s 不上去。R10 给的缓解措施对它自己定的阈值无效。
- 手册 §6 只写"测吞吐",**没写通过线**:`ml/train.py:98` 打出 `samples_per_s`,读者看到 6k 无从判断该继续还是改配置。
建议:R10 阈值改为终态判据("60 000 步 ≤ 3 h")或把 samples/s 线降到 ~5 千;手册 §6 补一行"实测参考:本机 3090 batch=1024 → 6.2 k 样本/s ≈ 2.8 h/60 k 步"。
### P0-2 共识过滤分支的期望数字整段缺失
- `ml/pipeline.sh:27-31`:`consistentByGateRule < 0.9` 时自动加 `--consensus 4`。
- 方案 §10.1 R1 记录首测一致率 **78%**(100 任务 / 373 对邻居,门禁 90%)→ **默认走的就是 consensus 分支**。
- `ml/gen/gen_dataset.cjs:51`:邻居多数不同意就 `keep=false`(why=consensus)→ keepRate 与样本量双双下降。
- 手册 §4 的 `keepRate≈0.95`、`projectedSamplesFor50k≈180 万`(实测无共识 0.977 / 178 万)是**关共识**的口径;开共识后没有对应期望值,也没写"样本不够要不要加 N_TASKS"。
- §13 回传表要求按 `stats.json` 判下一步 → 判据缺一条分支。
建议:§4 增加共识分支的两行期望(keepRate≈? / projected≈?),并明确"低于 X 就把 N_TASKS 提到 8 万"这类动作。
### P0-3 WTA 回退会覆盖 MeanFlow 的训练产物
- `ml/pipeline.sh:34-35`:`train` 阶段输出目录写死 `ml/runs/bench` 与 `ml/runs/base`,`CFG` 只换头不换目录。
- `ml/pipeline.sh:37`(m5)与 `:44`(apg)写死读 `ml/runs/base/best.pt`。
- `ml/train.py:57`:`log.jsonl` 以 append 打开 → 两次不同头的日志混在同一文件。
- 后果:手册 §7 的 `CFG=ml/configs/wta.json bash ml/pipeline.sh train` 会盖掉已训好的 MeanFlow `best.pt/last.pt`,对比物消失;而方案 §1.1 选头的依据恰恰是两者对比(沙箱里两者 100%/0%,"分不出高下")。
建议:`OUT=${OUT:-ml/runs/base_$HEADTAG}`,m5/apg/bench 用 `CKPT=` 变量指;两头的 run 分目录共存。
### P0-4 手册要求 Linux/WSL2,但本机 Windows 原生可跑,只差一处
- 实测第 2/4/5/6 步与闭环仿真在 Windows + Git Bash 下全部跑通(Python 用 `python`)。
- `ml/prep/run_prep.sh:8` 硬用 `python3`,而 Windows 的 `python3` 是 `WindowsApps` 假壳(`python3 -c` 直接 exit 1)→ 第 5 步在**最后一步**失败,`set -e` 会让 `pipeline.sh all` 在此中止(前面的 npy 已写好,重跑代价大)。
- 同类:`ml/pipeline.sh` 内联的 `python -c`(gate1 的 CONSENSUS 判定、m5 的打印)用的是 `python`,在 Windows 没问题 → 两个脚本各用一种,本身就是不一致。
建议:统一 `${PYTHON:-python}`(或 `${PYTHON:-python3}`);手册 §1 补一句"Windows 原生实测可跑,需 Git Bash + `python` 在 PATH"。
---
## 三、口径不一致("这一步通过"不等于"部署能过")
### 口径-1 闭环仿真的安全层 ≠ 部署运行时的安全层
- 仿真只有"逐步候选干涉则换下一条"(`ml/sim/closed_loop.py:118-130`)。
- 运行时多出:1 步胶囊梯度投影(`webapp/js/ik-policy.js:107`)、刹停段 + 每条候选 40 次距离查询预算(`:177`)、安全层单次推理 30 ms 预算(`:322`)、卡死检测与换向锁 1 s(`:296-304`)。
- §6 EVAL、§7 M5 门禁、§9 挖错/门禁**全部**用仿真那套(默认 `safety=False`)。
- 于是 §7 的"穿柱率 ≤2%"和 §11 的"collisionFrames 必须为 0"是两把尺,互不预示;手册没有任何一处说明这点。
建议:§7 明说"M5 是纯策略指标,§11 是策略+安全层指标";m5 对同一门禁集加跑一遍 `--safety`,两个口径都写进 `m5_gate.json`。
### 口径-2 门禁集/挖错题的时长预算是假的
- `ml/mining/tasks.py:47` 每题写死 `exec_s: 3.0, travel: 0.0`。
- `ml/sim/closed_loop.py:67` 超时 = `clamp(2*exec_s, min=3)` = 6 s;`ml/mining/mine_round.py:38` 又用 `max_sec=6.0` 覆盖。
- 后果:§7 M5 的 1000 题、§9 的门禁集里,"到达"一律 6 s 硬顶、`time_ok_1p3` 一律 3.9 s;而 §6 训练期 EVAL 用的是老师真实时长 ×1.3。两个"到达率"不可比却共用同名指标。`travel=0` 还使 `travel_ratio_median`(`closed_loop.py:154`)在门禁集上直接返回 None。
- 方案 §10.1 R8"3 s 内恢复 ≥95%、活锁=0"在 12 步里没有执行点。
建议:`tasks.py` 出题时带上老师时长(或明确写"门禁集按定长 6 s 口径");R8 补对抗用例集与命令。
### 口径-3 APG 的"到达"是定长 3.6 s 窗口内的距离塑形,且碰撞只查端点
- `configs/apg.json`:`plans:60`,每次推理提交 3 步 × `DT=0.02` → 展开 **3.6 s**(`ml/apg/apg_finetune.py:67`),无"到达即停";到达项只在每个 10 块段末用 `((T-pe)/100)²`(`:104-109`)。
- 实测这批老师轨迹 exec_s p50 2.3 / p90 3.0 / max 3.7 s → 样本刚好压线;真数据里老师时长 >3.6 s 的绕远长任务(正是 C/B 难题)APG **永远看不到绕出段**。
- 碰撞 hinge 只打每步末端点(`:95-97`),仿真与运行时都查端点+中点(`closed_loop.py:142-144`、`ik-policy.js:222`)。
- 手册 §8 写"直接优化到达、碰撞余量",读者会以为是全 horizon 到终点。
建议:§8 补一句"定长 3.6 s 滚动 + 段末距离替代到达项";把 `plans` 提到覆盖 exec_s p90(≥55 s 不现实,折中:对 exec_s>3.6 s 的题按比例加 plans,或在 README 说明这是已知截断)。
### 口径-4 训练余量 5 mm 压在老师轨迹自身的间隙分布上
- 实测 88 条 keep 轨迹 `cert.minGap` **p50 4.4 mm / p90 5.9 mm**(`ml/gen/stats.cjs:18` 已算出 `vertexMinGapMm`)。
- `docs/collide.json` 的 `margin_mm = 0.3`,`kin.gaps()` 的 gap 已减掉它 → 这 4.4 mm 是实打实的几何间隙。
- `configs/apg.json` 的 `margin_train_mm = 5.0` + 运行时投影目标 `margin:5`(`ik-policy.js:174`)→ **约一半 BC 标签落在 5 mm 以下**,APG 碰撞项与 BC 项方向相反。
- 手册 §4 让检查的三项(keepRate / byCatMode / projectedSamples)里没有 `vertexMinGapMm`;方案 §7.1 只写"margin=认证+5",没和老师的间隙分布对齐。
建议:§4 检查项加 `vertexMinGapMm` 并给期望区间;要么 `margin_train_mm` 降到老师分布 p50 附近(~4 mm),要么承认 BC/APG 有对抗并把它当成设计取舍写下来。
---
## 四、缺项与细节
1. **验收表落不了地**:方案 §9 要求 held-out 可达 ≥98%、D 类停靠 ≤老师+5 mm、刹停发生率 <2%、R7 左右比例与行程门禁、R8 对抗用例——12 步里都没有对应命令。`ml/mining/gate.py:41` 只查 3 项(到达增益 / A 类降幅 / 上轮仍对);`tests/policy_bench.cjs:81` 已经算出 `brakes/locks/uncertifiedSegs` 但没进任何门禁。
2. **挖错池累积**:`ml/mining/loop.sh:20` `ls ml/runs/mine/r*/pool.jsonl` 把**所有历史轮**的错题池喂给每轮 APG,池子逐轮变大,且 `mine_round.py:57` 对 E1 复制 ×2、每题再带 10 个邻居。手册 §9 只说"错题与邻居进采样池",没说会跨年累积 → 后期轮次的采样分布严重偏向老错题(A 类降幅门禁是唯一的兜底)。
3. **fp16 导出方向可疑**:手册 §10 把 `--fp16` 报错当偶发("去掉 --fp16 手动导出 fp32")。但部署端是 wasm(`webapp/js/ik-policy-glue.js:36` 默认 wasm)和 Node CPU(`tests/policy_bench.cjs:55` `executionProviders:['cpu']`),fp16 在 CPU EP 上要么缺 kernel 要么靠大量 Cast 兜底,不保证比 fp32 快。参数量实测 4.92 M → fp32 ≈ 20 MB(与手册一致),fp16 省的 10 MB 对浏览器收益有限。**本机 `onnxconverter_common` 未装,此条未实测。**
4. **`--n` 同时控制两个集合**:`tests/policy_bench.cjs:85-86` 的 `+opt('--n')` 对 nc 和 route 一起生效,手册说的"30 例 / 40 例"只在默认值成立。
5. **val 为空时崩**:小样本摸底(几百条、5% split 可能 0 个 val 任务)下 `ml/sim/closed_loop.py:161` 的 `evaluate` 返回空 dict,`ml/train.py:106` 取 `res['success']` KeyError。真实数据不会撞,但手册鼓励先小跑摸底。
6. **文件地图缺 4 个真实文件**:`ml/gen/cert.cjs`(认证实现在 ik-policy.js,这里是跳转壳)、`ml/gen/pathdev.cjs`(同伦类判定,共识过滤与门禁都依赖它)、`ml/prep/npy.cjs`、`ml/toy/toy_bimodal.py`(方案 §沙箱 的依据)。
7. **R2 无执行点**:方案要求"近邻样本标签方差 <10% 步长、起步失败率=0",手册 §3–§5 的检查项里没有。
---
## 五、按优先级的改动清单
| 优先级 | 改什么 | 落点 |
|---|---|---|
| 1 | 吞吐判据对齐:R10 改成终态判据或降线,§6 写实测参考值 | `docs/Transformer轨迹拟合训练方案.md` §10.1、`ml/README.md` §6 |
| 2 | train 阶段输出目录随头分开,m5/apg/bench 用 CKPT 变量 | `ml/pipeline.sh:34-37,44,48` |
| 3 | `python3` → `${PYTHON:-python}`,§1 说明 Windows 原生可跑 | `ml/prep/run_prep.sh:8` |
| 4 | §4 补共识分支的 keepRate/样本量期望与"加 N_TASKS"动作;检查项加 `vertexMinGapMm` | `ml/README.md` §3–§4 |
| 5 | §7 说明 M5 与 §11 两个口径,m5 加 `--safety` 对照 | `ml/pipeline.sh:36-42`、`ml/README.md` §7 |
| 6 | 出题带真实老师时长(或明写定长 6 s),补 R7/R8 执行点 | `ml/mining/tasks.py:47`、`ml/mining/gate.py:41`、`ml/README.md` §9 |
| 7 | §8 明写 APG 的 3.6 s 截断与只查端点;`margin_train_mm` 与老师间隙分布对齐 | `ml/README.md` §8、`ml/configs/apg.json` |
| 8 | §10 默认 fp32 + `__POLICY.latency()` 实测后才考虑 fp16(仅 WebGPU);loop.sh 池子只取本轮;文件地图补全;evaluate 空任务保护 | `ml/README.md` §10/文件地图、`ml/mining/loop.sh:20`、`ml/sim/closed_loop.py:161` |
未验证范围:第 7(m5)、8(apg)、9(mine)、10(export)、11(bench)步与浏览器 `?policy=1` 第 12 步都没跑过(`ml/node_modules` 未安装、`webapp/models/` 无模型、`onnxconverter_common` 未装)。这些通路只做过静态代码核对。
---
---
# 第二轮:对修订版(提交 `d3b7c7b`)的可行性评估
评估对象:另一台机器按上述审查做的修订(18 文件、+493/−156)。方式:**只读代码 + 只读 diff,本轮没有跑任何东西**,第一轮的实测数字(6208 样本/s、keepRate 0.977、minGap p50 4.4 mm、1.56 s/条)继续沿用。上文第一轮的正文按 0218d7f 时的代码写,路径与章节号(`ml/runs/base`、12 步)在修订后已变,不逐条订正,以本节为准。
## 一、第一轮 13 条的处置
| 第一轮条目 | 状态 | 落点 |
|---|---|---|
| P0-1 R10 吞吐判据矛盾 | 已修 | 方案 §10.1 R10 改为"60000 步 ≤ 3.5 h,即 ≥5000 样本/s",缓解改成 `fk_caps` 96→48 / `steps`→40000(增大 batch 明确标注无效);`ml/train.py:101` 加 `eta_h` |
| P0-2 共识分支缺期望数字 | 已修 | README §4 加两张表(不共识实测 / 共识估算 + 异常动作);`ml/gen/stats.cjs:20` 加 `consensusDrop`、分位数加 p10;`ml/pipeline.sh` gen 阶段按实测"样本/任务"自动补量到 `TARGET_SAMPLES=1700000`(最多 2 次) |
| P0-3 WTA 回退覆盖 MeanFlow 产物 | 已修 | `pipeline.sh`:输出 `ml/runs/$TAG`、`ml/runs/bench_$TAG`;m5 通过后写 `ml/runs/selected_ckpt`,apg/export/accept 经 `ckpt()` 取;`ml/train.py:58` 与 `apg_finetune.py:51` 日志改为新训覆盖、续训追加 |
| P0-4 `python3` 在 Windows 断第 5 步 | 已修 | `run_prep.sh:8` 与各脚本统一 `${PYTHON:-python}`;README §1 加"Windows 原生 + Git Bash 实测可跑",并写明 Windows 不要用 `python3` |
| 口径-1 仿真安全层 ≠ 运行时 | 已修(说明层) | m5 同跑 `--safety` 一遍,产出 `m5_gate_<tag>.json` 的 `policy_only` / `with_sim_safety` 两块;README §7 明写"三口径互不替代,部署只看第 11 步" |
| 口径-2 门禁题假时长 | 已修 | `ml/mining/tasks.py:54` `exec_s/travel` 置 None;`ml/sim/closed_loop.py:24` `NOREF_SEC=6.0`,`time_ok_1p3`/`travel_ratio` 只在有老师参考的题上统计,新增 `n_ref`、`time_budget` 字段 |
| 口径-3 APG 定长 3.6 s + 只查端点 | 已修(但引入新问题,见下 B-2) | `apg_finetune.py:70` 展开长度随批取 `exec_s p90 × 1.2`,夹在 60–150 次推理;`:102` 铰链改端点 + 中点 |
| 口径-4 5 mm 余量压老师间隙分布 | 已改,方向不认同 | `configs/apg.json` 与 `webapp/js/ik-policy.js:174` 一起降到 3 mm;方案决策表"训练余量 5 mm"改为 3 mm,R3 回退改"提高到 4–6 mm" |
| 缺项-1 §9 验收表无执行点 | 已补 | 新增 `ml/eval/acceptance.py`(第 12 步 `accept`):held-out 到达率 ≥98%、D 类停靠 ≤老师+5 mm、起步失败=0,并汇总 R2/R7/R8/R10/M5/部署形态 |
| 缺项-2 挖错池累积 | 已修 | `ml/mining/loop.sh:21` 改为 `--pool $D/pool.jsonl` 只用本轮 |
| 缺项-3 fp16 部署 | 已修 | `pipeline.sh` export 去掉 `--fp16`,README §10 改默认 fp32,只在 `&ep=webgpu` 实测受益才另出 fp16 对比 |
| 缺项-4 `--n` 混控两集合 | 已修 | 拆成 `--nc-n` / `--route-n` / `--r8-n`,positional 过滤改用白名单 `VALOPT` |
| 缺项-5 val 为空崩 | 已修 | `closed_loop.evaluate` 空任务返回 NaN 字典;`train.py:59` 无 val 任务时提示并自动 `--no-eval` |
| 缺项-6 文件地图缺 4 文件 | 已修 | README 文件地图补 cert.cjs / pathdev.cjs / npy.cjs / toy_bimodal.py |
| 缺项-7 R2 无执行点 | 已补 | 新增 `ml/eval/check_r2.py`,prep 末尾自动跑 |
| 附带 | 新增 | R7(左右比例 + 行程)进 `ml/mining/gate.py:47-53`;R8 对抗集 + `brakeRate` 进 `tests/policy_bench.cjs`;出题与间隙计算分块防 OOM(`tasks.py:9` `min_gap_chunked`) |
## 二、修订新引入的问题(按严重度)
### B-1(最高)3 mm 是拿真机护栏迁就数据分布
依据是本轮实测"老师最小间隙 p50 4.4 mm",但正解是在认证环节把 `cert.minGap < 3 mm` 的老师样本过滤掉(`stats.cjs` 已经算这个数,逐条记录里就有),而不是把**运行时投影余量**一起降下来。认证只保证扫掠间隙 > 0,`collide.json` 的 `margin_mm` 只有 0.3 mm,`project()` 是唯一主动把臂往外推的力量(`ik-policy.js:279`)。方案 R3 原文写的回退是"训练余量**提高到** 3–6 mm 以缓解认证过保守",修订把这个值定成 3 = 把回退方向当成了默认。贴柱真实距离从 ≥5 mm 变 ≥3 mm 是机械/安全决定,需要单独确认,不该由 ML 口径推出。
### B-2 APG 两处改动耦合且没重标定
- `apg_finetune.py:102-104`:端点与中点两个 hinge 直接 `view(2, B).sum(0)` 相加 → 碰撞项数值约为旧版 **2 倍**,而 `w_col=2.0` 未动。
- `:70` + `plans_max=150`:展开最坏 60→150 次推理(2.5 倍),每步 `kin.gaps` 的位形数又 ×2(端点+中点)→ 单个 APG step 代价上界约 **4 倍**。
- 同时 margin 5→3 让铰链激活的样本数下降。一增一减方向相反,幅度都没实测。
- README §8 的"2–4 小时"沿用旧口径,没随改动更新。
后验表现无法预判:APG 之后若行程变长/贴柱反而更近,第一嫌疑是这个组合而不是学习率。
### B-3 新代码路径一次没跑,check_r2 自身可能成为闸门
- `check_r2.py:39`:`m.sum()==0` 时对空张量取 `torch.quantile(std, 0.9)` 直接报错(小样本摸底必撞;`label_std_mean` 也是 NaN)。
- 默认 `--queries 20000 --pool 200000`,分块距离矩阵 1024×200000 ≈ 0.8 GB/块,`torch.where` 再复制一份 → 峰值 2–3 GB 显存;`Samples` 本身又把 X/Y/SG 全量上卡(约 1.5 GB)。CPU 兜底时 20000×200000 fp32 = 16 GB 内存,docstring 说"降到 50000"仍然不轻。
- 它挂在第 5 步末尾,README 写"不通过先发我,不要直接训练"→ 一个自身可能 OOM/崩的硬门禁。
### B-4 R7 的左右比例被成功率污染,会漏报它想抓的东西
`gate.py:47` 的 `left(...)` 以"到达"为条件掩码。APG 把某一侧绕行全做失败时,剩余成功集里的左右比例可以纹丝不动 → 而 R7 的目标(方案:APG 压缩多模态)恰恰是这种情况。建议按全部题的首次 J1 方向统计,不筛到达。
### B-5 r8 集合没实现"两侧都要绕远"
`policy_bench.cjs:47-64` 只约束终点贴立柱 + |ΔJ1|≥140° + 直线被挡,**起点没做 `nearColumn` 检查**。方案 §10.1 R8 的口径是"两侧都要绕远",现在起点对侧无约束 → 恢复率会比设计意图偏松(判据偏松是危险的偏)。
### B-6 估时里"实测"两字一处用错、两处仍是拍的
- §2 写"1 分钟(实测 7.6 s 对拍)"——7.6 s 是 `dump_parity 300` 的数,pipeline 跑 2000 条,不同口径。
- §6 的"测速 6 分钟 / 正式 3 小时"由 6.2k 样本/s 换算,可信。
- §7 的 10–20 分钟(1000 题 ×2 遍 × 定长 6 s)、§11 的"约 1 小时"(题数已从 1070 增到 1120,且 r8 采样每条最多 200 次 `collideDetail` 重试)、§8 的 2–4 小时(见 B-2)都无依据。
### B-7 方案自标的最大不确定项 R4 仍然是空的
策略推理在 wasm 多线程、batch=8 下的 P99 从未量过:`webapp/models/` 只有一个 README.md(至今没导出过任何模型),方案 §1.1 表里的 0.19 ms 是 2D 玩具沙箱(`ml/toy/toy_bimodal.py`)的数,不是这个 4.92 M 模型。而 60 ms 一次推理的部署节奏、`safetyMs:30` 预算、`certBudget:40` 全靠它。R4 不过就要改模型规模(d=128)或提交步数(3→2),是伤筋动骨的返工,却排在第 13 步才第一次被测。
### B-8 杂项
- `build_dataset.cjs:46` 噪声增广的接受地板仍是 `S.clearance(qn, 5) > 1`,与新的 3 mm 投影不同步(一松一紧,不是矛盾但没对齐)。
- `acceptance.py:44` 用 `start_fail == 0` 硬判:held-out 约 2500 题里任何一题 0.5 s 内行程 <1° 就整项未过,判据脆。
- `pipeline.sh` m5 不通过 `sys.exit(3)` → `all` 会中止(有意,但应写进"常见问题")。
- `requirements.txt` 仍列 `onnxconverter-common`(fp16 已非默认,留着无害)。
- `tasks.py:36` 的 `column_gap(kin, b)` 仍在 2048 行整批上算(`free_q`/`straight_blocked` 已分块),单卡可过但和"已分块防 OOM"的说法不完全一致。
## 三、可行性判断
1. **前段(第 1–6 步)可执行**:数据生成、打包、两种头、闭环仿真、对拍都在本机实测过,数字与手册自洽。修订把 R10、共识补量、目录覆盖、`python3` 这几个会真卡住人的点解决了,这部分我认可。
2. **后段(第 7–13 步)逻辑闭合但无证据**:判据齐全、口径终于分开了,可"APG+挖错能不能把纯策略穿柱率压到 ≤2%"、"机时是不是 2–4 h"、"held-out 能不能 98%"一个都没跑过。别把 §8–§12 的估时当预算。
3. **不建议按现值直接跑第 7 步之前**:B-1(3 mm)是需要你拍板的安全决定,B-2(w_col 没跟着重标)会让后段任何异常都无法归因。
## 四、第 7 步之前建议先做的两件事(都不需要训练)
1. **结掉 R4**:用一个随机初始化的 4.92 M 模型导出 fp32 ONNX,走 `ml/serve.py` + `?policy=1`,在目标浏览器实测 `__POLICY.latency()` 的 batch=8 P99 与安全层 P99(方案要求 <15 ms)。不过就要改 `d`/`commit`,此时改配置的成本远低于训完 3 小时再改。
2. **把 margin 决定单独拍板**:在"过滤老师数据保 5 mm"与"放宽护栏到 3 mm"之间选一个,再把 `w_col` 与 §8 估时按选择重算。这两条是本轮唯一拦住往下跑的理由。
---
---
# 第三轮:对第二轮 B-1~B-8 的处置 + 新增训练控制台
修订方:沙箱(Hark)。基于 `655e1fb`。沙箱只做了 CPU 小数据冒烟(见第四节),所有耗时、keepRate、gapDrop 比例仍以你机器上的实测为准。
本轮改动以补丁形式交付(`git apply review2_and_monitor.patch`),确认后再推送。
## 一、B-1~B-8 处置
| 条目 | 处置 | 改动位置 |
|---|---|---|
| B-1 3 mm 拿护栏迁就数据 | **采纳你的方向**:运行时投影护栏恢复 **5 mm**;改为在数据侧剔除认证最小间隙 `cert.minGap < 3 mm` 的老师轨迹;APG 碰撞项余量 3 mm 与过滤线一致(碰撞项不与 BC 标签对抗)。护栏比数据更保守,二者不再绑定 | `webapp/js/ik-policy.js:174` margin 3→5;`ml/gen/stats.cjs` 新增 `gapDrop`、`minGapFilterMm`,样本数与补量只按过滤后计;`ml/prep/build_dataset.cjs` 同一过滤(`MIN_GAP_MM=3`,可用环境变量改),打包输出也报 `gapDrop` |
| B-2 端点+中点 hinge ×2、w_col 未重标 | 两处 hinge 由求和改为**取均值**,与只查端点同量纲,`w_col=2.0` 不用动。展开 60–150 次的单步代价不再拍估时:手册 §8/§9 改为"未实测,以监控页前 50 步换算的 ETA 为准" | `ml/apg/apg_finetune.py:104`;README 阶段表 |
| B-3 check_r2 空匹配崩、显存峰值 | 近邻对 < 20 时输出 `pass: null` 不报错;默认 5000 查询 × 50000 池、分块 256、`masked_fill_` 原地,GPU 峰值 < 0.5 GB。`pass: false` 时 prep 以返回码 4 结束、一键流程停下;`null` 不拦 | `ml/eval/check_r2.py`;`ml/pipeline.sh` prep |
| B-4 R7 以到达为条件会漏报 | 左右比例改为按**全部** B/C 题的首次 J1 方向统计,不筛到达 | `ml/mining/gate.py:47` |
| B-5 r8 起点没贴柱 | 起点也要求 `nearColumn`,两侧都要绕远 | `tests/policy_bench.cjs` r8Cases |
| B-6 估时口径 | 对拍改为"约 1 分钟(估算:300 条实测 7.6 s,流程跑 2000 条)";M5、部署评测标"估算";APG、挖错标"未实测" | README 阶段表 |
| B-7 R4 排在最后 | **提到训练前**:新增 `bash ml/pipeline.sh r4`,用随机初始化模型导出 fp32 ONNX(延迟只与结构有关),`python ml/serve.py` + `?policy=1` 测 `__POLICY.latency()`;不过就把 `model.d` 192→128、`ff` 768→512 后重测 | `ml/export_onnx.py` 新增 `--random <配置>`;`pipeline.sh` r4;README §2;方案 R4 行"M1 前" |
| B-8 杂项 | 噪声增广接受地板 1 mm → 3 mm(与过滤线一致);验收起步失败 `= 0` → `≤ 0.2%`;`column_gap` 分块 256(沙箱实测约 20 MB/位形,整批 2048 会爆);m5 返回码 3 中止 `all` 写进常见问题;`set -o pipefail` + 门禁结果先写 `.tmp` 再改名(中断不留残缺 `consistency.json`) | `build_dataset.cjs`、`acceptance.py`、`tasks.py`、`pipeline.sh`、README 常见问题 |
| `onnxconverter-common` | 保留(`--fp16` 仍可用于 WebGPU 对比) | — |
方案文档同步:决策表"训练余量"改为"数据过滤与 APG 碰撞项 3 mm、运行时护栏 5 mm";APG 碰撞项写明端点与中点取均值;R4 检测时点改为训练前。HTML 已重新生成。
**需要你确认的一处**:3 mm 过滤会剔除多少老师轨迹没实测过。沙箱 30 条小样本里剔除了 9/29(p10 = 1 mm),量太小不具代表性;你那边第一轮实测 p50 4.4 mm。生成完看 `stats.json` 的 `gapDrop`:> 25% 说明老师整体太贴柱,把 `stats.json` 发我再定。自动补量会按过滤后的样本数补,所以样本总量不受影响,只是生成时间相应变长。
## 二、新增:训练控制台(一键运行 + 全程可视化)
### 怎么用
1. Windows 双击 `ml/console.bat`(Linux/WSL:`bash ml/console.sh`),浏览器自动打开 `http://localhost:8100/`。
2. 点右上角「▶ 开始训练」,在对话框里选起始阶段、结束阶段和参数,点「开始」。
3. 之后整个流程(对拍 → 老师门禁 → 生成 → 打包 → 预训练 → M5 → APG → 挖错 → 导出 → 部署评测 → 验收)都在这一页看;「■ 停止」随时停,再开始默认从停下的那一步继续。
网页可以关,训练不受影响;关闭控制台窗口会结束训练。R2、M5 不通过时流程会停在那一步。
### 组成与接口
| 文件 | 作用 |
|---|---|
| `ml/console.bat` / `ml/console.sh` | 一键启动:`python -m ml.monitor --open` |
| `ml/monitor.py` | Python 标准库 HTTP 服务,默认只监听 127.0.0.1:8100 |
| `ml/monitor.html` | 网页,零依赖(原生 canvas 画图),不连外网;`?demo=1` 或直接双击打开时用内置示例数据 |
| `ml/pstate.py` | 写 `ml/runs/pipeline.json`:`pipeline.sh` 每个阶段开始/结束时自动调用(终端里跑也会写) |
| 接口 | 方法 | 说明 |
|---|---|---|
| `/` | GET | 网页 |
| `/api/runs` | GET | `ml/runs/*/log.jsonl` 列表(名称、类型 train/apg/bench、更新时间、是否发散) |
| `/api/log?run=&offset=` | GET | 增量读日志:只返回 offset 之后的完整行,日志被新训练覆盖时自动从头读 |
| `/api/status` | GET | GPU、`pipeline.json` + 当前阶段进度、数据统计、R2、M5、挖错各轮、部署评测、验收 |
| `/api/job` | GET | 控制台启动的流水线进程:是否在跑、PID、起止阶段、返回码、是否手动停止 |
| `/api/console?offset=` | GET | `ml/runs/console.log` 增量(首次只给最后 64 KB) |
| `/api/start` | POST | `{"from":"kin","to":"accept","env":{...}}` → 后台 `bash ml/pipeline.sh all`;env 只接受白名单:`N_TASKS NPROC TARGET_SAMPLES CFG CONSENSUS ROUNDS APG_STEPS MINE_N`,逐个正则校验 |
| `/api/stop` | POST | 结束整个进程树(Windows `taskkill /T /F`,其他系统进程组 SIGTERM,10 秒后 SIGKILL),当前阶段记为返回码 -15 |
安全:开始/停止只接受本机请求(`--host 0.0.0.0` 开放给局域网时其他机器只能看,`--remote-control` 才放开);已经有流水线在跑(控制台自己起的,或终端里起的、日志 2 分钟内有更新)时拒绝再开始。
Windows 找 bash 的顺序:环境变量 `BASH` → `C:\Program Files\Git\bin\bash.exe` → `C:\Program Files (x86)\Git\...` → `%LOCALAPPDATA%\Programs\Git\...` → `git` 所在目录推断;不用 `System32\bash.exe`(那是 WSL)。控制台把自己的 `sys.executable` 作为 `PYTHON` 传给流水线(路径含空格时不传,回落到 `python`)。
### 流水线脚本配套改动
- `bash ml/pipeline.sh all` 支持 `FROM` / `TO` 只跑一段(如 `FROM=gen TO=train`);在终端里用 `all` 时也会在后台自动起控制台(`MONITOR=0` 关闭)。
- 每个阶段开始写 `begin`(生成阶段带 `target_tasks`,补量时更新;预训练带 `tag`;挖错带 `rounds`),退出时由 `trap EXIT` 写返回码。
- `pipeline.json` 在从中间续跑时保留计划之外各步的记录,所以流水线卡片能显示"之前已完成"。
- 训练与 APG 日志每条记录新增 `total`(总步数)与 `t`(时间戳),评估记录也带 `t`,用于进度条、已用时间与 ETA。
### 网页内容
流水线阶段条 → 全流程卡(总百分比按各步粗估耗时加权、当前步骤及其进度、总用时、本步用时、剩余粗估、开始/停止)+ GPU 仪表 → 当前运行(自动跟随正在跑的训练,可手动切换)→ 指标卡(带趋势小图)→ 4 张曲线(预训练:总损失含原始值淡线、各分量、闭环评估带"最好"标记、吞吐带 R10 5000 线;APG:到达误差、损失分量、闭环评估、展开长度)→ 数据 / M5 / 挖错 / 部署评测 / 验收面板 → 终端输出(报错标红)。顶栏有平滑系数、对数纵轴、自动刷新开关。
当前步骤进度的口径:生成 = 已写任务条数 / 目标条数;打包 = 已打包分片 / 分片数;预训练 = (测速 2000 步 + 正式步数) / (2000 + 总步数);APG = 步数;挖错 = 已完成轮数 + 本轮 APG 步数;M5 = 两遍评估;对拍、老师门禁、导出、部署评测、验收无法计量,显示用时与粗估。
## 三、本轮改动文件清单
```
新增 ml/monitor.py ml/monitor.html ml/pstate.py ml/console.bat ml/console.sh
修改 ml/pipeline.sh r4 / monitor 阶段、all 支持 FROM/TO 与自动起控制台、阶段状态记录、pipefail、R2 不通过停下、补量更新目标
ml/train.py 日志加 total、t
ml/apg/apg_finetune.py 日志加 total、t;端点+中点 hinge 取均值;docstring 余量说明
ml/gen/stats.cjs gapDrop / minGapFilterMm,样本数按过滤后计
ml/prep/build_dataset.cjs 剔除 minGap < 3 mm 的轨迹;增广地板 3 mm;输出 gapDrop
ml/eval/check_r2.py 空匹配保护、默认规模、分块 256
ml/eval/acceptance.py 起步失败 ≤ 0.2%
ml/mining/gate.py R7 左右比例不以到达为条件
ml/mining/tasks.py column_gap 分块
ml/export_onnx.py --random
tests/policy_bench.cjs r8 起点贴柱
webapp/js/ik-policy.js 投影护栏 5 mm
ml/README.md 一键运行、R4、训练控制台、过滤口径、估时标注、回传文件、常见问题、文件地图
docs/Transformer轨迹拟合训练方案.md / .html 余量决策、APG 碰撞项、R4 时点
```
## 四、沙箱验证(CPU,2 核,小数据)
| 项 | 结果 |
|---|---|
| `stats.cjs` 过滤 | 30 条任务:keep 20、gapDrop 9;`MIN_GAP_MM=4.4` 时 keep 16、gapDrop 13,口径一致 |
| `build_dataset.cjs` | 20 条任务 761 样本,gapDrop 9,增广拒绝 5/226 |
| `check_r2.py` | 小样本可跑,不再报错 |
| APG 2 步 + 门禁(含新 R7) | 通过 |
| `column_gap` 分块 | 300 位形 / 块 100 正常;块 512 在 7 GB 内存下被杀 → 默认 256 |
| `export_onnx --random` | 走到导出一步,沙箱缺 `onnx` 包未完成,需在你机器上跑 `r4` |
| 控制台接口 | 网页开始 `gen→prep`(6 条任务):进度 2/6 → 4/6 → 打包 0/2 → 完成,返回码 0;停止 `gate1`:进程树结束、该步记为已停止、不留残缺 `consistency.json`、"已停止"提示不被覆盖 |
| 网页 | jsdom 跑 4 个示例场景 + 开始/停止流程,无脚本错误;沙箱没有浏览器,没有截图 |
| 未验证 | Windows 下 `console.bat` 与 Git Bash 查找、`taskkill` 停止;`policy_bench.cjs` 完整运行(沙箱无 `onnxruntime-node`) |
## 五、你机器上的建议顺序
1. `git apply review2_and_monitor.patch`(或等我推送后 `git pull`)。
2. `bash ml/pipeline.sh setup`(如依赖已装可跳过)→ `bash ml/pipeline.sh r4` + 浏览器测延迟,把 `__POLICY.latency()` 发我。
3. 双击 `ml/console.bat` → 「开始训练」,起始「对拍」、结束「打包样本」,跑完看 `gapDrop` 与 R2。
4. 没问题再「开始训练」从「预训练」跑到「验收汇总」。