13. 交接:任务、猜想、教训(压缩上下文前的存档)
#13.1 任务状态
| # | 任务 | 状态 | 证据/位置 |
|---|---|---|---|
| 1 | 视觉前端可读性(英文/汉字 → 字号×下采样) | ✅ 完成 | §12.1 §12.2 |
| 2 | 字符集内在可分辨性门禁 | ✅ 完成 | §12.10 diag_charset_gate.py |
| 3 | 认字环境 read_screen(屏幕给字→打拼音) | ✅ 完成 42 项自检 | §12.13 |
| 4 | 视觉预热 + 形变增广 | ✅ 完成 | §12.9 留出字体 90.5% |
| 5 | exp31 抄写任务(老师 β:1→0 + RL) | ✅ 能跑 | §12.16 |
| 6 | 判据 1/2/3/6(正确率/认字/空白屏/emit 方差) | ✅ 通过 | 空白屏 0.0% 是铁证 |
| 7 | 判据 5(撤掉老师后 ≥50%) | ⚠️ 44.7%,未过但已 3.2× 改善 | §13.2 |
| 8 | 判据 4(留出字体,策略端) | ⚠️ 弱(8~30%),编码器端已 90.5% | |
| 9 | ★★ 同声旁结构迁移 | ⚠️ A/B = 7.8× 仍然成立,但机制未识别(见 §12.19,原判读已改) | §12.18 §12.19 |
| 10 | 形近异音第三控制(C′) | ⚠️ 跑完了,但发现它没有分辨力(满分线 0%) | §12.19 |
| 11 | D 内驱力 + E DAgger 解耦 | ✅ 实现并跑完,3.2× 改善 | §13.2 |
| 12 | 接地线(指令→执行) | ⬜ 未开始 | §13.4 |
| 13 | 工作台(全局广播) | ⬜ 未开始 | §13.4 |
| 14 | 记忆地平线 | ✅ 完成,假设被否掉 | §12.17 |
| 15 | ★ 留出集零学习基线(查最近邻满分线) | ✅ 完成,救了两个错结论 | §12.19 diag_nn_baseline.py |
| 16 | ★ 留出集逐字预测串倒出 | ✅ 完成(C′ 上 41.7% 输出孪生读音) | §12.19 diag_transfer_strings.py |
| 17 | 2×2 混淆矩阵(视觉×读音) | ⚠️ 候选池塌了,未建成(记下原因) | §12.19 |
#13.2 ★★ D+E 的最终读数(results/logs/exp31_DE.log)
| 之前(无 D/E) | DE(有 D/E) | 变化 | |
|---|---|---|---|
| β=0 时整串正确率 | 4.2% | 13.5% | 3.2× |
| β=0 时认字 | 9.4% | 36.5% | 3.9× |
| emit 均值 | 0.10~0.20 | 0.85 | 门从关死变常开 |
| 门(该开/该关) | 0.10 / 0.27 | 0.87 / 0.94 | ⚠️ 见下 |
判据 5 的分母是 30.2%(纯模仿),13.5% / 30.2% = 44.7% —— 未过 50%, 但比之前的 4.2% 好了 3.2 倍。
★ 两个新发现:
- D(内驱力)确实修好了"该动不动":emit 从 0.10 → 0.85。
- ⚠️ 但门现在"常开",矫正过头了:该关时也是 0.94(应 <0.5)。
→
DRIVE_EMIT=1.0偏大,或者缺少"说完该停"的约束。下一步要调。
#13.3 猜想清单(验证过的 / 被否掉的 / 待验证的)
| 猜想 | 结论 | 证据 |
|---|---|---|
| 用 raw 单通道就能认字 | ❌ 否 | 2.1%(=瞎猜);edge 层才是关键,四通道 84.6% |
| 降低下采样对英文有用 | ❌ 否 | 12×12 反而 85.7% |
| 汉字和英文对分辨率的需求一样 | ❌ 否 | 16px 汉字 4 次下采样 0.5%,3 次 99.8% |
| 4 次下采样 = 信息上限("6×6 不可分") | ❌ 否,是我错了 | 加形变增广后 c24/d4 从 0.4% → 91.6% |
| 多字体训练能救跨字体泛化 | ✅ 是 | 30.9% → 81.8%;加增广 → 90.5% |
| 纯 RL 能从零认字 | ❌ 否 | 冻结特征线性探针只有 2~19% |
| 目标字一直显示 → 记忆不必要 → 长不出记忆 | ❌ 否(我错了) | 字消失 20 刻准确率一点不掉(§12.17) |
| 真瓶颈是"每字 65%、误差乘性" | ✅ 是 | 31.2% ≈ 0.65³,0.65⁶≈7.5% |
| 它只是查表器 | ⚠️ 分不开(原判"否"已撤回) | A 的"查最近邻满分线"是 93.8% → 查表也能考这么高(§12.19) |
| A 的机制是"读声旁" | ⚠️ 未识别 | C′ 满分线 0% → 它没有分辨力;实测 2.0% 在噪声里(§12.19) |
| C′ 能分辨"视觉最近邻 vs 更细结构" | ❌ 否(是我的设计错) | C′ 的最近邻读音全不同音 → 两个假说都预测"低"(§12.19) |
| 给没教过的字,它会输出孪生字的读音 | ✅ 是 | C′ 上 41.7%,逐字预测串实测(§12.19) |
| 放手后崩 = RL 破坏模仿(不是池变难) | ✅ 是 | C(β=1) 30.2% vs 放手 4.2% |
| 内驱力能修 emit 门 | ✅ 是 | 0.10 → 0.85 |
| DAgger 解耦能修放手后崩 | ⚠️ 部分 | 3.2× 改善但仍未过 50% |
| 少样本/结构迁移 = 0 | ⚠️ 降级为"未定" | 原判"否"依赖 A 的判读,而 A 的机制未识别(§12.19) |
#13.4 下一步(按优先级)
- 读 C′ 形近异音(
exp31_Cnear.log)→ 钉死"视觉最近邻 vs 更细结构" - 调
DRIVE_EMIT:门现在常开(该关 0.94),需要"说完该停"的约束 - 继续压低判据 5 的差距(44.7% → 50%+):
- 候选:自我纠正(Backspace)让误差不再乘性累积
- 候选:把 drive 作为输入喂给策略(当前只调制输出,策略"感不到"它)
- 候选:更长训练 / 更好编码器
- 接地线(指令→执行):让字第一次有后果
- 工作台:只在 1–4 之后,判据 = 让"保持"与"迁移"同时改善
#13.5 ★★ 经验与教训(本阶段新增,跨任务通用)
A. 关于"假设"
- ★★ 校准锚点必须最先做。§12.17 里 N=0 那个对照(31.2% vs 训练时 30.2%) 救了整个判读:没有它,我会把 31.2% 当成"记忆掉了"的证据去改循环核,方向全错。
- ★★ 一个假设被否掉,和它被证实一样有价值 —— 前提是判据能失败。 本阶段有三个我的假设被实测否掉(记忆、下采样上限、任务漏洞),每一个都 把方向纠正到了真正的地方。
- ★ 报一个数字时必须同时报它的地板与天花板(§11.15)。"31.2%" 本身 无法解释;"地板 0.4%(随机)、天花板 100%(训练集)"才让它有意义。
B. 关于"对照设计"
- ★★ 对照集必须与实验组在「哪些变量被控制住」上对称。 形近异音对照我犯了两次同一个错(v2 随机留出的读音不在训练集; C′ 第一次构造的 5 个字读音也不在训练集)—— 两次都让对照变得不公平。 → 建对照时先列表:哪些变量必须相同?逐个核对。
- ★ 两个条件只差一个变量,否则结论无法归因。 v1(训练集 102 vs 3706)就是典型错误。
- ★ 一次训练可以同时评估多个留出集(同一个策略)—— 省一半算力, 而且天然保证两个条件在同一条学习轨迹上。
C. 关于"静默失效"(本阶段又抓了 5 个,见 §12.16)
- ★★ 不报错、不 NaN、只表现为"怎么练都不动"的 bug 是最贵的。
本阶段五个:
grp.obs没写回(策略永远看黑屏)、评估器绕过了它(第二现场)、 采样与更新不是同一个策略(h 状态没携带)、第 0 刻老师照黑屏示范、 emit 监督 14:2 类别不平衡。 - ★★ 分层可量是定位它们的唯一办法:像素差 → Crystal 差 → 编码器差 → 隐状态差 → logits 差。断在哪层一目了然。
- ★★
sup卡在ln(候选数)就是"完全没用输入"的指纹 (那是无信息时的正确最优解)。 - ★★ "训练好、评估差"先怀疑评估器也看错了输入,别急着说过拟合。
- ★ 指标要挑不依赖其它子系统的:
first_ok依赖 emit 门,门塌恒为 0;key_first_ok(直接比 argmax 键)才是干净读数。 - ★ 恒真检查 = 没在测东西。本阶段抓到两次:
gamma参数没被用上, 于是"γ<1 时原地不动白得奖励"那条反向验证永远通过; 以及gamma版塑形根本没实现。
D. 关于"工具与环境"(血泪)
- ★★★ 绝不用 shell 的字符串 cmdlet 往返读写源码(
Get-Content/Set-Content)。 一次误操作把screen_agent.py全毁,恢复花了十几轮(§12.12)。 - ★★ 这个项目现在有 git 了(
c5e638d起)。每完成一件事就提交。 - ★
.pyc当真相基准前先核对它的源文件 mtime/size;它可能比源码旧。 而且 pyc 里的测试自身可能有 bug(本次那个漏了[1]的断言)。 - ★ PowerShell 会吞掉空字符串参数(
--out ""),用none哨兵。 - ★ 中文字符串里绝不能嵌 ASCII 双引号(会截断 Python 字符串)。
本阶段我犯了 4 次。一律用
「」。 - ★ 改文件用
edit工具或 Python + 显式encoding="utf-8"; 批量改动写成可复现的补丁脚本(tools/patch_*.py),别手改。 - ★ 补丁脚本自己也可能有语法错 → 跑完必须检查它的退出码, 否则会看到"语法 OK / 自检通过"(那验的是没被改过的文件)。
- ★ 无头截图加
--virtual-time-budget会得到假阴性(时钟飞速推进 → 停滞检测立刻触发 → 全黑 25KB)。去掉它才是 295KB 的正确截图。
E. 关于"监控页"
- ★ 监控页必须按数据新鲜度停画,且"从未收到数据"要算作陈旧
(初值必须是
Date.now()而不是 0,否则最该停的场景反而永不停止)。 - ★ 同一个页面的不同部分不能有两条更新路径:本次
drawScreen在轮询回调、render2D在渲染循环 → 停画时出现"显示器有内容、面板全是 —"的矛盾画面。