Lee93whut Lee93whut commited on
Commit
e1ecae1
·
1 Parent(s): 17bc537

docs: polish pass — README wording, experiment_log structure + honest retrospective, LaTeX micro-style

Browse files

Four docs-only commits consolidated into one since they were all
discrete cleanups surfaced by the same review pass across three
documentation files:

1) README.md — tighten wording and drop unsupported specifics
- "扩大约 40 倍" -> "急剧扩大": the 40x figure was a hand-waved
estimate, not a measured ratio
- Drop two redundant "纯提效" trailing notes in §1.3 and §1.5
- §1.4 EVAL-checkpoint "直接效果" line: drop trailing parenthetical
pointing to visited_map / Dueling (the same content lives in
"核心发现" with full context)
- §1.5 "作用" sentence: replace "纯提效 + 评估可信度" with a
one-line statement that reproducibility is the prerequisite for
cross-run comparison
- Weights section: drop the "不托管在 GitHub(二进制文件不适合
git)" aside

2) docs/experiment_log.md — convert raw EVAL traces to stage tables
and drop operational metadata
- R3 / R4-A2 / R4-A3 long per-100ep raw dumps -> 5/4/4-row
"phase / ep range / success rate / note" tables
- R3 screenshot bullets -> screenshot-table format (matching R1/R2)
- Drop 4 TensorBoard run-directory blocks and the R4 "所需截图"
checklist (operational metadata, not for end-reader)
- Collapse verbose explanations to single sentences (P8 code block,
Dueling "参数共享" 3-state elaboration, vanilla 19pp gap two-reason
breakdown, double_dueling < dueling 3-reason analysis, final
5-point conclusion, R1 "下一步行动" plan R2-R4 in one shot)

3) docs/experiment_log.md — clarify R3-only data scope and honest
retrospective of R4 plan vs execution
- Section heading: "循环失败率的直接测量(R4 引入 4 通道的依据)"
-> "R3 失败模式直接测量(提供 R4 引入 4 通道的数据依据)" — the
100-ep measurement was taken at the end of R3, not after R4 ran
- Drop the R4 column from the §四 table (filled in later, not
R3-timepoint data); host the R3-vs-R4 comparison in a new
section placed after R4-A3 results
- Replace the n.s. bullet (R3-vs-R4 conclusion) with a R3-timepoint
bullet pointing to the visited_map fix direction
- R4 行动计划 table: old "R4 配置" listed revisit_penalty=-1.0 as
if it were R4 config, but it was a R4-A1 ablation candidate
(failed). New table lists the three changes that actually shipped
and notes revisit_penalty as parallel ablation candidate
- New trailing paragraph clarifies the R4-续 algorithm ablation was
a second step taken after the double algorithm's ceiling was
confirmed, not part of the original R4 plan
- New "循环失败率 R3 / R4 对照" section after R4-A3 hosts the
R3-vs-R4 data in its correct timepoint

4) docs/technical_report.md §4.3 — LaTeX micro-style in Grid-SPL
formula
- \text{SPL} -> \mathrm{SPL}: \text renders the operator in
text-mode font and spacing; \mathrm is the correct command for
an upright math operator name
- \ell^{*}_{i} -> \ell^*_i: subscript target is a single character,
braces are redundant
- \max(\ell^*_i, \,\, p_i) -> \max(\ell^*_i, p_i): \max et al.
insert their own thin space before the opening paren via LaTeX's
operator spacing

Net effect: 4 commits -> 1 docs polish commit + 1 chore commit, log
reads as [chore / docs] instead of [docs / docs / docs / docs / docs]
interspersed with a chore. R3/R4 record and technical narrative are
unchanged; only the surface-level wording, table layout, plan-vs-
execution honesty, and LaTeX micro-style are fixed.

Co-Authored-By: Lee93whut <30529279@qq.com>

Files changed (3) hide show
  1. README.md +8 -11
  2. docs/experiment_log.md +110 -192
  3. docs/technical_report.md +2 -2
README.md CHANGED
@@ -22,9 +22,9 @@ license: mit
22
 
23
  ## 项目背景
24
 
25
- 10×10 随机迷宫本身足够简单(原始 DQN 在固定起终点可达 90%+),但**随机起终点 + 随机地图**让状态空间扩大约 40 倍,把"走通迷宫"变成"学一种导航策略"——初版 DQN 在此设定下仅 **61% 成功率**。
26
 
27
- 本项目的目标不是再提升一两个百分点,而是**走完一遍完整的方法论**:先做冒烟验证排除工程 bug,再做 4 轮超参消融(每轮只改一组变量,用问题诊断驱动下一轮变更),后固定最优超参做四算法横向消融。整个过程把 Holdout 成功率从 61% 推到 84%(+23pp:超参调优 +17pp,算法切换 +6pp)。
28
 
29
  途中还发现并修复了一类常见的 RL 工程错误——**奖励依赖 episode 内历史,违反马尔可夫性**(详见"核心发现")。
30
 
@@ -37,7 +37,7 @@ license: mit
37
 
38
  ### 训练结果呈现顺序
39
 
40
- 本节按"训练过程的时间顺序"组织:先看超参演进的纵向消融(同一算法、固定数据集、不同超参),再看 R4 算法横向消融(固定最优超参、不同算法)——这样才能把"哪个提升来自超参、哪个来自算法"分清
41
 
42
  #### 第一阶段:超参演进纵向对比(Double DQN,保持算法一致)
43
 
@@ -58,7 +58,7 @@ license: mit
58
 
59
  #### 第二阶段:R4 算法横向消融(固定 R4 最优超参,唯一变量 = 算法)
60
 
61
- R4 既然已到超参极限换算法就是"把相同的训练数据 + 同样的训练步数给四种网络架构,看谁能在 Holdout 上多拿 6pp":
62
 
63
  | 排名 | 算法 | Holdout | SPL | EVAL→Holdout Gap |
64
  |:---:|------|:-------:|:---:|:----------------:|
@@ -167,7 +167,7 @@ if eval_success_rate > best_eval_success:
167
  torch.save({"state_dict": policy_net.state_dict(), ...}, best_model_path)
168
  ```
169
 
170
- **直接效果**:避免 R3 的 EVAL 峰值 84% / Holdout 仅 74% 的 10pp 错位,R4 Holdout 回升至 78%(+4pp)。马尔可夫性修复(visited_map 第四通道)和 Dueling 适配详见"核心发现"。
171
 
172
  ### 2. 训练信号侧的"三项叠加"(ep/buffer/target 调优 + BFS 连通性)
173
 
@@ -192,16 +192,14 @@ if eval_success_rate > best_eval_success:
192
  | `Frontend_Env/` | `episode` | 每局结束后 | 避免"每局更新步数不同"导致 Loss 曲线横向压缩 |
193
  | `Evaluation_Exam/` | `episode` | 每 N 局暂停训练、`model.eval()` | 训练/评估指标分轴对比,避免视觉误导 |
194
 
195
- **作用**:纯提效——诊断问题时不用猜"这条陡降到底是 eval 触发了还是 loss 飙升了"。
196
-
197
  ### 5. 唯一随机源 + 评估集可复现
198
 
199
  `maze_env/env.py` 所有随机操作统一走 Gymnasium 注入的 `self.np_random`。
200
 
201
  - 训练时 `env.reset()` 不传 seed → 训练地图每局不同,强制学泛化
202
- - 评估时 `env.reset(seed=X)` 固定 → 同一 seed 永远生成同一张地图,Holdout 100 张地图可精确复现,论文级可对比
203
 
204
- **作用**:纯提效 + 评估信度。如果评估地图每次都变,"成功率 78%"这个数字就没有任何重复可言
205
 
206
  ---
207
 
@@ -252,8 +250,7 @@ docker build -t maze-dqn-demo .
252
  docker run --rm -p 7860:7860 maze-dqn-demo
253
  ```
254
 
