ml/gen: 确定性老师(碰撞次数计时 + resetSession)、pos 任务冻结 J6、--consensus 邻域共识过滤、Dr 类、README(高性能机器运行说明)

This commit is contained in:
Hark
2026-10-17 15:48:19 +00:00
parent b02b8291c4
commit 7e70c4e811
8 changed files with 109 additions and 23 deletions
+20 -2
View File
@@ -1,5 +1,7 @@
/* M1 数据生成器(2026-10-17,方案 §4)
* node ml/gen/gen_dataset.cjs --n 500 --seed 1 --out ml/data/shard_0001.jsonl
* node ml/gen/gen_dataset.cjs --n 500 --seed 1 --out ml/data/shard_0001.jsonl [--consensus 4]
* --consensus k:邻域共识过滤。起点不变、目标位置各扰动 5 mm 造 k 个邻居跑老师,原任务路径若与多数邻居
* 不在同一绕行类(pathdev.sameClass),整条样本 keep=false(why=consensus)。成本约 (1+k) 倍。
* 每行一条任务:采样 → 老师 → 距离下界认证过滤 → 局部时间律(50 Hz)→ 写出。
* 认证不过的样本也写出(keep=false + 原因),供 stats 统计丢弃率;训练只用 keep=true。 */
'use strict';
@@ -9,6 +11,8 @@ const N = +args.n || 100, SEED = +args.seed || 1, OUT = args.out || 'ml/data/sha
const { S, ArmIK } = require('../../tests/route_bench_setup.cjs')();
const sampler = require('./sampler.cjs')(S, SEED * 7919 + 13);
const teach = require('./teacher.cjs')(S, ArmIK);
const { sameClass } = require('./pathdev.cjs');
const K_CONS = +args.consensus || 0;
const LEVER = S.leverBounds(4000);
const cert = require('./cert.cjs')(S, { lever: LEVER });
const { timeParam } = require('./timelaw.cjs');
@@ -24,12 +28,26 @@ for (let i = 0; i < N; i++) {
q0: task.q0.map(r3), T: task.T.map(r3), R: task.R, fp };
if (!t.ok) { rec.keep = false; rec.why = t.why; fs.writeSync(fd, JSON.stringify(rec) + '\n'); continue; }
const c0 = performance.now();
const c = cert.path(t.pts);
let c = null;
if (t.ptsJ6Frozen) { const cf = cert.path(t.ptsJ6Frozen); if (cf.ok) { t.pts = t.ptsJ6Frozen; t.travel = t.travelOf(t.pts); c = cf; rec.j6Frozen = true; } }
if (!c) c = cert.path(t.pts);
if (task.cat === 'D' && t.reached) rec.cat = 'Dr'; // "不可达"采样其实可达:单独记类,不当停靠样本
Object.assign(rec, { path: t.pts.map(q => q.map(r3)), reached: t.reached, err: r3(t.err), oerr: r3(t.oerr), travel_deg: r3(t.travel),
plan_ms: Math.round(t.ms), blocked: t.blocked, poseRelaxed: t.poseRelaxed, detour: t.detour,
cert: { ok: c.ok, queries: c.queries, minGap: r3(c.minGap), ms: Math.round(performance.now() - c0), why: c.why || null, failAt: c.failAt == null ? null : c.failAt } });
/* 训练可用:认证通过;D 类允许未到达(停靠),其余类必须到达;poseRelaxed 的 pose 样本降为 pos */
rec.keep = c.ok && (t.reached || task.cat === 'D');
if (rec.keep && K_CONS > 0 && t.reached) {
let agree = 0, valid = 0;
for (let k = 0; k < K_CONS; k++) {
const u = [sampler.rnd() - 0.5, sampler.rnd() - 0.5, sampler.rnd() - 0.5], n = Math.hypot(u[0], u[1], u[2]);
const nb = teach(Object.assign({}, task, { T: task.T.map((v, j) => v + 5 * u[j] / n) }));
if (!nb.ok || !nb.reached) continue;
valid++; if (sameClass(t.pts, nb.ptsJ6Frozen && rec.j6Frozen ? nb.ptsJ6Frozen : nb.pts, task.mode)) agree++;
}
rec.consensus = { agree, valid };
if (valid >= 2 && agree * 2 < valid) { rec.keep = false; rec.why = 'consensus'; }
}
if (t.poseRelaxed && task.mode === 'pose') { rec.mode = 'pos'; rec.R = null; rec.demoted = true; rec.reached = t.err < 1; }
if (rec.keep) { const tp = timeParam(t.pts); rec.traj = tp.traj.map(q => q.map(r3)); rec.exec_s = r3(tp.steps * 0.02); }
fs.writeSync(fd, JSON.stringify(rec) + '\n');