From 422fb8b72f4e897fd7aa3f80f8b807f35ecd737d Mon Sep 17 00:00:00 2001 From: cbb <2625274797@qq.com> Date: Tue, 20 Oct 2026 22:10:44 +0800 Subject: [PATCH] =?UTF-8?q?exp+fix:=20=E8=BD=AE=E6=AC=A139=E2=80=94?= =?UTF-8?q?=E2=80=94backoff=3D0+cert=5Fbatch1=20=E4=B8=8E=E8=BD=AE?= =?UTF-8?q?=E6=AC=A133=20cap=20=E9=80=90=E9=A1=B9=E7=9B=B8=E5=90=8C(?= =?UTF-8?q?=E9=87=8D=E5=86=99=E6=89=B9=E9=87=8F=E5=88=86=E6=94=AF=E6=97=A0?= =?UTF-8?q?=E8=A1=8C=E4=B8=BA=E5=8F=98=E5=8C=96)=EF=BC=9B=E4=BF=AE=20backo?= =?UTF-8?q?ff=20=E6=8C=87=E6=A0=87=E8=A2=AB=20eval=5Fcl=20=E6=98=BE?= =?UTF-8?q?=E5=BC=8F=E9=94=AE=E5=88=97=E8=A1=A8=E4=B8=A2=E6=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/experiment_round38_backoff0.json | 73 +++++++++++++++++++++++++++ docs/探索日志.md | 4 ++ ml/eval/eval_cl.py | 3 ++ 3 files changed, 80 insertions(+) create mode 100644 docs/experiment_round38_backoff0.json diff --git a/docs/experiment_round38_backoff0.json b/docs/experiment_round38_backoff0.json new file mode 100644 index 0000000..c3945c8 --- /dev/null +++ b/docs/experiment_round38_backoff0.json @@ -0,0 +1,73 @@ +{ + "config": { + "ckpt": "ml/runs/base_dag2_dag1/best.pt", + "samples": "ml/data/samples", + "tasks": null, + "split": "val", + "n": 256, + "K": 8, + "commit": 2, + "fb": 2.2, + "ki": 0.0, + "fb_scale": 0.0, + "fb_near": 0.2, + "fb_fallback": 0.0, + "kdecay": 0.9, + "kimax": 0.5, + "fb_every": 1, + "safety_try": 0, + "sel_w": 0.1, + "dls_safety": 1, + "fb_clear": 0.0, + "fb_cmin": 0.3, + "sub_refresh": 0, + "fb_block_gain": 0.5, + "dump": null, + "out": "docs/experiment_round38_backoff0.json", + "trace": null, + "select": "endpoint", + "replan": "empty", + "safety": 1, + "partial": 1, + "inc_cap": 1, + "gap_margin": 0.0, + "cert_batch": 1, + "steps": 1, + "backoff": 0, + "max_sec": null, + "seed": 0, + "dls": "analytic", + "device": "cuda" + }, + "batch_size": 256, + "batch_seed_rule": "same seed per batch", + "checkpoint_sha256": "f7f686fd8ee92fb6948fbcc4ee954636065ad87bb54f661c4f8f575bc16c2ce1", + "tasks_sha256": "249bd93457825cda98c59e64d9a096d3473c69aeb3553de1dea6d9e56be71772", + "kin_fp": "2ebcbf17", + "act_scale": 1.0, + "metrics": { + "n": 256, + "n_ref": 256, + "success": 0.5234375, + "collision_free_success": 0.5234375, + "time_ok_1p3": 0.265625, + "collision_rate": 0.0, + "collision_steps_mean": 0.0, + "travel_ratio_median": 2.615795850753784, + "time_mean_s": 2.486567258834839, + "brakes_mean": 19.5546875, + "start_fail": 0.0, + "goal_ratio_2s": 0.27920001745224, + "err_fail_med": 204.71360778808594, + "err_success_med": 0.21751396358013153, + "dls_share": 0.61328125, + "time_budget": "teacher×2(≥3 s)", + "speed_ratio_p50": 1.0000016689300537, + "speed_ratio_p95": 1.0000101327896118, + "speed_ratio_max": 1.0000101327896118, + "over_vmax_rate": 0.0, + "accel_ratio_p95": 1.0000016689300537, + "accel_ratio_max": 1.0000101327896118 + }, + "simulation_wall_s": 329.1139315000037 +} diff --git a/docs/探索日志.md b/docs/探索日志.md index 5303af8..30637c9 100644 --- a/docs/探索日志.md +++ b/docs/探索日志.md @@ -47,6 +47,10 @@ - 待测:`len_w ∈ {0.1, 0.3, 1.0}` 三臂,看行程比能压到多少、到达与时限各付多少。这条杠杆与"到达率"是相互冲突的目标(惩罚行程=主动走慢),所以必须成对汇报,不能只报行程变好。 - 单位口径要说清:`len_w` 的量纲是"mm 误差 / 一个归一 STEP 的累计行程",16 步满速在 3 条轴上大约是 48,所以 0.1~1.0 对应的惩罚是 5~50 mm 当量——这是扫这三个值的原因,不是随手取的。 - 测试 `tests/test_eval_cl.py` 38→40 项、全套 43→45 项(`python -m unittest discover -s tests`,2.2 s 全绿)。GPU 队列顺序:backoff A/B → `--safety 0` 判别 → 候选档位 → 行程惩罚。 +- **等价闸门先过了**:`--backoff 0 --cert_batch 1 --inc_cap 1` 的 256 题与轮次 33 cap(`--cert_batch 0`)**逐项完全相同**(`docs/experiment_round38_backoff0.json` 对 `docs/experiment_round33_cap.json`,把两个 metrics 字典做键并集比较,差异集合为空,含 success 0.523438、time_ok 0.265625、brakes 19.55…)⇒ 轮次 36 我把批量认证分支重写(加缩步档那一段)没有改动任何行为。 +- **两个我自己的操作失误,如实记在这里**: + 1. 新加的 `backoff` 指标一度在产物里根本没有——`ml/eval/eval_cl.py:run()` 的 `out` 是**自己显式列键**的,不是从 `rollout` 返回的字典通抄,所以我往 `res` 加的 `backoff_mean` 被无声丢掉。已改成从逐题 `per['backoff']` 汇总(`backoff_mean` + `reject_all_mean = backoff+brakes`,后者才是与"原来全拒次数"可比的量)。**教训:加指标要顺着输出链路走到底,别只改生产端。** + 2. 停后台 GPU 作业时,`TaskStop` 之后 `bash` 脚本链会活下来并继续拉起下一个 python;而 `nvidia-smi --query-compute-apps` 在这台机器上列不出这些 python(只列 ShellHost/wallpaper32 之类),据此判断"卡已空"会误判。我第一次按 PID 杀子进程后,链条 30 秒后又起了一个新的 eval。第二次我按进程树杀,但**把父子关系读反了**(Windows 的 PPID 在父进程已死时是陈旧值),结果误杀了新链的第一臂。正确做法:重启前用命令行正则列出全量候选、数 python 个数确认单租户,重启后再数一次;杀之前先按 `StartTime` 判新旧。backoff 那一臂因此要补跑。 ## 轮次 38:把 `--steps` 打通之后,闭环反而变差——瓶颈从"动作质量"移到了"安全层拒绝率" diff --git a/ml/eval/eval_cl.py b/ml/eval/eval_cl.py index a5823d7..bfcd66d 100644 --- a/ml/eval/eval_cl.py +++ b/ml/eval/eval_cl.py @@ -49,6 +49,9 @@ def run(model, kin, tasks, device, bs=256, **kw): out.update({'speed_ratio_p50': median(v), 'speed_ratio_p95': v.quantile(0.95).item(), 'speed_ratio_max': v.max().item(), 'over_vmax_rate': (v > 1.001).float().mean().item(), 'accel_ratio_p95': acc.quantile(0.95).item(), 'accel_ratio_max': acc.max().item()}) + if 'backoff' in flat and flat['backoff'].any(): # backoff=缩步顶上的次数;brakes 现在只记连最小档都不安全的 + out['backoff_mean'] = flat['backoff'].mean().item() # ⇒ 原来的"全拒"事件数 = 两者之和 + out['reject_all_mean'] = (flat['backoff'] + flat['brakes']).mean().item() return out, per