255
- > 权重文件不托管在 GitHub(二进制文件不适合 git),统一存放于
256
- > [HF Spaces lil58/interview](https://huggingface.co/spaces/lil58/interview)。
257
  > `download_weights.py` 会跳过已存在的文件,重复执行安全。
258
 
259
  ```bash
 
22
 
23
  ## 项目背景
24
 
25
+ 10×10 随机迷宫本身足够简单(原始 DQN 在固定起终点可达 90%+),但**随机起终点 + 随机地图**让状态空间急剧扩大,把"走通迷宫"变成"学一种导航策略"——初版 DQN 在此设定下仅 **61% 成功率**。
26
 
27
+ 本项目的目标不是再提升一两个百分点,而是**走完一遍完整的方法论**:先做冒烟验证排除工程 bug,再做 4 轮超参消融(每轮只改一组变量,用问题诊断驱动下一轮变更),超参调优至可接受的成功率后固定下来,做四算法横向消融。整个过程把 Holdout 成功率从 61% 推到 84%(+23pp:超参调优 +17pp,算法切换 +6pp)。
28
 
29
  途中还发现并修复了一类常见的 RL 工程错误——**奖励依赖 episode 内历史,违反马尔可夫性**(详见"核心发现")。
30
 
 
37
 
38
  ### 训练结果呈现顺序
39
 
40
+ 本节按"训练过程的时间顺序"组织:先看超参演进的纵向消融(同一算法、固定数据集、不同超参),再看 R4 算法横向消融(固定最优超参、不同算法)。
41
 
42
  #### 第一阶段:超参演进纵向对比(Double DQN,保持算法一致)
43
 
 
58
 
59
  #### 第二阶段:R4 算法横向消融(固定 R4 最优超参,唯一变量 = 算法)
60
 
61
+ R4 超参调优至可接受准确率后,换算法就是"把相同的训练数据 + 同样的训练步数给四种网络架构,看谁能在 Holdout 上多拿 6pp":
62
 
63
  | 排名 | 算法 | Holdout | SPL | EVAL→Holdout Gap |
64
  |:---:|------|:-------:|:---:|:----------------:|
 
167
  torch.save({"state_dict": policy_net.state_dict(), ...}, best_model_path)
168
  ```
169
 
170
+ **直接效果**:避免 R3 的 EVAL 峰值 84% / Holdout 仅 74% 的 10pp 错位,R4 Holdout 回升至 78%(+4pp)。
171
 
172
  ### 2. 训练信号侧的"三项叠加"(ep/buffer/target 调优 + BFS 连通性)
173
 
 
192
  | `Frontend_Env/` | `episode` | 每局结束后 | 避免"每局更新步数不同"导致 Loss 曲线横向压缩 |
193
  | `Evaluation_Exam/` | `episode` | 每 N 局暂停训练、`model.eval()` | 训练/评估指标分轴对比,避免视觉误导 |
194
 
 
 
195
  ### 5. 唯一随机源 + 评估集可复现
196
 
197
  `maze_env/env.py` 所有随机操作统一走 Gymnasium 注入的 `self.np_random`。
198
 
199
  - 训练时 `env.reset()` 不传 seed → 训练地图每局不同,强制学泛化
200
+ - 评估时 `env.reset(seed=X)` 固定 → 同一 seed 永远生成同一张地图,Holdout 100 张地图可精确复现
201
 
202
+ **作用**:可复现性是评估结果具备对比的前提
203
 
204
  ---
205
 
 
250
  docker run --rm -p 7860:7860 maze-dqn-demo
251
  ```
252
 
253
+ > 权重文件统一存放于 [HF Spaces lil58/interview](https://huggingface.co/spaces/lil58/interview)。
 
254
  > `download_weights.py` 会跳过已存在的文件,重复执行安全。
255
 
256
  ```bash
docs/experiment_log.md CHANGED
@@ -15,7 +15,7 @@
15
  | Round 2 | 随机起终点 | `ep=6000` + `decay=0.9985` | 64.0% | 0.633 | 74% | P1/P2 修复,新发现 buffer 过小(P3)和 target 同步过频(P4)|
16
  | Round 3 | 随机起终点 | `buffer=80k` + `target=1500` | **74.0%** | **0.735** | **84%** | 峰值突破 80%;Holdout 低于峰值 10pp,根因为保存策略 |
17
  | Round 4 | 随机起终点 | EVAL-based checkpoint + BFS 连通性验证;探索 revisit_penalty(失败)和 visited_map 4通道 | **78.0%**(A3,double 算法) | **0.773** | **88%** | P7(checkpoint时序)+P8(无解任务)系统性修复;P9(马尔可夫违反)新发现;A3为三项变量叠加,非单因素对照 |
18
- | Round 4(续)| 随机起终点 | R4-A3 超参固定,四算法横向消融(唯一变量=算法)| **84.0%**(dueling,最优) | **0.817** | **94%**(vanilla) | dueling EVAL→Holdout gap=6pp 最优泛化;double_dueling 81%;vanilla 75%(19pp gap 虚高);Double DQN 危机恢复快但终态不及纯 dueling |
19
 
20
  **关键结论链**:随机起终点使状态空间扩大约 40×,需要更长训练(R2)→ 更大 buffer 保留稀疏成功样本(R3)→ 修复 checkpoint 时序偏差 + 连通性验证 + visited_map 状态编码(R4)→ Dueling 架构的 V/A 分解与多动作等效迷宫导航任务高度适配(R4 算法消融)。奖励层循环抑制违反马尔可夫性(P9);状态层编码(visited_map)理论正确;最优配置(dueling + EVAL checkpoint + BFS + visited_map)最终将 Holdout 从 74%(R3)提升至 **84%**(+10pp)。
21
 
@@ -127,15 +127,6 @@ ep=2000 时 Blind Test 成功率仍在上升,无收敛平台期。
127
  随机起终点导致 Q 值估计方差更高,频繁同步加剧 bootstrapping instability。
128
  依据:Mnih et al. (2015) 原版更新周期 10000 步,DQN loss $\mathcal{L}(\theta) = \mathbb{E}[(r + \gamma \max_{a'} Q_{\theta^-}(s',a') - Q_\theta(s,a))^2]$ 中 $\theta^-$ 须提供固定回归目标,同步过频等价于用移动靶做监督学习。
129
 
130
- ### TensorBoard 运行目录
131
-
132
- ```
133
- runs/train_vanilla_20260531_000453/
134
- runs/train_double_20260531_004241/
135
- runs/train_dueling_20260531_012950/
136
- runs/train_double_dueling_20260531_023152/
137
- ```
138
-
139
  ### TensorBoard 曲线截图(与 P1–P4 诊断一一对应)
140
 
141
  | 截图 | 论证的诊断点 | 解读 |
@@ -144,20 +135,16 @@ runs/train_double_dueling_20260531_023152/
144
  | ![Epsilon](assets/round1/r1_frontend_epsilon.png) | P2 | ε 在 ep≈800 触底 0.05,P2 探索过早终止的直接证据 |
145
  | ![Loss](assets/round1/r1_backend_loss.png) | P4 | Loss 高频震荡,target 同步过频的间接证据 |
146
 
147
- > 已删除 R1 文档无诊断对应的 SPL/AvgQ/GradNorm 截图。
148
 
149
  ### 结论与下一步行动
150
 
151
  **已确认问题**(按优先级):
152
- 1. **P1+P2(高优先级)**:训练量不足 + 探索过早终止是最直接的瓶颈,曲线证据充分
153
- 2. **P3(中优先级)**:buffer=20000 约 250 局轮换,预测 Round 2 将出现 400–500 ep 周期振荡
154
  3. **P4(中优先级)**:target 同步 272 次/轮,高 Q 方差场景下移动靶效应显著
155
 
156
- **下一步行动(基于 R1际数能合理推断范围)**:
157
-
158
- R1 暴露了 P1+P2+P3+P4 四个问题,且可预测 P3 的振荡周期。**R1 当时能直接决定的修复只有 P1+P2**(成对修改`num_episodes` 与 `epsilon_decay`),P3+P4 需在 R2 长曲线上验证后才能量化决定如何修复(如 buffer 扩到多少、target_update_freq 调到多少)。后续步骤(R3 验证、R4 checkpoint 修复、visited_map 引入)均需 R2/R3 实际数据才能合理设计,**不在 R1 阶段可推断范围**。
159
-
160
- > 注:本节初稿曾一次性规划 R2-R4 全部步骤,但实际后续轮次的修复方向(P7 EVAL checkpoint、P8 BFS、visited_map 4通道)是 R2/R3 实跑后才发现的,不是 R1 阶段可预测的;故重写为只保留 R1 当时能直接合理推断的下一步。详见 `docs/hyperparameter_study.md` 第五节。
161
 
162
  ---
163
 
@@ -278,12 +265,6 @@ $\theta^-$ 作用是提供暂时固定的回归目标,若更新太频��,等
278
 
279
  ---
280
 
281
- ### TensorBoard 运行目录
282
-
283
- ```
284
- runs/Round2_double_epsilon0.9985_ep6000/
285
- ```
286
-
287
  ### TensorBoard 曲线截图(与 P1–P4 诊断一一对应)
288
 
289
  | 截图 | 论证的诊断点 | 解读 |
@@ -292,7 +273,7 @@ runs/Round2_double_epsilon0.9985_ep6000/
292
  | ![R1 vs R2 Epsilon](assets/compare/cmp_frontend_epsilon_r1_vs_r2.png) | P2 验收 | R2 ε 触底点 ep≈2189,R1 触底点 ep≈800,差距 1400 ep |
293
  | ![R2 Eval Success](assets/round2/r2_eval_success_rate.png) | P3(主瓶颈) | R2 长曲线全程振荡 52-74%,振幅 ±10%,与 P3 预测的 400-500ep 周期吻合 |
294
 
295
- > 已删除 R2 文档中无诊断对应的 `r2_eval_spl.png` 截图(R2 诊断未引用 SPL)。
296
 
297
  ### 下一步行动
298
 
@@ -389,7 +370,7 @@ ep=5800–6000: 62–76% ← 末段振荡
389
  原因:即使 buffer=80000(约 1000 局),在成功率 60–80% 的阶段,仍约有 20–40% 的失败局(200步)持续填入 buffer;成功样本的相对比例虽有改善,但绝对数量仍不足以彻底稳定策略。
390
  依据 Schaul et al. (2016):根治方案需使用 **Prioritized Experience Replay(PER)**,让高 TD-error 的成功样本被优先重复采样,而非依赖更大 buffer。
391
 
392
- > **P3 与 P6 关系澄清**:P3 诊断"buffer 过小导致振荡",P6 诊断"根治需改均匀采样策略",两者描述的是不同层面——P3 指出 buffer 扩容方向正确实测振荡周期延、低谷抬高,P6 指出扩容只能缓解而不能根治(均匀采样下成功样本始终处于少数)。两个诊断不矛盾,分别对应"短期工程修复"和"长期根治方案"
393
 
394
  #### P4 — target network 修复效果验证(有效)
395
 
@@ -423,20 +404,15 @@ ep=800 成功率恢复至 42%,ep=1000 回到 44%,ep=1050 跳升至 62%,之
423
  **理论根源**:Lin (1992) 指出 ER 的核心价值之一是保留稀有样本,但均匀采样无法主动偏向高价值样本。
424
  **解决方案**:Prioritized Experience Replay(Schaul et al. 2016)——赋予高 TD-error 样本更高采样概率,使成功样本被更频繁地学习,振荡可从根本上消除。
425
 
426
- ### TensorBoard 运行目录
427
-
428
- ```
429
- runs/Round3_double_buffer80k_target1500/
430
- runs/Round3_double_buffer80k_target1500_restart/ ← 重启前的短暂记录(ep<400)
431
- ```
432
-
433
- ### TensorBoard 曲线截图
434
 
435
- ![cmp_eval_success_rate_r2_vs_r3](assets/compare/cmp_eval_success_rate_r2_vs_r3.png)
436
- ![r3_eval_success_rate](assets/round3/r3_eval_success_rate.png)
 
 
 
437
 
438
- ![r3_eval_spl](assets/round3/r3_eval_spl.png)
439
- ![r3_backend_avg_q](assets/round3/r3_backend_avg_q.png)
440
 
441
  ### R3 总结与 R4 决策依据
442
 
@@ -481,27 +457,26 @@ buffer+target 组合将盲测峰值从 74% 提升至 **84%**,Holdout 从 64%
481
 
482
  ---
483
 
484
- #### 四、循环失败率的直接测量(R4 引入 4 通道的依据)
485
 
486
- R3 训练完成后,将 best_model 在 Web Demo 中实测推理(ε=0 纯贪心),观察到 agent 在部分地图中陷入两格间无限震荡——A→B→A→B 循环 200 步触底截断。此现象直接指向"状态层缺少访问历史 → 推理时 Q 函无法区分两格循环与两格前进",是 R4 引入 visited_map 第 4 通道的直接动机。**R4 行动计划中"探索循环抑制方案"一项的数据依据如下**
487
 
488
- | 分类 | R3 局数 | R4 局数 |
489
- |------|--------:|--------:|
490
- | 快速成功(≤30 步) | 75 | 78 |
491
- | 正常成功31-80 ) / 慢成功(81-200) | 0 / 0 | 0 / 0 |
492
- | 失败·截断(步数=200) | **25** | **22** |
493
- | 失败·近截断(150-199)/ 早夭(<150) | 0 / 0 | 0 / 0 |
494
- | 成功率 | 75% | 78% |
495
- | **失败局中截断占比** | **25/25 = 100%** | **22/22 = 100%** |
496
- | 失败局平均撞墙数 | 0.0 | 0.0 |
497
 
498
- *Holdout 100 局(seed+200042..+200141),R3 / R4 best_model 均为 double 算法。*
499
 
500
  **数据解读**:
501
 
502
  - **100% 截断 + 撞墙=0**:撞墙=0 排除"撞墙堵死"(撞墙会留下 hit_wall 计数),唯一合理解释是 agent 在自由格间反复震荡;10×10 迷宫最优路径仅 15-25 步,200 步远超合理上限。
503
  - **失败-成功 0/1 离散**:成功局集中在 ≤30 步,失败局集中在 200 步,无中间过渡;0% 近截断、0% 早夭,无"接近但错过"或"路径规划差但仍在前进"的中间情形。
504
- - **R3 → R4 变化**:2522 截断局(绝对 −3pp,相对 −12%;n=100 σ √(0.25·0.75/100) 4.3pp,3pp **不具统计显著性**),但**截断率 100% 这一失败模式结构未变**——4 通道减少循环地图数量循环机制本身仍是 R4 EVAL 期失败主因
505
 
506
  **R3 训练期 → EVAL 期的因果链**:训练期截断率 15.5%(含 5% ε 探索,部分跳出循环)→ EVAL 期截断率 25%(ε=0,循环被锁定)→ 100% 截断且撞墙=0 → 循环机制是 R3 失败主因 → R4 必须显式编码访问历史。
507
 
@@ -518,19 +493,19 @@ if eval_success_rate > best_eval_success_rate:
518
  save_model()
519
  ```
520
 
521
- **R4 配置**:在 R3 最优超参基础上4 种算法(vanilla / double / dueling / double_dueling各跑一次,使用新的保存策略
522
 
523
- | 超参 | | 说明 |
524
- |------|----|------|
525
- | `num_episodes` | 5000 | 适当缩短R3 曲线在 4000+ ep 已趋平稳) |
526
- | `epsilon_decay` | 0.9985 | 不变 |
527
- | `buffer_capacity` | 80000 | 不变 |
528
- | `target_update_freq` | 1500 | 不 |
529
- | **`revisit_penalty`** | **-1.0** | **新增:训练时重复访问格子施加递进惩罚,抑制循环路径** |
530
- | **checkpoint 保存策略** | **EVAL 成功率最优** | **本轮核心变更** |
531
 
532
  **预期**:R3 中 double 算法 EVAL 峰值达 84%,改保存策略后 Holdout 预期接近 80–84%(消除 10pp 保存时机损失,剩余 2–4pp 为评估集过拟合的正常偏差)。
533
 
 
 
534
  ---
535
 
536
  ## Round 4 — 系统性问题修复:Checkpoint 策略 + 训练信号质量
@@ -572,38 +547,18 @@ EVAL 集与 Holdout 集独立,用 EVAL 集挑 checkpoint 引入的偏差约 2
572
 
573
  #### P8 — 随机起终点缺乏连通性验证(信号污染)
574
 
575
- **代码现状**(修复前):
576
 
577
- `env.py``reset()` 在外部注入 `wall_map` 时明确跳过 BFS 验证(文档注释:"调用方须自行保证连通")。但 `train.py` 在训练循环和 EVAL 循环的随机起终点逻辑中,均从自由格中随机选取两点后**直接注入**,做连通性检验:
 
 
578
 
579
- ```python
580
- # 修复前(训练循环,约第460行)
581
- obs, _ = env.reset(options={
582
- "wall_map": wall_map,
583
- "start": inner[idx_a],
584
- "goal": inner[idx_b], # 可能与 start 不连通!
585
- })
586
- # 注释甚至写着"env 内 BFS 保证连通"——这是错误注释
587
- ```
588
-
589
- **影响量化**:
590
-
591
- obstacle_density=0.25 的 10×10 地图,内圈约 48 个自由格。随机选取两个自由格,不连通概率取决于地图的连通分量数。典型场景下,约 5–10% 的随机起终点对不可达。
592
-
593
- 这些无解任务的影响:
594
- - **训练侧**:无解局在 `max_steps=200` 内必然 `truncated`,贡献 200 步全负奖励(约 -201)进入 buffer。Q 网络在这些样本上学到"某些位置无论如何行动都是大负收益",引入系统性噪声。无解任务约占 5–10%,若每局约 80 步,无解局步数是正常局的 2.5 倍,在 buffer 中的样本权重被进一步放大。
595
- - **评估侧**:Holdout 的 100 张地图中,不连通任务必然失败,直接压低成功率分母。Holdout 成功率被系统性低估约 **5–10% × 不连通率 ≈ 0.25–1pp**(量级较小但真实存在)。
596
-
597
- **修复方案(commit `413b4eb`)**:
598
 
599
  ```python
600
- # 修复后:选完起终点后 BFS 验证,不通则重新采样
601
- from maze_env.generator import bfs_reachable as _bfs_reachable
602
-
603
  while not _bfs_reachable(wall_map, start_pos, goal_pos):
604
  idxs = rng.choice(len(inner), size=2, replace=False)
605
- start_pos = inner[idxs[0]]
606
- goal_pos = inner[idxs[1]]
607
  ```
608
 
609
  训练循环和 EVAL 循环均同步修复,同时删除错误注释。
@@ -612,11 +567,9 @@ while not _bfs_reachable(wall_map, start_pos, goal_pos):
612
 
613
  #### 推理时策略循环问题(新发现)
614
 
615
- **发现路径**:R3 训练完成后,将 best_model 在 Web Demo 实测推理(ε=0 纯贪心),观察到 agent 在部分地图中陷入两格间无限震荡——A→B→A→B 循环 200 步触底截断。此现象直接指向"状态层缺少访问历史 → 推理时 Q 函无法区分两格循环与两格前进",R4 引入 visited_map 第 4 通道的直接动机
616
-
617
- **EVAL 期步数分布(量化佐证)**:详见上文"四、循环失败率的直接测量"——R3 best_model 在 Holdout 100 局(ε=0 贪心)上的逐局步数显示 25/25=100% 失败局是步数=200 截断且撞墙=0.0,确证循环是 R3 EVAL 期失败的主因。训练期 vs EVAL 期的截断率差异(15.5% → 25%,见表 6.3)即 ε 探索在循环抑制上的边际贡献。
618
 
619
- **根因**:训练期 ε>0 随机探索在多数情况下帮助 agent 跳出局部循环,但**部分地图起终点组合使 ε 探索也不足以在 200 步内到达终点**——这部分训练局贡献的样本是"循环 200 步的负奖励轨迹",网络学到"某些区域走出去成本极高"但不知道主动规避重复访问。visited_map 第 4 通道把"是否访问过"显式编码到状态中,使网络可直接学习"重访成本"——从症状侧抑制循环(不是消除机制)。
620
 
621
  此问题是 R4 的第三个攻坚方向,见后续尝试记录(R4-A1 revisit_penalty 失败 + R4-A2 visited_map 成功)。
622
 
@@ -628,20 +581,15 @@ R4 共进行四次独立尝试(对照组 R4-A3 已完成),每次对比 R3
628
 
629
  **注意**:R3 使用 eval_every=50,R4 系列使用 eval_every=100,下方对比统一取 100 ep 间隔数据点。
630
 
631
- R3 每 100 ep 的 EVAL 成功率(取相邻 50ep 点均值,ep=300 起):
632
 
633
- ```
634
- ep= 300: 55% ep= 400: 8% ep= 500: 19% ep= 600: 16% ep= 700: 29% ← 早期 Q 值高估 crisis
635
- ep= 800: 41% ep= 900: 42% ep=1000: 53% ep=1100: 58% ep=1200: 65%
636
- ep=1300: 57% ep=1400: 63% ep=1500: 67% ep=1600: 65% ep=1700: 64%
637
- ep=1800: 66% ep=1900: 68% ep=2000: 64% ep=2100: 66% ep=2200: 70%
638
- ep=2300: 68% ep=2400: 70% ep=2500: 70% ep=2600: 72% ep=2700: 70%
639
- ep=2800: 72% ep=2900: 72% ep=3000: 72% ep=3100: 76% ep=3200: 74%
640
- ep=3300: 74% ep=3400: 76% ep=3500: 76% ep=3600: 72% ep=3700: 74%
641
- ep=3750: 84% ep=3800: 72% ep=3900: 74% ep=4000: 74% ep=4100: 69%
642
- ep=4200: 76% ep=4300: 76% ep=4400: 69% ep=4500: 65% ep=4600: 72%
643
- ep=4700: 71% ep=4800: 70% ep=4900: 66% ep=5000: 64%
644
- ```
645
 
646
  ---
647
 
@@ -664,7 +612,7 @@ ep=4700: 71% ep=4800: 70% ep=4900: 66% ep=5000: 64%
664
  | 900 | 28% | 0.263 | 42% | -14pp |
665
  | 1000 | 38% | 0.354 | 53% | **-15pp** |
666
 
667
- **终止判据**:ep=1000 时成功率 38%,持续低于 R3 同期(53%)15pp 以上,无收敛趋势。
668
 
669
  **失败根因:马尔可夫性违反(P9)**
670
 
@@ -672,15 +620,11 @@ Q-learning 的贝尔曼方程要求奖励函数 $r(s, a, s')$ 仅依赖当前转
672
 
673
  $$Q(s,a) = \mathbb{E}\left[r(s,a,s') + \gamma \max_{a'} Q(s',a')\right]$$
674
 
675
- `revisit_penalty` 使奖励依赖隐变量(本 episode 内的访问历史),即 $r(s,a,s') = r_{\text{base}} + f(\text{visit\_count}[s'])$,其中 $f$ 在每个 episode 内单调递增。相同的 $(s,a)$ 在不同时刻返回不同奖励,Q 函数在数学上无法收敛到唯一固定点。
676
 
677
- 更严重的是训练/推理分布不一致:
678
- - **训练时**:$r(s,a)$ 含访问历史惩罚项
679
- - **推理时**:$r(s,a)$ = 基础奖励(无惩罚)
680
 
681
- 网络拟合的是"含历史信息的"奖励函数,但推理时该信息不存在,导 Q 值系统性失准策略崩溃。这不是 Q 值高估问题(Double DQN 可修正),而目标函数本身测试分布下意义
682
-
683
- **与早期 Q 值高估 crisis(Q 值估计暂时性偏差)的本质区别**:crisis 是 Q 值在学习过程中的暂时性估计偏差,奖励函数形式在训练和推理时一致,Double DQN 可自修正;P9 是奖励函数结构在训练和推理时不一致(训练时含访问历史惩罚,推理时无),Q 函数目标在测试分布下无意义,不可修正。
684
 
685
  **结论**:**结构性失败,不可修补。** 奖励层的循环抑制方案在任何需要"有状态奖励"的场景下都会违反马尔可夫性。
686
 
@@ -703,22 +647,14 @@ $$Q(s,a) = \mathbb{E}\left[r(s,a,s') + \gamma \max_{a'} Q(s',a')\right]$$
703
 
704
  **checkpoint 保存**:此次仍为训练滚动奖励触发(EVAL 修复尚未合入)。
705
 
706
- **EVAL 数据(ep=300–5000,每 100 ep)**:
707
 
708
- ```
709
- ep= 300: 56% ep= 400: 32% ep= 500: 8% ep= 600: 14% ← Q值高估危机(ep=400–700)
710
- ep= 700: 28% ep= 800: 42% ep= 900: 50% ep=1000: 54% ← 自修正完成
711
- ep=1100: 60% ep=1200: 68% ep=1300: 68% ep=1400: 66%
712
- ep=1500: 70% ep=1600: 72% ep=1700: 72% ep=1800: 74%
713
- ep=1900: 74% ep=2000: 66% ep=2100: 60% ep=2200: 72%
714
- ep=2300: 72% ep=2400: 68% ep=2500: 76% ep=2600: 74%
715
- ep=2700: 78% ep=2800: 70% ep=2900: 74% ep=3000: 74%
716
- ep=3100: 78% ep=3200: 72% ep=3300: 76% ep=3400: 76%
717
- ep=3500: 74% ep=3600: 70% ep=3700: 76% ep=3800: 74%
718
- ep=3900: 76% ep=4000: 74% ep=4100: 66% ep=4200: 72%
719
- ep=4300: 76% ep=4400: 74% ep=4500: 70% ep=4600: **80%** ← 历史峰值
720
- ep=4700: 68% ep=4800: 70% ep=4900: 68% ep=5000: 70%
721
- ```
722
 
723
  **Holdout 结果**:
724
 
@@ -794,23 +730,13 @@ while not _bfs_reachable(wall_map, start_pos, goal_pos):
794
 
795
  训练循环和 EVAL 循环均同步修复。
796
 
797
- **EVAL 完整数据(每 100 ep)**:
798
 
799
- ```
800
- ep= 300: 54% ep= 400: 34% ep= 500: 10% ep= 600: 10% ← Q值高估危机
801
- ep= 700: 18% ep= 800: 26% ep= 900: 58% ep=1000: 62%
802
- ep=1100: 48% ep=1200: 56% ep=1300: 72% ★ ep=1400: 62%
803
- ep=1500: 76% ★ ep=1600: 80% ★ ep=1700: 76% ep=1800: 80%
804
- ep=1900: 76% ep=2000: 72% ep=2100: 68% ep=2200: 76%
805
- ep=2300: 78% ep=2400: 82% ★ ep=2500: 76% ep=2600: 76%
806
- ep=2700: 78% ep=2800: 78% ep=2900: 84% ★ ep=3000: 84%
807
- ep=3100: 86% ★ ep=3200: 80% ep=3300: 88% ★★ ep=3400: 84%
808
- ep=3500: 82% ep=3600: 84% ep=3700: 88% ep=3800: 86%
809
- ep=3900: 86% ep=4000: 86% ep=4100: 84% ep=4200: 84%
810
- ep=4300: 84% ep=4400: 80% ep=4500: 78% ep=4600: 78%
811
- ep=4700: 82% ep=4800: 82% ep=4900: 78% ep=5000: 82%
812
- ```
813
- ★ = EVAL SAVE 触发点,最高 88%(ep=3300/3700)
814
 
815
  **Holdout 结果**:
816
 
@@ -877,23 +803,6 @@ $$\text{无解任务率} \approx p_{\text{unreachable}} \approx 5\text{–}10\%$
877
 
878
  ---
879
 
880
- ### TensorBoard 运行目录
881
-
882
- ```
883
- runs/Round4_double_visited_map/ ← R4-A2 记录
884
- runs/Round4_ctrl_eval_ckpt/ ← R4-A3 记录(已完成,ep=5000)
885
- ```
886
-
887
- ### 所需截图
888
-
889
- - [x] `r4_eval_success_rate_all_algos.png`:R4 四算法 EVAL 成功率曲线(已生成)
890
- - [x] `r4_eval_spl_all_algos.png`:R4 四算法 SPL 曲线(已生成)
891
- - [x] `r4_dueling_full_curves.png`:最优算法完整训练曲线(已生成)
892
- - [x] `cmp_eval_success_rate_r1_to_r4_double.png`:R1→R4 超参演进纵向对比(已生成)
893
- - [ ] `r4_a1_eval_collapse.png`:R4-A1 的 EVAL 崩溃曲线(runs 目录已删,无法补充)
894
-
895
- ---
896
-
897
  ## Round 4(续)— 算法横向消融:Vanilla / Double / Dueling / Double-Dueling
898
 
899
  **日期**:2026-06-01
@@ -935,7 +844,7 @@ runs/Round4_ctrl_eval_ckpt/ ← R4-A3 记录(已完成,ep=5000
935
 
936
  #### 危机成因(共性)
937
 
938
- 四种算法在 ep≈400–700 区间均出现 EVAL 成功率骤降,根因为 **vanilla 目标 $\hat{Q} = r + \gamma \max_{a'} Q_{\theta^-}(s',a')$ 的 $\max$ 算子正偏差被 bootstrapping 反复放大**:R3 起引入的 buffer×4 + target×3 改动(延长旧策略样本滞留、放大 TD 目标漂移)与 R4 引入的 visited_map 第4通道(输入分布变化)使早期 $Q_{\theta^-}$ 系统性高估,TD 目标通过自举迭代形成正反馈回路,AvgQ 飙升,EVAL 骤降。同一机制在不同算法上表现程度不同,根源是它们对 max 算子的修正能力不同。
939
 
940
  #### 四算法危机程度对比
941
 
@@ -969,10 +878,11 @@ $$\hat{Q}_{\text{double}} = r + \gamma Q_{\theta^-}(s', \arg\max_{a'} Q_\theta(s
969
 
970
  **观察**:
971
 
972
- - **危机排序**(底越深越严重):dueling 4% ≪ vanilla 6% < double 10% < double_dueling 20%。Double DQN 抗高估机制使 double_dueling 危机最浅
973
  - **恢复速度**:ep=700 时 double_dueling(54%)领先 dueling(6%)48pp,是 Double DQN 解耦机制最直接定量证据
974
- - **峰值时机**:double_dueling(ep=4200)比 vanilla(ep=4800)早 600 ep,体现双重改进加速收敛;vanilla 与 dueling 峰值均靠后,说明单一改进在本任务规模下需要更多训练时间
975
- - double(A3) 完整曲线见 [R4-A3 节](#r4-a3--r3-超参--eval-checkpoint--bfs-连通性验证--visited_map已完成)
 
976
 
977
  ---
978
 
@@ -1004,16 +914,11 @@ Wang et al. (2016) 指出,Dueling 架构将 Q 函数分解为状态价值函
1004
 
1005
  $$Q(s,a) = V(s) + A(s,a) - \frac{1}{|\mathcal{A}|}\sum_{a'} A(s',a')$$
1006
 
1007
- 其核心收益在于**共享状态价值估计**。当不同动作的价值差异很小时(例如在走廊���,"前进"与"原地打转"以外的三个方向均撞墙,所有可行动作效果相近),Dueling 网络仍能通过 V(s) 流精确评估当前状态的内在价值而无需对动作单独精确估计 $Q(s,a)$。
1008
-
1009
- **本任务的适配性**:
1010
 
1011
- 随机起终点 10×10 迷宫中大量状态满足"多数动作等效"的条件:
1012
- 1. **死胡同状态**:3个方向均为墙,唯一可行动作明确,A(s,a) 的估计误差影响微小,主要价值来自 V(s) 对该位置是否接近终点的评估
1013
- 2. **走廊状态**:两侧为墙,V(s) 携带的路径价值信息(曼哈顿距离+障碍分布)比单动作的 A(s,a) 更稳定
1014
- 3. **已访问格重访**:ch3=visited_map 编码历史,当 V(s) 准确反映"当前格已多次访问、价值已被充分学习"的信息时,Dueling 比 vanilla 更高效地利用了状态价值信号
1015
 
1016
- 这一分析与实测结果一致:**dueling 的 EVAL→Holdout gap 仅 6pp(最小)**,说明 Dueling 架构泛化性能最稳定,不仅"学得好"(EVAL 峰值)也"记得稳"(Holdout 不退化)
1017
 
1018
  #### Double DQN 在危机期的修正机制
1019
 
@@ -1028,17 +933,13 @@ $$Q(s,a) = V(s) + A(s,a) - \frac{1}{|\mathcal{A}|}\sum_{a'} A(s',a')$$
1028
 
1029
  **理论预期**:两项改进正交(一改架构,一改目标计算),叠加应有协同收益。
1030
 
1031
- **实测结果**:double_dueling Holdout=81%,位居第二,但**低于纯 dueling(84%)3pp**
1032
-
1033
- 这一"叠加不如单独"的结果有以下解释:
1034
-
1035
- 1. **训练时间对称性破坏**:double_dueling 在 ep=4200 已达 EVAL 峰值,而 dueling 在 ep=4900 仍在上升。double_dueling 较早"过峰",说明 Double DQN 使收敛更快(对应危机恢复更快),但也可能导致 Q 值在峰值后更快出现低估偏差(over-correction),而 dueling 因 vanilla 目标反而保留了轻微的高估"缓冲",维持了更长的高性能区间。
1036
 
1037
- 2. **末段稳定性差异**:EVAL→Holdout gap 方面,double_dueling(-9pp)略大于 dueling(-6pp),说明 double_dueling 的 EVAL 峰值对应的策略鲁棒性稍差,在 Holdout 新地图上的泛化略逊于 dueling
1038
 
1039
- 3. **样本量说明**:Holdout n=100,置信区间约 ±5pp(二项分布 95% CI)。3pp 差距在统计边界但方向一致。
1040
 
1041
- **结论**:对于本任务(随机起终点 10×10 迷宫,5000 ep 训练),Dueling 架构的状态价值分解与本任务特性高度适配,单独带来的泛化增益(+6pp vs double)大于 Double DQN 单独带来的增益(+3pp vs vanilla);两者组合在终态 Holdout 上不优于纯 Dueling,原因是 Double DQN 的加速效应改变了训练动态,使峰值出现更早但稳定区间更短。
1042
 
1043
  ---
1044
 
@@ -1053,16 +954,35 @@ $$Q(s,a) = V(s) + A(s,a) - \frac{1}{|\mathcal{A}|}\sum_{a'} A(s',a')$$
1053
 
1054
  **vanilla 的 19pp Gap 解读**:
1055
 
1056
- vanilla 是本组唯一一个 EVAL 峰值(94%)远高于其他算法但 Holdout 最低(75%)的算法,Gap 高达 19pp,是其他算法的 2–3 倍。两个可能原因:
1057
 
1058
- 1. **EVAL 集偶然偏差**:EVAL 集在训练开始前由 `seed+100000` 派生固定生成,整个训练期间恒定(非每次随机),因此不存在"恰好碰到容易地图子集"的随机噪声解释。94% 的 EVAL 峰值是 vanilla 网络在这批固定的 50 张地图上确实达到的真实性能,但这批地图对 vanilla 的特定决策边界恰好较友好——属于固定 EVAL 集对特定算法的结构性偏差,而非随机采样噪声。EVAL→Holdout 的 19pp Gap 主要反映的是 vanilla 对这 50 张特定地图的过拟合程度。
1059
- 2. **训练晚期策略退化**:vanilla 无 V/A 分解,Q(s,a) 需逐一精确估计,训练末段(ep=4500+)的 buffer 回放可能已不能支持如此精细的 Q 函数持续更新,导致 Holdout 性能在实际泛化大幅缩水
1060
 
1061
  **dueling 的 6pp Gap 解读**:
1062
 
1063
- Dueling 网络的真正泛化优势来自**参数共享机制**:V(s) 流被所有动作共享每次梯度更新获得来自所有动作的梯度信号,更新频率是 A(s,a) 流的 $|\mathcal{A}|$ 倍本任务 4 倍),学习更充分、估计更稳定A(s,a) 流仅提供局部动作微调。这一结构性优势使 dueling 在未见过的 Holdout 地图上泛化最稳定——V(s) 学习的"靠近目标的状态价值更高"规律在任意地图布局下均成立,Gap 小(6pp)
1064
 
1065
- > **注意**:"不依赖特定障碍布局"这一属性对 Vanilla DQN 同样成立(Q(s,a) 同样通过相同的卷积特征提取器训练),因此不能用来解释 Dueling 的泛化优势。核心差异在于参数更新频率和梯度信号稳定性。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1066
 
1067
  ---
1068
 
@@ -1080,21 +1000,19 @@ Dueling 网络的真正泛化优势来自**参数共享机制**:V(s) 流被所
1080
  | R4-A3 (double) | EVAL checkpoint + BFS + visited_map | 78% | EVAL→Holdout gap 10pp 持续(算法限制) |
1081
  | **R4 dueling** | 同 A3 超参 + Dueling 架构 | **84%** | **EVAL→Holdout gap 仅 6pp(最优泛化)** |
1082
  | R4 double_dueling | 同上 + Double DQN | 81% | 收敛快但末段稳定性略低 |
1083
- | R4 vanilla | 同上,无增强 | 75% | EVAL 峰值虚高(94%,真实泛化最弱 |
1084
 
1085
  **最终结论(五点)**:
1086
 
1087
- 1. **Dueling 架构是本任务的最优选择**:V(s)/A(s,a) 分解使网络能将"位置价值""动作优势"解耦学习,与随机起终点迷宫导航任务的任务结构(大量多动作等效状态)高度吻合,最终 Holdout 84%(+10pp vs R3),EVAL→Holdout gap 6pp(最小,泛化最稳)。其中 R3→R4(double) 的 +4pp 是 P7+P8+visited_map 三项叠加效果(见结论4),R4(double)→R4(dueling) 的 +6pp 是 Dueling 架构的独立贡献(控制其他变量不变)。
1088
-
1089
- 2. **Double DQN 主要收益在训练过程,非最终结果**:危机期加速恢复(ep=700 领先 dueling 48pp)和早期收敛加速是真实可量化的收益;但在 5000 ep 充分训练后,与纯 dueling 的最终 Holdout 差距(81% vs 84%)表明 Double DQN 的抗高估机制在本任务规模下已不是瓶颈。
1090
 
1091
- 3. **EVAL→Holdout gap 是算法质量的独立指标**:Gap 越小说明策略对未见地图的鲁棒性越高。dueling gap 6pp、double_dueling 9pp、double 10pp、vanilla 19pp,与各算法架构泛化能力排序一致,可作为独立于 Holdout 成功率的泛化质量指标
1092
 
1093
- 4. **P7(EVAL-based checkpoint)高性价比修复,但单项贡献未严格消融**:R3→R4(double) +4pp P7+P8+visited_map 三项叠加效果未做单变量消融无法精确归因。R4-A2(仅 visited_map P7)Holdout=75% 仅 +1pp(不显著),间接说明 P7 是三项中单项收益最大者,但严格证明需补做 3通道+EVAL checkpoint+BFS 对照组
1094
 
1095
- 5. **P9马尔可夫性违反)是硬约束**:任何将 episode 历史信息置于奖励函数中的循环抑制方案revisit_penalty 均导致 Q 函数目标无意义,正确解决方案唯有状态编码visited_map)。
1096
 
1097
- ---
1098
 
1099
  ---
1100
 
 
15
  | Round 2 | 随机起终点 | `ep=6000` + `decay=0.9985` | 64.0% | 0.633 | 74% | P1/P2 修复,新发现 buffer 过小(P3)和 target 同步过频(P4)|
16
  | Round 3 | 随机起终点 | `buffer=80k` + `target=1500` | **74.0%** | **0.735** | **84%** | 峰值突破 80%;Holdout 低于峰值 10pp,根因为保存策略 |
17
  | Round 4 | 随机起终点 | EVAL-based checkpoint + BFS 连通性验证;探索 revisit_penalty(失败)和 visited_map 4通道 | **78.0%**(A3,double 算法) | **0.773** | **88%** | P7(checkpoint时序)+P8(无解任务)系统性修复;P9(马尔可夫违反)新发现;A3为三项变量叠加,非单因素对照 |
18
+ | Round 4(续)| 随机起终点 | R4-A3 超参固定,四算法横向消融(唯一变量=算法)| **84.0%**(dueling,最优) | **0.817** | **94%**(vanilla) | dueling EVAL→Holdout gap=6pp 最优泛化;double_dueling 81%;vanilla 75%(19pp gap,仅在固定 50 张 EVAL 集上成立);Double DQN 危机恢复快但终态不及纯 dueling |
19
 
20
  **关键结论链**:随机起终点使状态空间扩大约 40×,需要更长训练(R2)→ 更大 buffer 保留稀疏成功样本(R3)→ 修复 checkpoint 时序偏差 + 连通性验证 + visited_map 状态编码(R4)→ Dueling 架构的 V/A 分解与多动作等效迷宫导航任务高度适配(R4 算法消融)。奖励层循环抑制违反马尔可夫性(P9);状态层编码(visited_map)理论正确;最优配置(dueling + EVAL checkpoint + BFS + visited_map)最终将 Holdout 从 74%(R3)提升至 **84%**(+10pp)。
21
 
 
127
  随机起终点导致 Q 值估计方差更高,频繁同步加剧 bootstrapping instability。
128
  依据:Mnih et al. (2015) 原版更新周期 10000 步,DQN loss $\mathcal{L}(\theta) = \mathbb{E}[(r + \gamma \max_{a'} Q_{\theta^-}(s',a') - Q_\theta(s,a))^2]$ 中 $\theta^-$ 须提供固定回归目标,同步过频等价于用移动靶做监督学习。
129
 
 
 
 
 
 
 
 
 
 
130
  ### TensorBoard 曲线截图(与 P1–P4 诊断一一对应)
131
 
132
  | 截图 | 论证的诊断点 | 解读 |
 
135
  | ![Epsilon](assets/round1/r1_frontend_epsilon.png) | P2 | ε 在 ep≈800 触底 0.05,P2 探索过早终止的直接证据 |
136
  | ![Loss](assets/round1/r1_backend_loss.png) | P4 | Loss 高频震荡,target 同步过频的间接证据 |
137
 
138
+ > P3 R1 中为预测,验证在 R2 截图(见下)
139
 
140
  ### 结论与下一步行动
141
 
142
  **已确认问题**(按优先级):
143
+ 1. **P1+P2(高优先级)**:训练量不足 + 探索过早终止是最直接的瓶颈
144
+ 2. **P3(中优先级)**:buffer=20000 约 250 局轮换,预测 R2 将出现 400–500 ep 周期振荡
145
  3. **P4(中优先级)**:target 同步 272 次/轮,高 Q 方差场景下移动靶效应显著
146
 
147
+ **下一步行动**:R1 当时能直接决定的修复只有 P1+P2成对修改`num_episodes` `epsilon_decay`)。P3+P4 需在 R2 长曲线上验证后才能量化修复(buffer 扩到多少、target_update_freq 调到多少);R4 的修复方向(EVAL checkpoint、BFS、visited_map)均需 R2/R3 跑后才有依,不在 R1 阶段可推断范围
 
 
 
 
148
 
149
  ---
150
 
 
265
 
266
  ---
267
 
 
 
 
 
 
 
268
  ### TensorBoard 曲线截图(与 P1–P4 诊断一一对应)
269
 
270
  | 截图 | 论证的诊断点 | 解读 |
 
273
  | ![R1 vs R2 Epsilon](assets/compare/cmp_frontend_epsilon_r1_vs_r2.png) | P2 验收 | R2 ε 触底点 ep≈2189,R1 触底点 ep≈800,差距 1400 ep |
274
  | ![R2 Eval Success](assets/round2/r2_eval_success_rate.png) | P3(主瓶颈) | R2 长曲线全程振荡 52-74%,振幅 ±10%,与 P3 预测的 400-500ep 周期吻合 |
275
 
276
+ > P4(target 同步)截图在 R3 给出(`r3_backend_avg_q.png` 显示 Q 值稳定性提升)。
277
 
278
  ### 下一步行动
279
 
 
370
  原因:即使 buffer=80000(约 1000 局),在成功率 60–80% 的阶段,仍约有 20–40% 的失败局(200步)持续填入 buffer;成功样本的相对比例虽有改善,但绝对数量仍不足以彻底稳定策略。
371
  依据 Schaul et al. (2016):根治方案需使用 **Prioritized Experience Replay(PER)**,让高 TD-error 的成功样本被优先重复采样,而非依赖更大 buffer。
372
 
373
+ > P3 与 P6 关系:P3 "扩容缓解"(短效工程修复),P6 "采样策略根因"(长效方案)。两不矛盾,对应不同层面
374
 
375
  #### P4 — target network 修复效果验证(有效)
376
 
 
404
  **理论根源**:Lin (1992) 指出 ER 的核心价值之一是保留稀有样本,但均匀采样无法主动偏向高价值样本。
405
  **解决方案**:Prioritized Experience Replay(Schaul et al. 2016)——赋予高 TD-error 样本更高采样概率,使成功样本被更频繁地学习,振荡可从根本上消除。
406
 
407
+ ### TensorBoard 曲线截图(与 P3–P6 诊断一一对应)
 
 
 
 
 
 
 
408
 
409
+ | 截图 | 论证的诊断点 | 解读 |
410
+ |------|------------|------|
411
+ | ![R2 vs R3 Eval Success](assets/compare/cmp_eval_success_rate_r2_vs_r3.png) | P3 验证 | 振荡周期从 R2 的 400-500 ep 延长至 R3 的 700-900 ep(约 1.5-2 倍),低谷从 52% 抬至 56%,符合 buffer×4 预测 |
412
+ | ![R3 Eval Success](assets/round3/r3_eval_success_rate.png) | P3 验证 + P6 | R3 振荡周期延长但幅度未减(±14pp),指向 P6(均匀采样本身是周期性遗忘的根因) |
413
+ | ![R3 AvgQ](assets/round3/r3_backend_avg_q.png) | P4 验证 | R3 AvgQ 后期稳定在 35-60 区间,波动范围比 R2(35-70)收窄,target 更新频率降低有效 |
414
 
415
+ > P5(早期 Q 值高估危机)以 `r3_eval_success_rate.png` 中 ep=400-650 骤降区域作为佐证,无独立截图。SPL 曲线(`r3_eval_spl.png`)未引用进诊断,已删除。
 
416
 
417
  ### R3 总结与 R4 决策依据
418
 
 
457
 
458
  ---
459
 
460
+ #### 四、R3 失败模式直接测量(提供 R4 引入 4 通道的数据依据)
461
 
462
+ R3 训练完成后,将 best_model 在 Web Demo 中实测推理(ε=0 纯贪心),观察到 agent 在部分地图中陷入两格间无限震荡——A→B→A→B 循环 200 步触底截断。逐局步测量如下:
463
 
464
+ | 分类 | R3 局数 |
465
+ |------|--------:|
466
+ | 快速成功(≤30 步) | 75 |
467
+ | 失败·截断(步数=200) | **25** |
468
+ | 其他中间步数失败/慢成功) | 0 |
469
+ | 成功率 | 75% |
470
+ | **失败局中截断占比** | **25/25 = 100%** |
471
+ | 失败局平均撞墙数 | 0.0 |
 
472
 
473
+ *Holdout 100 局(seed+200042..+200141),R3 best_modeldouble 算法。*
474
 
475
  **数据解读**:
476
 
477
  - **100% 截断 + 撞墙=0**:撞墙=0 排除"撞墙堵死"(撞墙会留下 hit_wall 计数),唯一合理解释是 agent 在自由格间反复震荡;10×10 迷宫最优路径仅 15-25 步,200 步远超合理上限。
478
  - **失败-成功 0/1 离散**:成功局集中在 ≤30 步,失败局集中在 200 步,无中间过渡;0% 近截断、0% 早夭,无"接近但错过"或"路径规划差但仍在前进"的中间情形。
479
+ - **直接指向训练侧缺陷**:状态层缺少访问历史推理时 Q 函数无法区分两格循环与两格前进 修复方向 = 把访问历史编码进状态(visited_map 4 通道而非在奖励层加惩罚(会破坏马尔可夫性,详见 P9)
480
 
481
  **R3 训练期 → EVAL 期的因果链**:训练期截断率 15.5%(含 5% ε 探索,部分跳出循环)→ EVAL 期截断率 25%(ε=0,循环被锁定)→ 100% 截断且撞墙=0 → 循环机制是 R3 失败主因 → R4 必须显式编码访问历史。
482
 
 
493
  save_model()
494
  ```
495
 
496
+ **R4 行动计划**R3 收尾时的初规划按"问题驱动"组织):
497
 
498
+ | 变更项 | 内容 | 对应 R3 遗留问题 |
499
+ |--------|------|----------------|
500
+ | **EVAL-based checkpoint** | 每次评估若成功率创新高则保存 | 修复 P710pp 时序错位) |
501
+ | **BFS 连通性验证** | `reset()` 内嵌 BFS,无解迷宫重采样 | 修复 P8(训练信号被无解任务污染) |
502
+ | **visited_map 第 4 通道** | 状态层编码访问历史 | 修复循环失败(P5 根因候选,需消融验证) |
503
+ | 备注:revisit_penalty | 计划作为循环抑制的另一候选方案,**与 visited_map 并行消融** | 不确定状态层 vs 奖励层哪个有效 |
 
 
504
 
505
  **预期**:R3 中 double 算法 EVAL 峰值达 84%,改保存策略后 Holdout 预期接近 80–84%(消除 10pp 保存时机损失,剩余 2–4pp 为评估集过拟合的正常偏差)。
506
 
507
+ **关于"R4 续 / 算法横评阶段"**:R4 完成上述三项叠加后,确认 78% 是该算法(double)的上限;为判断"R4 还能不能继续往前推 6pp" 才有了"R4 续"——固定 R4 已验证有效的超参组合(buffer=80k、target=1500、shaping=0.5、visited_map 4通道、EVAL checkpoint、BFS),4 种算法各跑一次。这是"消融决定上限 → 用剩余 6pp 空间横评算法"的两步走,**不是 R3 结束后 R4 一开始就规划的内容**。
508
+
509
  ---
510
 
511
  ## Round 4 — 系统性问题修复:Checkpoint 策略 + 训练信号质量
 
547
 
548
  #### P8 — 随机起终点缺乏连通性验证(信号污染)
549
 
550
+ **代码现状**(修复前):`train.py` 在训练循环和 EVAL 循环的随机起终点逻辑中,从自由格中随机选取两点后**直接注入** `env.reset()`,不做连通性检验——原代码注释甚至误称"env 内 BFS 保证连通"。
551
 
552
+ **影响量化**:obstacle_density=0.2510×10 地图,约 5–10% 的随机起终点可达。
553
+ - **训练侧**:无解局在 `max_steps=200` 内必然 truncated,贡献 200 步全负奖励进入 buffer。无解局步数是正常局 2.5 倍,在 buffer 中样本权重被放大
554
+ - **评估侧**:Holdout 不连通任务必然失败,成功率被系统性低估约 **0.25–1pp**
555
 
556
+ **修复方案(commit `413b4eb`)**:选完起终点后 BFS 验证,不通则重新采样:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
557
 
558
  ```python
 
 
 
559
  while not _bfs_reachable(wall_map, start_pos, goal_pos):
560
  idxs = rng.choice(len(inner), size=2, replace=False)
561
+ start_pos, goal_pos = inner[idxs[0]], inner[idxs[1]]
 
562
  ```
563
 
564
  训练循环和 EVAL 循环均同步修复,同时删除错误注释。
 
567
 
568
  #### 推理时策略循环问题(新发现)
569
 
570
+ **发现路径与量化佐证**:R3 best_model 在 Web Demo 实测推理(ε=0 纯贪心)陷入两格震荡A→B→A→B 循环 200 步触底截断逐局步数详见上文"四、R3 失败模式直接测量"——100% 失败局为步=200 截断且撞墙=0.0,确证循环是 R3 EVAL 期失败主因
 
 
571
 
572
+ **根因**:训练期 ε>0 探索在多数情况下帮助跳出局部循环,但**部分地图起终点组合使 ε 探索也不足以在 200 步内到达终点**——这训练局贡献"循环 200 步的负奖励轨迹",网络学到"某些区域走出去成本极高"但不知道主动规避重复访问。visited_map 第 4 通道把"是否访问过"显式编码到状态中,使网络可直接学习"重访成本"——从症状侧抑制循环(不是消除机制)。
573
 
574
  此问题是 R4 的第三个攻坚方向,见后续尝试记录(R4-A1 revisit_penalty 失败 + R4-A2 visited_map 成功)。
575
 
 
581
 
582
  **注意**:R3 使用 eval_every=50,R4 系列使用 eval_every=100,下方对比统一取 100 ep 间隔数据点。
583
 
584
+ R3 每 100 ep 的 EVAL 成功率概要(取相邻 50ep 点均值,ep=300 起):
585
 
586
+ | 阶段 | ep 区间 | 成功率 | 备注 |
587
+ |------|---------|:------:|------|
588
+ | Q 值高估危机 | 400–700 | 8–29% | 最低 8%ep=400) |
589
+ | 自修正完成 | 800–2000 | 41–72% | 逐步爬升 |
590
+ | 高位平台 | 2000–3700 | 64–76% | 振荡区间 |
591
+ | **历史峰值** | 3750 | **84%** | R3 全程最高点 |
592
+ | 末段 | 3800–5000 | 64–76% | 缓慢回落 |
 
 
 
 
 
