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 时点
This commit is contained in:
Hark
2026-10-17 17:15:16 +00:00
parent 655e1fb93c
commit 14d72a9794
21 changed files with 1465 additions and 57 deletions
+5 -4
View File
@@ -5,7 +5,8 @@
损失:段末到达项 + Σ碰撞铰链 ReLU(margin_train − 间隙)(逐胶囊对,端点+中点)+ 平滑(速度²+加速度²)+ 行程 + BC 锚定(MeanFlow 损失)。
2026-10-18:展开长度不再定长 60 次推理(3.6 s,会截掉老师时长 > 3.6 s 的绕远题),改为覆盖本批 exec_s p90×1.2,上限 plans_max;
"到达"仍是每 seg_plans 段末的距离项(无到达即停),属有意设计:段末项给出持续的接近梯度。
margin_train 5 → 3 mm:老师轨迹自身最小间隙 p50 4.4 / p90 5.9 mm,5 mm 会让约一半 BC 标签与碰撞项对抗;3 mm ≈ 老师 p10。"""
margin_train 3 mm:与训练数据过滤线一致(认证最小间隙 < 3 mm 的老师轨迹不进训练集),碰撞项不与 BC 标签对抗;
运行时投影护栏独立保持 5 mm。端点与中点两个铰链取均值,与只查端点同量纲,w_col 无需重标。"""
import argparse, json, math, os, random, time
import torch
@@ -101,7 +102,7 @@ def main():
# 碰撞铰链:端点 + 中点(与仿真/运行时的离散检查一致)
G = kin.gaps(torch.cat([q, 0.5 * (q + qp)], 0), M)
hinge = torch.relu(M - G['gap'])
col = torch.zeros(2 * B, device=dev).index_add(0, G['b'], hinge).view(2, B).sum(0)
col = torch.zeros(2 * B, device=dev).index_add(0, G['b'], hinge).view(2, B).mean(0) # 端点与中点取均值:与只查端点时同量纲,w_col 无需重标
sm = ((d / step) ** 2).sum(-1) + (((d - prev_d) / step) ** 2).sum(-1)
prev_d = d
seg_loss = seg_loss + C['w_col'] * col.mean() + C['w_smooth'] * sm.mean() + C['w_len'] * d.abs().sum(-1).mean()
@@ -129,13 +130,13 @@ def main():
opt.step()
with torch.no_grad():
e, oe = goal_err(kin, q, T, R)
rec = {'it': it, 'plans': n_plans, 'err_mm_mean': e.mean().item(), 'reach_frac': ((e < 1) & (oe < 0.5)).float().mean().item(), 'bc': l_bc.item(),
rec = {'it': it, 'total': C['steps'], 't': time.time(), 'plans': n_plans, 'err_mm_mean': e.mean().item(), 'reach_frac': ((e < 1) & (oe < 0.5)).float().mean().item(), 'bc': l_bc.item(),
'gnorm': gn.item(), **stats, 'min': (time.time() - t0) / 60}
if it % 10 == 0: print(json.dumps(rec), flush=True)
log.write(json.dumps(rec) + '\n'); log.flush()
if (it + 1) % C['eval_every'] == 0 or it == C['steps'] - 1:
res, _ = evaluate(model.eval(), kin, val_tasks, dev)
res['it'] = it + 1
res['it'] = it + 1; res['t'] = time.time()
print('EVAL', json.dumps(res), flush=True); log.write(json.dumps({'eval': res}) + '\n'); log.flush()
sd = {'model': model.state_dict(), 'cfg': mcfg, 'step': it + 1, 'fp': kin.fp, 'eval': res}
torch.save(sd, os.path.join(a.out, 'last.pt'))