17. 自主学习:自监督预测头(--pred-coef)

★★★ 2.7k 字 · 源文件 PROJECT.md 第 3296 行起 · ruler arch optim read memory

#17.1 为什么是这个东西(而不是"先停下认字去做个自主学习阶段")

用户提出:「是不是该先让它拥有『自主学习能力』,再让它学会表达?」

这个直觉方向对,但"自主学习能力"其实是两件事:

是什么可测判据现状
自主学习的能力没有老师也能从经验里变好β=0 的成绩 vs 纯模仿已经有了(判据 5 = 51.7%)
自主学习的意愿有没有自己的理由去学没有外部奖励时会不会去探索完全没有

认字任务给的是前者(β:1→0 就是"撤掉老师")。

★★ 但"先停下来做自主学习"是错的,因为:

认字任务是这个项目唯一能告诉我"视觉有没有用、记忆有没有用、状态有没有托住东西" 的仪器 —— 它有可验证的外部标准(读音是真值)。 放下它去做一个"自主学习阶段",我就失去了唯一的量具, 会变成"我觉得它在学"。

所以做法是加在它上面,不是替代它。

#17.2 设计:预测下一帧的编码(stop-gradient 当标签)

text
loss += pred_coef * MSE( pred(h_t),  z_enc(s_{t+1}).detach() )
选择为什么
预测编码,不预测原始像素96×96 像素的 MSE 会被"大部分是背景"主导,学到的多半是常数;编码是同一套已预热特征
目标是 z_enc(s_{t+1}) 且 stop-gradient否则模型可以把目标变得好预测(表征坍缩),表现是"损失下降但什么都没学会"
一次算全序列(forward_with_pred)_run_recurrence 返回 (B,T,units),不必在 rollout 里逐刻存状态(那要多传几 MB)
头零初始化给了一个精确的校准锚点(见下)

#17.3 ★★ pred_rel = 1.0 就是"什么都没学到"

读数是相对误差 MSE / mean(z²):

pred_rel含义
1.0随机预测(零初始化头的理论值,实测正好 1.0)
0.5解释掉一半方差
0.0完美预测

★ 这个 1.0 是免费的锚点 —— 和 §12.17 那个"31.2% vs 30.2%"是同一类东西: 没有它,看到 pred_rel=0.8 不知道算好还是坏。

#17.4 为什么它同时回答"能力"和"意愿"

  • 能力:预测误差 = 它在不在学这个世界,不需要任何标注
  • 意愿:预测误差就是"意外",是内在动机(好奇心)的标准定义

所以一条曲线同时回答两个问题,而且不需要给它新的任务 —— 与判据 5、无回显、留出字体并排看,一次实验四个读数。

#17.5 三条自检(防止"加了但静默无效")

新增一个目标函数最容易出的错是它根本没接进 loss(不报错,只表现为"没效果")。 所以自检里加了三条:

  1. 开预测头 -> pred_rel 是有限正数
  2. 预测头拿到了梯度(|g| > 0)—— 否则它只是装饰
  3. 关预测头 -> pred 按设计为 nan,且计算图与旧实现逐位相同 (--pred-coef 0 时走原来的 forward,不会悄悄改变旧读数)

★ 顺带一个自检本身的坑:update 返回有限值 那条原来检查 st.values() 全部有限, 而 pred 在关掉时按设计就是 nan -> 自检误报成"预测头算出了 nan"。 "故意关掉的功能"不该被算进有限性检查(已改成按 key 过滤)。

#17.6 ⚠️ PowerShell 工具链的第 4 次静默失效:.ps1 必须纯 ASCII这一阶段在"写运行脚本"这件小事上连踩四次,规律已经清楚,记下来一次说清:

#现象根因修法
1Tee-Object 写的日志中文变成 U+FFFD(不可恢复)PowerShell 把管道输出按控制台编码(GBK)转文本让 Python 自己写日志(--log)
2`2>&1 \` 同样毁掉中文同上(2>&1 也走文本转换)同上;或 2> file.err(只丢 stderr)
3.ps1 里含中文 -> 字符串缺少终止符 之类的假语法错PowerShell 5.1 按 ANSI/GBK 读 .ps1,UTF-8 的中文被读成乱码字节.ps1 保持纯 ASCII;中文放 .py 里
4多行哈希表 + foreach 报一堆莫名其妙的语法错解析器在上一处出错后级联误报(真正的原因可能在第 3 条)先查非 ASCII 字节数,(Get-Content -Raw).Length 式的检查没用

可复用的三条(都是这一阶段换来的):

  1. .ps1 里一个非 ASCII 字节都不要有。 用 (Get-Content -Raw).Length 检查不了,要按字节数: ([System.IO.File]::ReadAllBytes($p) | Where-Object { $_ -gt 127 }).Count —— 实测三个脚本现在都是 0。

  2. 中文参数走"代号 + Python 侧映射"。例子:--new-cmd 下 会毁掉整个脚本, 改成 --new-cmd AUTO(Python 里解析成"挑一条与 --base-cmd 不同的指令")。

  3. 日志一律 --log(Python 自己写 UTF-8),不要经过 PowerShell 的管道。

← 返回《PROJECT.md》目录