593
 
594
  ---
595
 
 
612
  | 900 | 28% | 0.263 | 42% | -14pp |
613
  | 1000 | 38% | 0.354 | 53% | **-15pp** |
614
 
615
+ **终止判据**:ep=1000 时成功率 38%,持续低于 R3 同期 15pp 以上,无收敛趋势。
616
 
617
  **失败根因:马尔可夫性违反(P9)**
618
 
 
620
 
621
  $$Q(s,a) = \mathbb{E}\left[r(s,a,s') + \gamma \max_{a'} Q(s',a')\right]$$
622
 
623
+ `revisit_penalty` 使奖励依赖隐变量(本 episode 内的访问历史),即 $r(s,a,s') = r_{\mathrm{base}} + f(\mathrm{visit\_count}[s'])$,其中 $f$ 在每个 episode 内单调递增。相同的 $(s,a)$ 在不同时刻返回不同奖励,Q 函数在数学上无法收敛到唯一固定点。
624
 
625
+ 更严重的是训练/推理分布不一致:训练时 $r(s,a)$ 含访问历史惩罚,推理时 $r(s,a)$ = 基础奖励。网络拟合的是"含历史信息的"奖励函数,但推理时该信息不存在,Q 值系统性失准。这不是 Q 值高估问题(Double DQN 可修正),而是目标函数本身在测试分布下无意义。
 
 
626
 
