第六、七轮:离线 ort/WebGPU、R9 查看器整周期、安全层截止下沉、enc_once 前瞻 bug(feat 动态轴)、UTF-8、断点 RNG 续跑与 --stop-at、R2 池无关性自检、R8 出题缓存、本机自检 selftest、冒烟 smoke;遗留清单并入审查文档第六节

This commit is contained in:
Hark
2026-10-18 06:40:25 +08:00
committed by cbb
parent b6141d237c
commit 591678703a
29 changed files with 715 additions and 127 deletions
+31 -13
View File
@@ -6,8 +6,8 @@
2026-10-18 第五轮(审查 N-2:判据与搜索池耦合):最近 5% 的近邻距离随池大小变,label_std 随之系统偏大/偏小。
改为按"近邻距离 → 标签差"做线性回归,取距离 → 0 的截距 label_std_norm 作判据(与池大小无关:池大只是近邻更近、点更多,
截距估计的是"同一输入下的固有标签分歧");旧口径 label_std_mean 保留作参考。pipeline 默认只警告,R2_STRICT=1 才拦。
自检:同一份数据 --pool 50000 与 --pool 200000 两跑,label_std_norm 应一致(差 < 0.02)。
2026-10-18 新增(审查:R2 无执行点)。默认 5000 查询 × 50000 池,分块 256:GPU 峰值 < 0.5 GB,CPU 约 1–2 分钟;近邻对为空时输出 pass=null 而不报错。"""
自检(第七轮起每次自动做):--pool 50000 与 4 倍池 200000 各测一次,label_std_norm 差 < 0.02 记 pool_check.independent=true。
2026-10-18 新增(审查:R2 无执行点)。默认 5000 查询 × 50000 池,分块 256:GPU 峰值 < 0.5 GB,连同 4 倍池自检 CPU 约 5–10 分钟、GPU 约 1 分钟;近邻对为空时输出 pass=null 而不报错。"""
import argparse, json, math
import torch
@@ -18,13 +18,34 @@ 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=5000); ap.add_argument('--pool', type=int, default=50000)
ap.add_argument('--pool2', type=int, default=0, help='池无关性自检的大池(默认 4×pool)')
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')
P2 = a.pool2 if a.pool2 else 4 * a.pool
r1 = measure(d, a, a.pool)
if r1.get('pairs', 0) == 0:
out = r1
else:
# 2026-10-18 第七轮(遗留 C-3):池无关性自检并入每次运行——同一批查询、池放大 4 倍再测一次,
# 截距差 < 0.02 才说明 label_std_norm 这把尺可信(independent=true);判定用大池的数(近邻更近、截距更稳)。
r2 = measure(d, a, P2) if min(P2, d.n) > r1['pool'] else None
out = dict(r2 or r1)
out['pool_check'] = {'pool_small': r1['pool'], 'norm_small': r1['label_std_norm'],
'pool_big': r2['pool'] if r2 else None, 'norm_big': r2['label_std_norm'] if r2 else None,
'diff': abs(r2['label_std_norm'] - r1['label_std_norm']) if r2 else None,
'independent': (abs(r2['label_std_norm'] - r1['label_std_norm']) < 0.02) if r2 else None,
'note': '样本数不足 4 倍池时只测一次' if not r2 else '差 < 0.02 → 判据与池无关,R2_STRICT=1 可以放心打开'}
print(json.dumps(out, indent=1))
json.dump(out, open(a.out, 'w'), indent=1)
def measure(d, a, pool):
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]
P = min(pool, d.n); Q = min(a.queries, d.n)
qi = torch.randperm(d.n, device=a.device, generator=g)[:Q] # 查询集与池大小无关(先抽查询)
pi = torch.randperm(d.n, device=a.device, generator=g)[:P]
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]
@@ -35,8 +56,7 @@ def main():
v, j = D.min(1); best_d[s:s + 256] = v; best_j[s:s + 256] = j
fin = torch.isfinite(best_d)
if fin.sum() < 20:
out = {'pairs': 0, 'label_std_mean': None, 'pass': None, 'pool': P, 'rule': 'label_std_norm < 0.10', 'note': '近邻对不足(样本太少),未判定'}
print(json.dumps(out)); json.dump(out, open(a.out, 'w'), indent=1); return
return {'pairs': 0, 'label_std_mean': None, 'pass': None, 'pool': P, 'rule': 'label_std_norm < 0.10', 'note': '近邻对不足(样本太少),未判定'}
# 与池无关的口径:全部有效近邻对(取距离较近的一半,排除远处非线性段)上回归 std ~ a + b·dist,截距 a
dd = best_d[fin]; jj = best_j[fin]; qf = torch.nonzero(fin).squeeze(1)
half = dd <= torch.quantile(dd, 0.5)
@@ -50,13 +70,11 @@ def main():
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()), 'pool': P, 'queries': Q, 'nn_dist_threshold': thr.item(),
'label_std_norm': std_norm, 'label_std_slope': coef[1].item(),
'label_std_mean': std.mean().item(), 'label_std_p90': torch.quantile(std, 0.9).item(),
'pass': std_norm < 0.10,
'rule': 'label_std_norm(近邻距离→0 的回归截距)< 0.10(10% 步长);label_std_mean 为旧口径(随池大小变),仅参考'}
print(json.dumps(out, indent=1))
json.dump(out, open(a.out, 'w'), indent=1)
return {'pairs': int(m.sum()), 'pool': P, 'queries': Q, 'nn_dist_threshold': thr.item(),
'label_std_norm': std_norm, 'label_std_slope': coef[1].item(),
'label_std_mean': std.mean().item(), 'label_std_p90': torch.quantile(std, 0.9).item(),
'pass': std_norm < 0.10,
'rule': 'label_std_norm(近邻距离→0 的回归截距)< 0.10(10% 步长);label_std_mean 为旧口径(随池大小变),仅参考'}
if __name__ == '__main__':