ml: 按运行手册审查修订——头分目录不互相覆盖(ml/runs/<CFG>、selected_ckpt/CKPT);统一 $PYTHON(Windows Git Bash 可跑);gen 按实测样本/任务自动补量;R10 改终态判据(≥5k 样本/s≈60k 步≤3.5h);m5 纯策略/仿真安全层双口径;无老师题定长 6 s 口径;APG 展开随批时长、端点+中点铰链、余量 3 mm(投影同步);挖错池只用本轮;门禁加 R7;bench 加 R8 对抗集与刹停率、--nc-n/--route-n/--r8-n;新增 check_r2 与 acceptance;export 默认 fp32;出题分块防 OOM;val 为空保护
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
"""方案 R2 数据侧检查:近邻样本的标签是否自洽(时间律不可观测成分会让相同输入对应不同动作)。
|
||||
python -m ml.eval.check_r2 --samples ml/data/samples --out ml/data/r2.json
|
||||
做法:特征逐维标准化;随机取 Q 个查询样本,在 P 个样本池里找最近邻(排除同一任务,避免同轨迹相邻帧冒充"近邻");
|
||||
取距离最近的 5% 近邻对,比较前 3 步(实际提交的动作)标签:std ≈ RMS(ΔY)/√2,单位为每步最大步长 STEP 的比例。
|
||||
判据:label_std < 0.10(即 < 10% 步长)。起步失败率在闭环仿真结果的 start_fail 字段(acceptance 汇总)。
|
||||
2026-10-18 新增(审查:R2 无执行点)。GPU 上约 1 分钟;CPU 上把 --pool 降到 50000。"""
|
||||
import argparse, json, math
|
||||
import torch
|
||||
|
||||
from ml.data import Samples
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument('--samples', nargs='+', default=['ml/data/samples']); ap.add_argument('--out', default='ml/data/r2.json')
|
||||
ap.add_argument('--queries', type=int, default=20000); ap.add_argument('--pool', type=int, default=200000)
|
||||
ap.add_argument('--frac', type=float, default=0.05); ap.add_argument('--seed', type=int, default=0)
|
||||
ap.add_argument('--device', default='cuda' if torch.cuda.is_available() else 'cpu')
|
||||
a = ap.parse_args()
|
||||
d = Samples(a.samples, device=a.device, split='train')
|
||||
g = torch.Generator(device=a.device); g.manual_seed(a.seed)
|
||||
P = min(a.pool, d.n); Q = min(a.queries, d.n)
|
||||
pi = torch.randperm(d.n, device=a.device, generator=g)[:P]; qi = torch.randperm(d.n, device=a.device, generator=g)[:Q]
|
||||
X = d.X.float(); mu, sd = X[pi].mean(0), X[pi].std(0).clamp(min=1e-6)
|
||||
Xp, Xq = (X[pi] - mu) / sd, (X[qi] - mu) / sd
|
||||
tp, tq = d.TID[pi], d.TID[qi]
|
||||
best_d = torch.empty(Q, device=a.device); best_j = torch.empty(Q, dtype=torch.long, device=a.device)
|
||||
for s in range(0, Q, 1024):
|
||||
D = torch.cdist(Xq[s:s + 1024], Xp)
|
||||
D = torch.where(tq[s:s + 1024, None] == tp[None], torch.full_like(D, float('inf')), D)
|
||||
v, j = D.min(1); best_d[s:s + 1024] = v; best_j[s:s + 1024] = j
|
||||
fin = torch.isfinite(best_d)
|
||||
thr = torch.quantile(best_d[fin], a.frac)
|
||||
m = fin & (best_d <= thr)
|
||||
Yq, Yp = d.Y[qi][m, :3].float(), d.Y[pi][best_j[m], :3].float()
|
||||
rms = (Yq - Yp).pow(2).mean(-1).mean(-1).sqrt() # 每对、6 轴 × 3 步平均
|
||||
std = (rms / math.sqrt(2))
|
||||
out = {'pairs': int(m.sum()), 'nn_dist_threshold': thr.item(), 'label_std_mean': std.mean().item(),
|
||||
'label_std_p90': torch.quantile(std, 0.9).item(), 'pass': std.mean().item() < 0.10,
|
||||
'rule': 'label_std_mean < 0.10(10% 步长)'}
|
||||
print(json.dumps(out, indent=1))
|
||||
json.dump(out, open(a.out, 'w'), indent=1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user