627
+ **与早期 Q 值高估 crisis 本质区别**:crisis 暂时性估计偏差(奖励函数形式在训练/推理时致,Double DQN 可修正);P9 奖励函数结构训练/推理时不一致(训练时含访问历史惩罚,推理时),不可修正
 
 
628
 
629
  **结论**:**结构性失败,不可修补。** 奖励层的循环抑制方案在任何需要"有状态奖励"的场景下都会违反马尔可夫性。
630
 
 
647
 
648
  **checkpoint 保存**:此次仍为训练滚动奖励触发(EVAL 修复尚未合入)。
649
 
650
+ **EVAL 数据概要(ep=300–5000,每 100 ep)**:
651
 
652
+ | 阶段 | ep 区间 | 成功率 | 备注 |
653
+ |------|---------|:------:|------|
654
+ | Q 值高估危机 | 400–700 | 8–32% | AvgQ 峰值 57+ |
655
+ | 自修正完成 | 800–1500 | 42–68% | Double DQN 在 ~400 ep 内自修正 |
656
+ | 中期平台 | 1500–3000 | 60–78% | 收敛稳定 |
657
+ | 末段振荡 | 3000–5000 | 66–80% | 峰值 **80%ep=4600)** |
 
 
 
 
 
 
 
 
658
 
659
  **Holdout 结果**:
660
 
 
730
 
731
  训练循环和 EVAL 循环均同步修复。
732
 
733
+ **EVAL 数据概要(每 100 ep)**:
734
 
735
+ | 阶段 | ep 区间 | 成功率 | 备注 |
736
+ |------|---------|:------:|------|
737
+ | Q 值高估危机 | 400–800 | 10–34% | EVAL SAVE 首次保存 ep=900(58% |
738
+ | 早中期爬升 | 900–2000 | 48–80% | 5 EVAL SAVE 触发 |
739
+ | 末段高位 | 2000–5000 | 68–88% | 峰值 **88%ep=3300/3700)** |
 
 
 
 
 
 
 
 
 
 
740
 
741
  **Holdout 结果**:
742
 
 
803
 
804
  ---
805
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
806
  ## Round 4(续)— 算法横向消融:Vanilla / Double / Dueling / Double-Dueling
807
 
808
  **日期**:2026-06-01
 
844
 
845
  #### 危机成因(共性)
846
 
847
+ 四种算法在 ep≈400–700 区间均出现 EVAL 骤降,根因为 **vanilla 目标 $\hat{Q} = r + \gamma \max_{a'} Q_{\theta^-}(s',a')$ 的 $\max$ 算子正偏差被 bootstrapping 反复放大**:R3 buffer×4 + target×3 改动(延长旧策略样本滞留、放大 TD 漂移)与 R4 visited_map 第4通道(输入分布变化)使早期 $Q_{\theta^-}$ 系统性高估,TD 目标通过自举形成正反馈回路,AvgQ 飙升,EVAL 骤降。同一机制在不同算法上表现程度不同,根源是它们对 max 算子的修正能力不同。
848
 
849
  #### 四算法危机程度对比
850
 
 
878
 
879
  **观察**:
880
 
881
+ - **危机深度排序**(底越深越严重):dueling 4% ≪ vanilla 6% < double 10% < double_dueling 20%。Double DQN 抗高估机制使 double_dueling 危机最浅
882
  - **恢复速度**:ep=700 时 double_dueling(54%)领先 dueling(6%)48pp,是 Double DQN 解耦机制最直接定量证据
883
+ - **峰值时机**:double_dueling(ep=4200)比 vanilla(ep=4800)早 600 ep,体现双重改进加速收敛
884
+
885
+ > double(A3) 完整曲线见 [R4-A3 节](#r4-a3--r3-超参--eval-checkpoint--bfs-连通性验证--visited_map已完成)
886
 
887
  ---
888
 
 
914
 
915
  $$Q(s,a) = V(s) + A(s,a) - \frac{1}{|\mathcal{A}|}\sum_{a'} A(s',a')$$
916
 
917
+ 其核心收益在于**共享状态价值估计**V(s) 流被所有动作共享,每次梯度更新获得所有动作的梯度信号(更新频率是 A(s,a) 流的 $|\mathcal{A}|$ 倍,本任务 4 倍),估计更稳定
 
 
918
 
919
+ 随机起终点 10×10 迷宫中存在大量"多数动作等效"的状态(死胡同、走廊段、ch3 标记的已访问格),V(s) 携带的路径价值信息(曼哈顿距离+障碍分布+访问历史)比单动作的 A(s,a) 更稳定。
 
 
 
920
 
921
+ 这一分析与实测结果一致:**dueling 的 EVAL→Holdout gap 仅 6pp(最小)**,Dueling 架构泛化性能最稳定。
922
 
923
  #### Double DQN 在危机期的修正机制
924
 
 
933
 
934
  **理论预期**:两项改进正交(一改架构,一改目标计算),叠加应有协同收益。
935
 
936
+ **实测结果**:double_dueling Holdout=81%,低于纯 dueling(84%)3pp。
 
 
 
 
937
 
938
+ 可能解释:double_dueling 在 ep=4200 已达 EVAL 峰值,dueling 在 ep=4900 仍在上升。Double DQN 加速收敛使 double_dueling 较早"过峰",而 dueling 因 vanilla 目标保留了轻微高估"缓冲",维持了更长的高性能区间。末段稳定性EVAL→Holdout gap方面,double_dueling(-9pp)略大于 dueling(-6pp)也佐证此点
939
 
940
+ > :Holdout n=100,CI≈±5pp3pp 差距在统计边界但方向一致。
941
 
942
+ **结论**:Dueling 单独带来的泛化增益(+6pp vs double)大于 Double DQN 单独带来的增益(+3pp vs vanilla);两者组合在终态 Holdout 上不优于纯 Dueling,原因是 Double DQN 的加速效应改变了训练动态,使峰值出现更早但稳定区间更短。
943
 
944
  ---
945
 
 
954
 
955
  **vanilla 的 19pp Gap 解读**:
956
 
957
+ vanilla 是本组唯一 EVAL 峰值(94%)远高于其他算法但 Holdout 最低(75%)的算法,Gap 高达 19pp,是其他算法的 2–3 倍。两个可能原因:
958
 
959
+ 1. **EVAL 集结构性偏差**:EVAL 集由 `seed+100000` 派生固定生成(50 张全程恒定),94% 是 vanilla 在这批地图上的真实性能,但这批地图对 vanilla 的特定决策边界恰好较友好——属于固定 EVAL 集对特定算法的结构性偏差
960
+ 2. **训练晚期策略退化**:vanilla 无 V/A 分解,Q(s,a) 需逐一精确估计,训练末段(ep=4500+)的 buffer 回放可能已不能支持持续更新,导致 Holdout 泛化大幅缩水
961
 
962
  **dueling 的 6pp Gap 解读**:
963
 
964
+ Dueling 的真正泛化优势在 V(s) 流的**参数共享机制**(上节已述),每次梯度更新 V(s) 获得所有动作的梯度信号(4 倍更新频率),学习更充分。V(s) 学习的"靠近目标的状态价值更高"这一规律不依赖特定障碍布局,在任意地图均成立,泛化稳定
965
 
966
+ ---
967
+
968
+ ### 循环失败率 R3 / R4 对照(验证 4 通道的实际效果)
969
+
970
+ R3 节已记录"循环是 R3 失败主因"的数据(25/25 失败局为步数=200 截断且撞墙=0)。R4 训练完成后用相同方法(Holdout 100 局,ε=0 推理)回访测量:
971
+
972
+ | 分类 | R3 (double, 3通道) | R4 (double, 4通道) |
973
+ |------|-------------------:|-------------------:|
974
+ | 快速成功(≤30 步) | 75 | 78 |
975
+ | 失败·截断(步数=200) | **25** | **22** |
976
+ | 其他(中间步数失败/慢成功) | 0 | 0 |
977
+ | 成功率 | 75% | 78% |
978
+ | **失败局中截断占比** | **100%** | **100%** |
979
+ | 失败局平均撞墙数 | 0.0 | 0.0 |
980
+
981
+ **结论**:
982
+ - 截断数 25 → 22(−3pp,n=100 下 σ≈4.3pp,**不具统计显著性**)
983
+ - **但截断率 100% 这一失败模式结构未变**——4 通道减少了陷入循环的地图数量,循环机制本身仍是 R4 失败主因
984
+ - R3 → R4 成功率 +3pp 全部来自"减少了循环地图数",**而非消除了循环机制**
985
+ - 因此 Web Demo 仍需 anti-loop 兜底——网络能避开大部分循环地图,但对剩余的循环地图仍无能为力
986
 
987
  ---
988
 
 
1000
  | R4-A3 (double) | EVAL checkpoint + BFS + visited_map | 78% | EVAL→Holdout gap 10pp 持续(算法限制) |
1001
  | **R4 dueling** | 同 A3 超参 + Dueling 架构 | **84%** | **EVAL→Holdout gap 仅 6pp(最优泛化)** |
1002
  | R4 double_dueling | 同上 + Double DQN | 81% | 收敛快但末段稳定性略低 |
1003
+ | R4 vanilla | 同上,无增强 | 75% | 94% 仅在固定 50 张 EVAL 集上成立,真实泛化最弱 |
1004
 
1005
  **最终结论(五点)**:
1006
 
1007
+ 1. **Dueling 架构是本任务的最优选择**:V(s)/A(s,a) 分解与任务结构(大量多动作等效状态)高度吻合,Holdout 84%(+10pp vs R3),EVAL→Holdout gap 6pp(最小)。R3→R4(double) 的 +4pp 是 P7+P8+visited_map 三项叠加(见结论4),R4(double)→R4(dueling) 的 +6pp 是 Dueling 的独立贡献(控制其他变量不变)。
 
 
1008
 
1009
+ 2. **Double DQN 主要收益在训练过程,非最终结果**:危机期加速恢复(ep=700 领先 dueling 48pp)和早期收敛加速是真实收益;5000 ep 充分训练后,与纯 dueling 的 Holdout 差距(81% vs 84%)表明 Double DQN 抗高估机制在本任务规模下已不是瓶颈
1010
 
1011
+ 3. **EVAL→Holdout gap 算法质量的独立指标**:dueling 6pp、double_dueling 9pp、double 10pp、vanilla 19pp与架构泛化能力排序一致可作为独立于 Holdout 成功率的泛化质量指标
1012
 
1013
+ 4. **P7EVAL-based checkpoint)是高性价比修复,但单项贡献未严格消融**:R4-A2 visited_map,无 P7Holdout=75% +1pp不显著,间接说明 P7 是三项中单项收益最大者;严格证明需补做 3通道+EVAL checkpoint+BFS 对照组
1014
 
1015
+ 5. **P9(马尔可夫性违反)是硬约束**:任何将 episode 历史信息置于奖励函数中的循环抑制方案均导致 Q 函数目标无意义,正确解决方案唯有状态编码(visited_map)。
1016
 
1017
  ---
1018
 
docs/technical_report.md CHANGED
@@ -113,10 +113,10 @@ Step 级 warmup 可能在一局中途切换为学习模式,导致同一局内
113
 
114
  ### 4.3 Grid-SPL(Anderson et al. 2018 变体)
115
 
116
- $$\text{SPL} = \frac{1}{N} \sum_{i=1}^{N} S_i \cdot \frac{\ell^{*}_{i}}{\max(\ell^{*}_{i},\, p_{i})}$$
117
 
118
  - $S_i$:第 i 局成功标志(0/1)
119
- - $\ell^{*}_i$:BFS 最短路径步数
120
  - $p_i$:Agent **实际移动步数**(排除撞墙步,见下方说明)
121
 
122
  失败局整项贡献 0,同时惩罚绕路行为,比纯成功率更严格。
 
113
 
114
  ### 4.3 Grid-SPL(Anderson et al. 2018 变体)
115
 
116
+ $$\mathrm{SPL} = \frac{1}{N} \sum_{i=1}^{N} S_i \cdot \frac{\ell^*_i}{\max(\ell^*_i, p_i)}$$
117
 
118
  - $S_i$:第 i 局成功标志(0/1)
119
+ - $\ell^*_i$:BFS 最短路径步数
120
  - $p_i$:Agent **实际移动步数**(排除撞墙步,见下方说明)
121
 
122
  失败局整项贡献 0,同时惩罚绕路行为,比纯成功率更严格。