20. 定容量:8.71M 参数 / 6 GB 显存 / 4470 刻每秒(已定为默认)
★★★
28.0k 字 ·
源文件 PROJECT.md 第 3724 行起 ·
ruler arch external
用户的明确要求(2026-09-27):
「定一个这样的参数量吧,训练和运行时吃 6G 显存,占用尽量吃满」
#20.1 ★★ 为什么必须看整卡读数,不能看 torch.max_memory_allocated()
experiments/diag_capacity_6g.py 的实测对照(同一配置,两种量法):
| 配置 | PyTorch 自报 allocated | 自报 reserved | nvidia-smi 整卡峰值 | 差 |
|---|---|---|---|---|
| u4096 bb256 B256 T24 | 3884 MiB | 5204 MiB | 5690 MiB | 1.5× |
差额来自 CUDA 上下文 + cuDNN 工作区 + 分配器缓存碎片。
★★ 这正是 §19 那次"爆显存"事故的根因:我按自报的 1415 MiB 估每个进程, 于是开了 4 个并行;实际每个吃 4.1~4.5 GB,8.6 GB 塞进 8.0 GB 的卡。 Windows WDDM 把溢出部分放进系统内存(共享显存涨到 15.9 GB), 每次张量访问都过 PCIe —— 整机卡顿、速度塌方。
立即可用的规矩:定并行数/定 batch 一律用
nvidia-smi的整卡读数。
#20.2 容量扫描结果
| 配置 | 参数量 | 整卡峰值 | 刻/秒 | 判定 |
|---|---|---|---|---|
| u256 bb16 B64 T16 | 1,377,396 | 2093 MiB | 3408 | 偏小 |
| u1024 bb64 B64 T16 | 2,107,044 | 2235 MiB | 3401 | 偏小 |
| u2048 bb128 B128 T16 | 3,653,348 | 2984 MiB | 3928 | 偏小 |
| u4096 bb256 B256 T16 | 8,712,036 | 4914 MiB | 4147 | 可用 |
| u4096 bb256 B256 T24 | 8,712,036 | 5690 MiB(95%) | 4470 | ★ 推荐 |
| u4096 bb512 B384 T16 | 14,020,708 | 6152 MiB | 4082 | 超预算 |
| u8192 bb512 B512 T16 | 26,693,732 | 7864 MiB | 1678 | 超预算(吞吐崩了) |
| u8192 bb512 B384 T24 | 26,693,732 | 7794 MiB | 977 | 超预算(吞吐崩了) |
#20.3 ★★ 定案:units=4096, backbone=256, batch=256
参数量 8,712,036 (比之前的 1.31M 大 6.6 倍)
整卡显存 5690 / 6000 MiB = 95%
吞吐 4470 刻/秒 (之前的 B64 是 2860 -> 快 56%)★ 又一次验证 §15 那条"加参数几乎免费":
| 参数量 | 秒/步 | |
|---|---|---|
| u256 bb16 B256 | 1.38M | — |
| u4096 bb256 B256 | 8.71M(×6.3) | 只慢 9% |
★ u8192 那一档吞吐塌方(1678 / 977 刻/秒)—— 说明算力墙在 26M 参数附近,
再往上加就要付真代价。8.7M 是这台机器在当前任务形状下的甜点。
#20.4 配套改动
tools/gpu_guard.py:开跑前查整卡空闲显存,不够就等而不是硬闯。 参数化--need-mb(exp31 ≈ 4200、exp41 ≈ 4600)。实测过两种情形都判对。tools/run_serial.ps1:一次只跑一个大任务,每次开跑前过闸门。 取代之前那些并行启动器(并行的代价已经用一次事故交过学费了)。--enc-lr-scale/ 冻结:接地线的诊断显示lr=3e-3会一直在动预训练编码器, 而|g|长期 10~38(裁剪阈值 1.0,一直被裁)。大模型必须给小 lr。
#20.5 ★★ 接地线的新发现:任务是可学的,之前全是配置错
experiments/diag_ground_learn.py(纯模仿 150 步,起点格距恒为 3.00):
| 配置 | 平均格距 | 到位率 | sup_c | ` | g | ` |
|---|---|---|---|---|---|---|
| 基线 lr3e-3 cw25 | 1.00 | 12.5% | 0.222 | 10.4 | ||
| 冻结编码器 | 3.00 | 0% | 0.220 | 5.2 | ||
| 编码器 lr×0.02 | 4.00 | 0% | 0.221 | 4.6 | ||
| lr 3e-4 | 3.00 | 0% | 0.220 | 3.6 | ||
| lr 1e-4 | 1.00 | 100% | 0.426 | 38.3 | ||
| CONT_W 5 | 1.00 | 0% | 0.221 | 2.3 | ||
| CONT_W 100 | 0.50 | 50% | 0.222 | 23.9 | ||
| 冻结 + lr3e-4 | 3.00 | 0% | 0.228 | 10.7 |
★★ 有组合能让它动起来(
CONT_W=100时格距 0.50、到位率 50%) —— 所以不是架构问题,是配置问题。而且规律很清楚: ·
lr太小(3e-4 / 1e-4)反而更容易停在 3.00(学不动) ·CONT_W是关键:5 时不动、25 时勉强、100 时才明确动 -> 印证了 §14.6 那个判断(79 个"永远负"的离散位会淹没 2 维摇杆), 而且我估的 25 还是太小。 · 冻结编码器 / 把 encoder lr 调小 并不能救(都是 3.00~4.00) -> 说明不是"编码器被改坏",而是摇杆那一路的梯度不够★ 注意
sup_c在 lr1e-4/100% 那组反而更高(0.426):因为它真的在输出 变化的摇杆值(而不是恒定 0),MSE 自然更大。不要用sup_c的绝对值判断好坏。
为什么会这样(假说,待验证):
- 优势估计的尺度问题:塑形奖励是编辑距离(量级 0~6),
而
adv做了批内标准化 —— 标准化会把"模仿得很好、所有动作都对"的样本 也变成有正有负的噪声,于是 RL 项在惩罚正确的动作。 · 判据:看rl那一项在 β→0 之后的正负(实测多为负:rl=-0.414 / -0.020 / +0.137乱跳) v一直降不下来(0.9~2.5),说明价值函数没学会 —— 优势就是噪声。- 探索噪声不该加在"已经在做对的事"上:β=1 时策略已 99.3% 正确, 此时 RL 的唯一作用是把它推离那个解。
★ 这三条都可以用现有日志验证,见 §19.5 的实验计划。
#19.5 下一步:先解释"RL 为什么会破坏模仿"
| 实验 | 做法 | 判据 |
|---|---|---|
| E1 关掉 RL(只留监督) | --beta-floor 1.0 跑满 1000 步 | 若到 95%+ -> 模仿本身没问题,问题全在 RL |
| E2 只降 lr 的 RL 部分 | 策略头 lr 调小、编码器照旧 | 若掉幅变小 -> 是步子太大 |
| E3 加 KL 锚(信任域) | 加 KL(π ‖ π_模仿) 惩罚项 | 正解,但要写代码 |
| E4 优势不改尺度 | 去掉 adv 的批内标准化 | 若 rl 不再乱跳 -> 就是尺度问题 |
优先级:E1(免费,只要一个参数)-> E4(改一行)-> E3(要写代码)。
★ E1 值得马上做:它是"RL 到底有没有正贡献"的直接判据, 而现在我们对这个问题的答案可能是没有。
§21 第 0 步:hunger 从"假驱力"变成"真驱力"(四项判据全过)
用户的要求(明确排序): 先需求/欲望(如好奇心、生存欲)-> 后期情感需求 -> 对它自己有认知
一、先修已经有的那个:hunger 原来是假的
energy += RATE 每刻涨;energy -= GAIN if dist==0 只有"整串打对"才掉。
而"整串打对"要求先开门、先打字、每字 65% 正确率 -> 几乎永远发生不了
-> clamp(0,1) 把它顶在 1.0 -> 一个恒定在 1.0 的信号不是驱力,是偏置。
★★ 一个不改变行为的"驱力"不是驱力,是标签。 它最危险的地方:看起来很深,而且永远不会以失败的形式暴露 —— 你没法从日志上看出"它其实没被驱动"。
二、修的过程中连踩三个设计错(每个都留档)
- 判据在"策略没学会"时没有分辨力: 第一版在同一个训练过程里换 DRIVE_REWARD 比行为,两个跑次正确率都是 9.4%(都还没学会)-> "行为一模一样"是必然的。 与 §12.19「C′ 满分线 0%」同类:分不开不是因为机制没用,而是任务没做对。 修法:先训会,再对照。
- 开关必须作用在"会改变参数"的那条路径上: 第二版在一个已冻结的策略上改 DRIVE_REWARD 再比行为 —— 而它只在训练时影响奖励,冻结后改它对行为不可能有影响。 那次读数(22.7% vs 22.7%)同样是必然的。 修法:同配置各训一次再比。
- ★★★ Δd 被"换字"主导,方向是反的:
corr(energy, Δd)= +0.285 —— 越"进步"越饿。 原因:回合结束换一个新目标,dist 从 0 跳回 2~6,那是个巨大且无意义的 Δd。 -> 那个驱力机制在跟踪"换题",不是在跟踪"做得好不好"。 修法:饱足信号改用真正的成就(dist == 0,环境免费给): energy += RATE(1 - solved) - GAINsolved*energy
三、最终读数(diag_hunger.py --warm-steps 400)
判据 结果
① 能量不是常数(std>0.02) 0.2131 [OK]
② 跟着成就走(corr(energy,距离)>0)+0.814 [OK] 越近越饱
③ 没长期饱和(<50%) 0.0% [OK](DRIVE_MAX 从 1.0 放宽到 3.0)
④ 行为对照(各训一次) 正确率差 3.9pp / 认字差 7.8pp [OK]
energy 均值 0.145 范围 [0.000, 0.600]
四、⚠️ 但判据 ④ 的方向是负的(重要的意外) DRIVE_REWARD=0.5 -> 正确率 4.7% 认字 29.7% d 2.55 DRIVE_REWARD=0.0 -> 正确率 8.6% 认字 37.5% d 2.39 -> 驱力确实改变了训练,但开驱力的更差。
原因(假说,很确定):r_used = r_ext * (1 + DRIVE_REWARD*energy) 是乘性放大。
能量 97.7% 时间很低 -> 调制大多数时候几乎不起作用(乘 1.07);
偶尔能量高时把奖励放大约 1.3 倍 -> 只是增加了策略梯度的方差,
没有提供任何方向性信息。
> ★★ 一个有信息量的驱力应该改变"做什么",而不是"奖励多大"。 > 现在这版只改了后者 —— 所以它降级成了"噪声源"。
★ 这条修正了 §13.2 里「内驱力能修 emit 门 -> ✅」那个结论: 那次改善很可能来自 emit 调制(它改变采样分布 = 改变行为), 而惩罚变差的是 reward 调制(它只改奖励尺度)。两者必须分开评价。
五、得到的新判据(以后每个驱力都按这个测)
- 不是常数:std > 0.02
- 跟着成就走:corr(驱力, 成就) 的符号必须对
- 不贴天花板:饱和占比 < 50%
- ★★ 改变行为:同配置各训一次,行为读数必须不同(且方向要更好)
- ★ 前置:策略必须先学会,否则判据 4 没有分辨力
六、下一步 好奇心(第 1 层)—— 注意它天然满足"改变做什么"(它改变去哪里看), 所以预期能避开第五点那个"只改奖励尺度"的坑。 附带的噪声区自检必须做(noisy-TV 陷阱)。
§22 第 1 步:好奇心(机制已建、防线未验证、判据已就位)
一、机制(已建)
· 内在奖励 = 预测误差 / 集成分歧(r += CURIOSITY * curiosity),
加法而不是乘法 —— §21 已证明乘法只改奖励尺度、只增加梯度方差。
· 两道门 + 集成分歧:
门 1 画面必须真的在变(用原始像素的最大逐像素变化)
门 2 单头路线:误差 > 近期滑动均值 × 1.5
集成路线(推荐):奖励 K 个头之间的分歧(Pathak 2017)
二、★★★ 关键洞察:分歧衡量"认不认得",误差衡量"准不准" 噪声永远测不准,但很快认得出来它是噪声 —— 只有分歧能表达这一点。 这是集成路线在原理上优于单头路线的唯一理由。
三、★★ 连踩三个"探针设计错"(比实现错更贵)
- 判据对不同实现给出同一个数 -> 先怀疑判据。 第一版探针用未训练的策略,单头与集成都给 81.25%。 随机初始化的头当然互相分歧 —— 那个数测的是"未训练策略",不是"防线"。
- 门 1 的度量选错了:原来用
.mean()(全屏平均)。 噪声区 24×24=576 像素只占 96×96 的 6.25%, 它在全屏平均里被稀释到 ~0.007,远低于阈值 0.02 —— 门 1 从来没真正工作过,而它算出的"变化"几乎完全由字符区决定 (成了"字有没有变"的代理,不是"屏幕有没有动")。 改成.amax()(最大逐像素变化)后才符合设计意图。 assert形状守卫 > 猜:好奇心涉及 5 个张量的广播, 报错只说size of tensor a (96) must match b (32),不说是哪个。 实测形状:x=(B,1,1,96,96)—— 取帧要两级索引[:, 0, 0]。
四、⚠️ 诚实结论:防线未验证
分段趋势(--steps 120,噪声区在场):
集成头数 = 1:93.8% -> 93.8% -> 93.8% -> 93.7% -> 92.9% -> 83.7% [不降]
集成头数 = 3:93.8% -> 93.8% -> 93.8% -> 93.8% -> 93.8% -> 93.8% [不降]
没有一个降下来,所以:我没有一个经过验证的 noisy-TV 防线。
已知的两个原因(都还没排除): a) 算力:120~400 步、batch 32~64 下,预测头远未训练好, 分歧还没收敛到"噪声处为 0"。 b) 门 1 的语义:随机噪声块确实是"屏幕在变", 门 1 按设计就该放行它 —— 它只负责挡"静止屏", 不负责区分"可学的新奇"和"不可学的噪声"。那个责任全在门 2 / 集成上。
五、目前唯一站得住的判据(已全过) · 好奇心信号真的在发(非零占比 2.4%) · 开关好奇心,行为确实不同(正确率/认字/d/emit 都有差) · ★ 判据 5(认字)没有掉 —— 没有"用意外换成绩"
六、下一步(下一步该做的)
- 把预测头训好(
--steps 2000+)再看分歧在噪声处是否趋于 0。 若仍然不趋于 0,那就不是算力问题,是噪声块真的不可学(不可学即应被奖励?不)。 - 若集成路线也失败,退回"可学性"判据: 用"预测误差随参数更新而下降的速度"当新奇度,而不是终值。
- ★ 但这三步都应在有注视控制的环境里做 —— 本环境没有注视, noisy-TV 的经典形式不可表达,探针只能用"噪声块"这种替代物, 而替代物与真现象不等价(这正是本次判据反复失效的根源)。
§23 ★★★ RND 换目标:noisy-TV 被根治 + 三个判据设计错
用户的判断:"我认为情感需求的陪伴之类的是为生存的一种机制,好奇心可能也是为了 更好地学习,饥饿也是,他们都是为了生存服务的……但这些机制应该是从生存需求 衍生出来的还是本身就存在的?"
一、查到的现成机制(RND / Burda 2018, arXiv:1810.12894) ① ★★★ 预测目标必须是输入的确定函数 —— 这是根治 noisy-TV 的正解 原文诊断:agents that maximize such prediction errors tend to get attracted to transitions where the answer to the prediction problem is a stochastic function of the inputs … the 'noisy-TV' problem 原文解法:define an exploration bonus using a prediction problem where the answer is a deterministic function of its inputs. Namely we predict the output of a fixed randomly initialized neural network on the current observation. ② 内在奖励必须归一化(除以内在回报的滑动标准差) ③ 两条奖励流两个价值头 —— 因为"外在工作奖励是平稳的,内在奖励是非平稳的" ④ 事实:内在奖励会衰减/消失(学过的就不新奇) ⑤ 陷阱:非回合制的外部奖励会被"故意自杀重开刷开头奖励"利用
经验依据(RND Table 1,Montezuma)—— 只换预测目标: RND 8,152 vs 前向动力学误差 400 (差 20 倍)
二、★ 我们原来的实现错在哪(这是本节最重要的一条)
旧:predictor(当前帧) -> 编码器(下一帧) ❌ 目标是随机的
新:predictor(当前帧) -> 固定随机网络(当前帧) ✅ 目标是确定函数
=> 我加的两道门 + 集成,全部是在给一个错误的问题打补丁。
RND 路线根本不需要 noisy-TV 的门。
三、★★★ 决定性验证(diag_rnd_noise.py --steps 180)
无噪声 :内在奖励幅度 0.3505 -> 0.2689 -> 0.2736 -> 0.2846 -> 0.2757 -> 0.2766 (78.9%)
噪声区在场:内在奖励幅度 0.7983 -> 0.4110 -> 0.1538 -> 0.0764 -> 0.0607 -> 0.0506 (6.3%)
判据 结果 ① 噪声区幅度大幅衰减(末段<首段25%) 6.3% [OK] ② 末段幅度 < 0.10(相对任务奖励可忽略) 0.0506 [OK] ③ 字符区信号还在 0.2766 [OK] ④ ★★ 噪声区衰减比字符区更快 6.3% vs 78.9% [OK]
★★ 判据 ④ 最有说服力:噪声被认得比字形更快 —— 因为噪声块是输入的 确定函数(每个像素只是它自己),而字形之间的差别要多花样本。 这正是 RND 的机制,而它在数据里显形了。
对照(旧实现的现场,--steps 120):
集成头数=1:非零占比 93.8% -> 93.8% -> 92.9% -> 83.7% [不降]
集成头数=3:非零占比 93.8% -> 93.8% -> 93.8% -> 93.8% [不降]
四、★★ 又一次"判据设计错"(第四次了,值得单列)
"非零占比"这个判据对 RND 这条路线恒为 100% —— 因为 RND 的奖励是
pe / running_rms,一个归一化后的均方误差,永远不可能恰好为 0。
我第一版用它,于是"100% -> 100%"被读成失败,而同一批数据的幅度
显示噪声区降了 16 倍。
> ★★ 要测的量必须能区分对与错。一个恒为 100% 的量测不出任何东西。 > 这与 §21「策略没学会时判据没有分辨力」、§22「判据对不同实现给同一个数」 > 是同一类错误的第四次出现。这是本项目最反复的失效模式。
五、关于"衍生 vs 原生"(用户的问题) · 心理学没有定论: Hull 驱力减退(1943):全部为降低生物驱力 Berlyne(1950s):老鼠在无任何强化的迷宫里仍主动探索 -> 驱力减退说不成立 Butler(1954):猴子为"看一眼"而工作 -> 探索本身即奖励 Harlow 恒河猴:小猴选没奶的绒布妈妈 -> 依恋不是喂食派生的 · Panksepp:7 个初级情绪系统(含 SEEKING=好奇、CARE、PANIC/GRIEF=分离焦虑) · Deci & Ryan:自主/胜任/联结是基本心理需求,与生理需求并列 · ★ 最站得住的中间立场:硬件给定,参数可塑(半原生) —— 机制原生,但目标对象与强度是学出来的 · 架构结论:不能只有一条"生存"标量(与 Harlow 矛盾); 取"分层":每条内在线各自原生 + 各自的价值头;生存当终止/可行性约束, 不当唯一分数。这正是 RND 第 ③ 条的推广。
六、本次代码改动
· pred_target:冻结的随机网络(题目),pred:学生
· 预测改到同一时刻(pred(h_t) -> pred_target(z_t))
· 逐样本误差 pred_pe (B,T) -> 内在奖励;pred_rms 是 buffer(跟着权重存)
· 删掉两道门、集成分支、cur_prev_z/cur_prev_scr
· 4 条 RND 自检(冻结/目标确定性/predictor 有梯度/pred_rms 是 buffer)
· --curiosity 现在必须配 --pred-coef > 0(否则报错退出,不静默失效)
#记录:RND 之后的第二次改动(双价值头)以及一个回归的定位过程
#这份文件是诊断笔记,不是提交信息。
现状(未提交):
exp31_read_rl.py +114 行:加 v_int 第二价值头、pred_pe 逐样本、
内在奖励归一化、forward_with_pred 加 PRED_COEF 守卫
exp41_ground_rl.py +29 行:改走 forward_with_pred(但不用 val_int)
回归:
exp31 自检 21 项全过
exp41 自检的回归判据 FAIL:纯模仿 120 步后平均格距 3.00/4.00,
而 9c60573 时是 1.00
同时 diag_min_repro.py 的 |g| 从 10~40 掉到 0.2
已排除:
· 不是 _g.reset 那一行(有无都一样)
· 不是 diag_min_repro 的 LIFO 栈污染(那是我读错,但两个 case 都是 3.00)
· 不是预测头的梯度泄漏(已加 PRED_COEF<=0 守卫在模型内部,exp41 走
forward_with_pred 时 pred/tgt 都是 None)
我的第一个改动(RND 换目标)是已验证的: 噪声区内奖励幅度 0.7983 -> 0.0506(6.3%),字符区 78.9% -> 判据 ④ 过 见 §23 与 results/logs/rnd_noise.json
所以问题一定在这次「双价值头」改动里。下一步是在同一状态上做干净的
A/B:把 v_int 从 ReadPolicy 里去掉,看 exp41 自检是否立刻回到 1.00。
§25 两个数据缺口 + 一次"以磁盘为准"的校正
一、★★★ 数据缺口一:acc_eval 声明了却从来没被写入
curve_*.json 里声明了 "acc_eval": None,但代码里没有任何地方给它赋值
-> 我们所有曲线里一个评估量都没有,只有逐 step 的训练损失。
为什么这个缺口很贵:它让我无法回答"能力跳变是真的还是度量造的"。 而那个问题(Schaeffer et al., arXiv 2304.15004)正好是我们反复踩的坑。
已修:评估点把五个量并排写进曲线 ——
· acc_eval 离散(0/1,"整串全对") ← 嫌疑对象
· dist_eval 连续(编辑距离)
· first_eval 连续(首字正确率)
· key1_eval 连续(认字率)
· emit_eval 连续(门开率)
验证:tools/show_curve_metrics.py results/logs/curve_metriccheck.json
-> 5 个键都在,格式通过。
> ★ 规矩:声明了却从不写入的字段 = 数据缺口,比崩溃更难发现 —— > 因为它不报错,只是让某个问题永远无法回答。
二、★★★ 数据缺口二:我自己的记忆缺口(这个更值钱)
本轮开始时我以为项目停在"好奇心防线未验证"。
实际 git log 显示已有两个提交是我记忆里没有的:
9c60573 §23 RND 换目标:noisy-TV 被根治
54ec37e 双价值头 + 修判据(格距方差太大导致连续误判两轮)
> ★★ 上下文压缩会制造"记忆缺口",而缺口的表现是"我以为的进度"与
> 磁盘状态不一致。
> 规矩:每轮开头先 git log + 读 tools/diag_note.md,
> 以磁盘为准,不要以叙述为准。这次正是这样校正回来的。
三、★★ 校正后的真实状态(磁盘为准)
| 项 | 状态 |
|---|---|
| RND 换目标 | ✅ 已验证:噪声区奖励幅度 0.7983 -> 0.0506(6.3%) |
双价值头 v_int | ✅ 已实现并跑通 600 步 |
| exp31 自检 | ✅ 21 项全过 |
| exp41 自检 | ✅ 全过(判据已改用 sup_c 是否下降) |
| 涌现判据 | ⏳ 曲线记录已补齐,形状对比待跑 |
四、★★★ 双价值头对"RL 摧毁模仿"的效果(这是目前最硬的一条对比)
同一个接地线任务、同一个 β 日程(β 降到 0):
| 跑次 | β=0 后到位率 | 平均格距 |
|---|---|---|
big_c1(单价值头) | 25.0% | 3.00 |
v2head(双价值头) | 50.0% | 2.00 |
★ 双价值头把 β→0 之后的性能从 25% 提到 50%(翻倍)。 方向与预测一致(RND 那篇说"两个头各面对一个平稳/非平稳的流"), 但没有完全解决 —— 仍低于纯模仿期的 100%。
> 所以"RL 摧毁模仿"现在是三个可分辨的层次: > ① 纯模仿(β=1):100% > ② 双价值头 + RL(β=0):50% > ③ 单价值头 + RL(β=0):25% > 每加一个正确的机制,恢复一层。下一步要找的是第二层缺口(50% -> 100%)。
五、"涌现"那条判据的进展
experiments/diag_emergence_metric.py 已建,判据是
跳变度 = max|Δ| / (max-min):平滑曲线 ≈ 1/步数,阶跃曲线 ≈ 1。
对现有曲线(只有连续量)测得:teach_acc 的跳变度 0.28~0.72。
★ 注意这不是结论 —— 它说明连续量本身也不平滑(这削弱了
"跳变全是度量造的"这一简单版本),但要真正检验 Schaeffer,
必须让离散量也进曲线(已补上,待跑)。
六、教训:判据的方差会让人连续误判
54ec37e 记录:平均格距在同一配置下能从 1.00 变到 5.00(只有 16 个回合),
于是连续两轮把"没学会"误判成"会动"、又反过来。
修法:改用 sup_c(监督项的连续分量)是否下降 —— 它来自 4096 个样本,
方差小得多。
> ★ 与 §22 那三条"判据设计错"是同一类:判据本身的噪声 = 假结论。
§26 检验"涌现是度量造的吗":一个判据失效,一个结论(阴性)
一、读到的东西(Schaeffer et al. 的精确主张) "Are Emergent Abilities of Large Language Models a Mirage?" arXiv 2304.15004,NeurIPS 2023 最佳论文: > "when analyzing fixed model outputs, emergent abilities appear due to the > researcher's choice of metric … nonlinear or discontinuous metrics produce > apparent emergent abilities, whereas linear or continuous metrics produce > smooth, continuous predictable changes"
★ 关键在 "fixed model outputs" —— 他主张的是:模型能力已经饱和 (曲线本应平了)时,离散度量凭空造出跳变。 不是在"学习还在快速爬升"的阶段。
二、★★★ 判据失效:跳变度在点数少时恒等于 1
第一版判据 jump = max|Δ| / (max-min)。实测 4 个量
(1 个离散 acc_eval + 3 个连续 dist_eval/first_eval/key1_eval)
全是 1.000。
原因:5 个点必然包含 max 和 min,所以 max|Δ| = max-min,比值恒为 1。
这个判据在 n=5 时没有任何分辨力。
> ★★★ 这是我在 §22 写下那条规矩的第三次违例: > "判据若对不同实现给出同一个数,先怀疑判据,别怀疑实现。" > 第一次:未训练策略的探针(单头/集成都 81.25%) > 第二次:没学会的任务(两组行为都是 9.4%) > 第三次:点数不够(四个量都是 1.000) > ★ 规律:判据失效的样子总是"所有东西看起来一样"。
已修:改成按点数归一的 jumpiness * (n-1)
(1 = 完全平滑,n-1 = 一步到位),且 n < 8 一律标 nan。
三、★★ 结论(阴性,且不支持 Schaeffer 的简单版本)
在同一组评估点上(8 点,curve_shape.json):
| 度量 | 类型 | 归一跳变度 |
|---|---|---|
acc_eval | 离散 | 6.87 |
dist_eval | 连续 | 7.00 |
first_eval | 连续 | 5.69 |
key1_eval | 连续 | 6.56 |
| 离散/连续 | 1.09× |
离散量并没有比连续量更跳。 所以在这份数据上, "能力跳变是度量造出来的"不成立。
四、★ 但这一轮不能用来检验 Schaeffer(混淆必须说清)
curve_shape.json 只跑了 50 步 —— 模型处在早期快速学习期,
所有曲线都在陡升,于是任何度量看起来都"跳"。
要真正检验,需要:跑到曲线真的平下来,然后看离散量在 "连续量已经平坦"的区域是否仍然跳。 -> 这是下一轮该做的那件事(不需要新机制,只需要跑长 + 用已补的曲线记录)。
五、这一轮的正面产出(都是可复用的)
acc_eval声明了却从未被写入 -> 已修,五个评估量并排入曲线 (离散acc_eval+ 连续dist_eval/first_eval/key1_eval/emit_eval)experiments/diag_emergence_metric.py—— 判据已修成按点数归一tools/show_curve_metrics.py—— 看一条曲线的离散/连续量- ★★ "每轮开头先
git log+ 读tools/diag_note.md" —— 本轮正是靠这条才发现两个我记忆里没有的提交(§23 RND、双价值头), 上下文压缩会造成记忆缺口,必须以磁盘为准。
六、意识文献的要点(子代理报告,全文在 darlin-consciousness-literature-report.md)
(用户 brief 的三处纠正)
· arXiv 1810.11143 不是展开论证,它是 "Smell Pittsburgh";
展开论证没有 arXiv 版,规范引用是 doi 10.1016/j.concog.2019.04.002
· "The Free Energy Principle: A Critique"(Colombo & Wright)未能证实存在
· "Juliani et al. Deep Learning and the GWT" 是另一篇(arXiv 2204.05133)
(改变"下一步做什么"的四条)
- Butlin 表不是测试,是可信度更新:其 v3 免责声明说满足指标 "would not mean that such an AI system would definitely be conscious"; 且 Koch, arXiv 2603.27597 指出这些赋值 无法校准、生物到硅的迁移无独立支持。 -> 唯一诚实的输出是相对建筑排名,永远不是概率。
- ★★ 可辩护的可测构念是
meta-d'(Type-2 元认知敏感度),不是"意识"。ECE/Brier把"知道多少"和"知道得准不准"混在一起。 ★ 必须用 0–20 置信度刻度:0–100 时 >78% 的回答挤在三个整数上。 - ★★ 唯一有已发表先例的因果协议:"no-rewire 自我模型损伤"双分离 (Phua, arXiv 2512.19155)—— "abolishes metacognitive calibration while preserving first-order task performance"(合成版盲视)。 同一篇的阴性结果:工作台瓶颈下 PCI-A 反而下降 —— IIT 系代理指标不能naive搬到工程智能体上。
- 不要建在 Φ/IIT 或 FEP-as-metaphysics 上(三重独立否证 + 2025 Nature 对手合作实验同时重创 IIT 与 GNWT)。 但 active inference 有具体的可证伪内容(如标准版在 horizon=1 是 Bellman 最优、再长就失败)。
("自我模型"的最低门槛:5 个条件,每个都有已记录的失效模式) · 写在决策路径上,不是旁边 —— Xie, arXiv 2604.11914:辅助置信模块 "collapse to near-constant outputs (confidence std < 0.006)"、 "the agent's decisions are unaffected by module outputs" · 显式且可解码(探针能从内部激活读出"关于自己"的属性,且不是世界模型已给的) · 生成式/预测式(要报误差 + 零假设 + 时程) · 选择性必要(双分离) —— 这是承重的那条 · 设计上就不完整(自身状态的残差误差有非零地板)
§25 ★★ 双价值头的决定性验证结果(崩溃止住了,但没保住最好状态)
一、对照(判据在跑之前写死:β→0 之后不许崩)
步 β v2head(双价值头) big_c1(单头,对照) 到位率 高亮前 教师一致 到位率 高亮前 教师一致 120 1.00 45.3% 45.3% +0.252 — — — 180 0.82 0.0% 0.0% +0.314 100% 100% +0.264 240 0.64 0.0% 0.0% +0.391 100% 100% +0.285 300 0.46 0.0% 0.0% +0.470 75% 75% +0.341 360 0.29 18.8% 18.8% +0.556 100% 100% +0.331 420 0.11 25.0% 25.0% +0.547 100% 100% +0.328 480 0.00 54.7% 54.7% +0.324 100% 100% +0.314 540 0.00 50.0% 50.0% +0.430 25% 25% -0.449 600 0.00 50.0% 50.0% +0.108 25% 25% -0.441
二、结论(诚实版) ✅ 双价值头止住了崩溃:β→0 之后不再从 100% 崩到 25%。 ✅ ★ 教师一致度再没翻符号:big_c1 在步 540 变成 -0.449(符号都反了), v2head 全程为正、末尾 +0.108。 ❌ 但它没保住最好状态:v2head 的峰值只有 45.3%(步 120), 末尾 50%;而纯模仿(β≡1)能到 100%。 -> 所以"非平稳流"是部分原因,不是全部。 -> 判据 5 的分母仍是 100%(纯模仿),所有 β 退火跑次都还在它之下。
三、下一个嫌疑:量级(两条,都已做成开关)
(a) pi 在步 600 到 -4.954,而 sup 只有 0.33~0.86 ——
RL 项比监督项大一个数量级,而监督项才是让策略"会做"的东西。
这正是 §21 在 exp31 里发现的同一个病(那边监督 ~0.02、RL 1~45)。
-> 加 --rl-scale
(b) ★★ exp41 原来一直在做 advantage 批内标准化:
adv_n = (adv - mean) / (std + 1e-6)
β→0 时 not_taught 变多、adv 的批内方差变小,
除以一个小 std 会把噪声放大。
exp31 里已经发现并默认关掉了这个(§21),但 exp41 漏了 ——
两个文件同一处逻辑分叉,正是 §18 那条"两处必须一致"的又一次代价。
-> 加 --adv-norm(默认关)
四、正在跑(run_N_rlscale.ps1)
rs01(rl-scale 0.1)、rs002(0.02)、rs01frozen(rl-scale 0.1 + β 下限 0.1)
判据:至少要有一个超过 50%,同时 β→0 之后仍不许崩。
五、★★★ 本次最贵的一课:判据本身的方差
改完双价值头后 exp41 自检回归 FAIL(格距 3.00 -> 4.00),
我连续给出两个错误归因(先怪共享 rng,再怪双价值头)。
真凶是判据(平均格距)方差极大:
diag_min_repro.py 同一份代码、同一策略,
训练循环前有 _g.reset(...) -> 格距 1.00
训练循环前没有那一行 -> 格距 5.00
起点本身也在 3.00~5.00 摆动。
> ★★★ 用一个方差巨大的代理量去判"结构性改动有没有把东西弄坏", > 必然得到随机结论。 我为此连看两轮 1.00/3.00/3.88/4.00/4.25/4.88, > 一直以为"代码在退化",而它只是同一个健康状态的噪声。
修法:换直接读数 sup_c(监督项的摇杆分量):
健康(自检):1.101 -> 0.222
健康(§21 外部):~4.5 -> 0.22
坏掉(79 离散位淹没摇杆):起点就只有 ~0.22,且不降
判据 = "降到 0.5 以下 且 相对起点降 ≥1.5 倍"。
★ 附带:阈值不能用"起点绝对值"卡死(起点随初始状态在 1.1~4.5 变),
要卡的是降幅。
六、未解决的环境问题(记下来,别忘)
_g.reset(...) 会改变训练结果(1.00 vs 5.00)。说明
GroundGroup.reset 用 self.rng 抽字体这件事,让"重置一次"
成了一个有副作用的操作。应当让字体抽样完全由显式种子决定,
不受"这个对象被用过几次"影响。(evaluate 已走显式 seed,训练循环里还没有。)
七、提交纪律(一次小事故)
我用 git add -A 时把 _emergence_research/ 里 9 个 .raw/.txt
研究中间产物误提交了(2914 行数据)。
已 git rm --cached 撤出,并给 .gitignore 加 *.raw。
> ★ 教训:提交要用显式路径(git add experiments/ tools/ PROJECT.md),
> 不要 git add -A —— 工作目录里随时可能有别人的产物。
§27 三主题调研定稿:能落地的规则 + 一条可立即检验的假说
三个子代理全部交回(各写了完整报告文件):
· 涌现 _emergence_research/EMERGENCE_SURVEY.md
· 意识 darlin-consciousness-literature-report.md
· LNN 见下文第六节(本会话内已落地)
一、★★★ 涌现:定稿结论(比我 §26 写的更精确)
- Schaeffer et al. 的主张成立,但比双方说的都窄。
已确立:① 构造性演示(固定模型输出只换度量,跳变消失;
GPT-3 算术、LaMDA/BIG-bench,外加两个从没人声称涌现的视觉域);
② 总体基率(39 个 BIG-bench 首选度量里至多 5 个显示涌现;
92% 的主张落在两个阈值型度量上);③ 分辨率不足;④ ~10⁶ 个三元组的 p-hacking 面。
未确立:不是"涌现从不真实"(他们自己明说);不是"锐变不可能"。 ★ 注意 NeurIPS 官方奖项页写的是 "Outstanding Paper",不是"最佳论文"。
- ★★ Wei et al. 原文自己就承认了度量解释 (附录 A.1:"We find that all six BIG-Bench tasks fall under Outcome 2" —— 即交叉熵平滑改进而 EM/BLEU/accuracy 停在随机水平)。 但其 §5.1 的 steelman:*"using evaluation metrics that do not give partial credit are at best an incomplete explanation*"。所以不是一边倒。
- ★★★ 最重要的反证:Zhao et al. [2502.17356] 他们构造了一个可证 Lipschitz 连续的度量(逐 token 最大损失的 token 均值 —— 有限个 Lipschitz 函数取 max 仍 Lipschitz), 结果:*"the distribution of this metric across random seeds is still clustered… emergent capabilities exhibit bimodal distributions even when using a continuous performance metric."* MMLU 的 NLL 双峰,Hartigan Dip Test p<0.001。 -> 有些离散的东西是真的,但它在「跨随机种子的分布」层面,不在均值上。
- ★★★ grokking 的机制否掉了"突然"(Nanda et al. [2301.05217]): 三阶段 = 记忆 -> 电路形成 -> 清理。原文: *"the sudden transition to perfect test accuracy in grokking occurs during cleanup, after the generalizing mechanism is learned."* 而且他们的进度度量(restricted/excluded loss)在 grokking 之前连续改进。 -> 跳变发生在"清理"阶段,而机制早就形成了。
- 哲学定性(Krakauer/Krakauer/Mitchell [2506.11135] 最有用): ML 的"涌现"至多是 Chalmers 的弱涌现(相对于某个外推族的意外), 而在 Schaeffer 分析的场合里不满足 Bedau 的不可压缩性判据 —— 因为宏观曲线正是微观平滑量的一个可压缩的确定性变换。 他们的操作性规则:*"the term emergence… should be reserved for the combination of successful task performance and the associated new coarse-grained representations formed within the responsible structure"*。 标题即结论:"Emergent Capability Is Not Emergent Intelligence."
二、★★★ 对我们的可执行测量规则(按性价比排序,[L] = 先做)
A. 让度量造不出跳变
- [L] 阈值型度量永远不能当主要证据(exact-match / accuracy / pass@1 / "每步都对" / MC-grade 都是阶跃函数)。可以报,但必须与底层量并排。
- [L] 主度量用似然型:目标续写的平均逐 token NLL + ★ 逐 token 最大损失的 token 均值(可证 Lipschitz 连续, 正是 Zhao 等用来证明"双峰不是阈值造成的"那个度量)。 这一个选择就化解掉整场 Schaeffer 之争。
- 能力要报两次:固定 k 的 pass@k(能力)与 pass@1(可靠性)。混起来就是假涌现。
小 p 时用 PassUntil(采样到 r 个通过,报
PU = r/K,负二项 MLE,近无限分辨率)。 - 多步任务设计上就给部分分(逐步正确率 + 对了多少步),让复合误差可见。
B. 别再画单次运行的均值
- [L] 每个配置 n ≥ 10 个种子,并把逐种子原始点画出来,不只画均值。 ★ "是不是跳变"这个问题本身就是关于分布的。
- [L] 每个配置做一次模态检验(Hartigan Dip Test,或 KDE + 自助法数峰数)。 "连续度量下仍双峰"是唯一便宜的、能活过 mirage 批判的证据。
- 报区间不报点估计(比例用 Wilson/Clopper–Pearson;分组题用聚类稳健标准误; 配对到题目层面,绝不用两个聚合数相减)。
- 跑之前做功效分析。N=200 题 -> 0.5% 分辨率;N=20 题 -> 5%, 这时任何"涌现"都在误差棒里。
C. 诚实呈现曲线
- [L] 每条曲线都画线性轴与对数轴两种,并说明结论依赖哪一种。 对数轴掩盖跳变,线性轴掩盖平滑的尾部进展 —— 两边各有一次合法命中。
- 拟合函数形式并报平滑度统计量(最大局部斜率/值域),别只说"很尖"。
- 扫第二个控制变量(轮数、数据量、内存、打断率)。跳变位置随检查点漂移 => 是预算/双下降产物。
D. 买机制证据,不买曲线形状
- [L] 在声称不连续之前,先找连续进度度量。 模板:Barak et al. 的权重移动量/Fourier 间隙;Nanda et al. 的 restricted/excluded loss —— 白盒标量单调上升,而黑盒度量平坦。 对我们的做法:在每个检查点上线性探针那个你认为承载行为的表征。 探针平滑 + 行为后跳 => 那是读出/竞争事件,就这么说。
- 优先因果检验而不是曲线形状(Omnigrok 能诱发也能消除 grokking; Varma 等预测并验证了 ungrokking)。
- 跟踪步级"隐藏进展"(首次失败前解对的比例;逐步最大损失)。 端到端平台期 + 步级损失在降 = 复合误差,不是新能力。
E. 设计护栏
- [L] 冻结并消融 harness。 对一个可打断智能体, 打断策略、重试预算、温度都是 harness。CurveShift [2608.00355]: 难题上的增益 "cannot be assigned to the model or its scaffold"。 -> 把 scaffold 当一个因子去变,报它的主效应。
- 难度要外生锚定(人工评分、留出生成器、固定题库的 IRT/Rasch), 否则"难题上的进步"有一部分只是天花板效应的改述。
- 预注册主度量、对照与停止规则。若扫 k 个度量 x m 个任务,报出 k·m 并做多重比较校正。
- 利用输出等价性:原始输出只存一次,离线用任意度量重打分 —— 零成本且结论不可辩驳。
- 在一个"不可能有这个能力"的模型上做 sanity check(随机初始化;不可能的任务)。
F. 语言纪律(免费,而且它改变你去找什么)
- 说"度量 M 在规模 S 处发生了锐变",不要说"能力 X 涌现了"。 "涌现"一词留给至少满足一条的主张: · 连续度量下逐种子双峰 + 通过模态检验; · 识别出一个屏蔽掉微观权重的粗粒化内部变量; · 相对预注册外推的预测性意外。 用"相变"就先说清序参量与控制参数。
★ 一句话分诊: *这个变化在「对逐 token 误差 Lipschitz 连续」的度量下还看得见吗? 它在逐种子上看得见,还是只在均值上?有没有一个内部连续进度度量预告了它?* 三个都否 -> 是度量。任一是 -> 有真东西要解释,而且你知道是哪一种。
三、★ 一条可以立刻用我们自己的数据检验的假说
我们有那个"100% 突然掉到 25%"的现场(big_c1 单头 vs v2head 双头)。
按上面 A2 + B5 + B6,正确的问法是:
把同一配置跑 n ≥ 10 个不同种子,看 β→0 之后的到位率是 (a) 每个种子一个固定值、种子之间分成两簇(-> Zhao 式双峰,真现象) (b) 每个种子内部就抖动(-> 只是噪声/评估方差) (c) 所有种子都平滑下滑(-> 就是连续的,之前的"崩"是阈值度量的错觉)
★ 这与 §26 那次检验不同:§26 只跑了 50 步(还在陡升期), 这次要跑到 β=0 之后曲线平下来,并且跨种子。 这是"涌现"主题唯一还欠我们的实验,而且它同时回答"RL 摧毁模仿是不是真的离散"。
四、意识:定稿要点(子代理完整报告已存)
· 没有任何单一有效的机器意识检验,文献自己就这么说
(Butlin 的免责声明、Koch 的校准/迁移批判、Schwitzgebel 的不可知论证)。
· 唯一真实的清单是 Butlin/Long et al. 的 14 条指标属性(5 个理论),
但它是可信度更新,不是测试;Koch [2603.27597] 指出赋值无法校准、
生物->硅的迁移无独立支持。-> 诚实输出是相对建筑排名,不是概率。
· ★★ 可辩护的可测构念是 meta-d'(Type-2 元认知敏感度),不是"意识";
ECE/Brier 把"知道多少"和"知道得准不准"混在一起。
★ 必须用 0–20 置信度刻度(0–100 时 >78% 答案挤在三个整数上)。
· ★★ 唯一有已发表先例的因果协议:no-rewire 自我模型损伤双分离
(损伤掉元认知校准、保住一阶任务)。同篇阴性结果:
PCI-A 在瓶颈下反而下降 -> IIT 系代理指标不能搬。
· 不要建在 Φ/IIT 或 FEP-as-metaphysics 上。
active inference 有具体可证伪内容(标准版在 horizon=1 是 Bellman 最优、再长就失败)。
· "自我监控必须坐在决策路径上,不是旁边" ——
Xie [2604.11914]:辅助置信模块 "collapse to near-constant outputs (std < 0.006)"、
决策不受影响。
五、★ 对我们架构的具体含义(这是三份调研的交点) · "全局工作台"(GWT-2/3/4)与"元认知"(HOT-2)是我们缺的两格 —— 而它们与我此前说的"③自我模型 -> ④元认知之间缺主动"是同一个位置。 · 但按 Koch 的批判,不要为了"上清单"去做它;要做的是 可测的功能后果(meta-d' 双分离),并把结论写成机制声明而非意识声明。 · active inference 那条"horizon>1 就失败"是唯一可以立刻拿来做判据的理论预测。
六、LNN:定稿(已在本会话落地)
· 留在 ncps CfC,不换。 没有更好的、还保留连续时间/可打断特性的替代。
所有候选在维护性上都更差(raminmh/CfC 自 2022 死;LRC 8★;haiku_CfC 2★;
flaxoil 转私有;LTC-SE 不在 PyPI;LTCNN 2022 孤儿)。
· ★★ 生态定性:作为库生态已僵死,作为研究小生境还活着。
ncps 2351★ 但最后一次合并 PR = 2024-08-14(25 个月前);
HF 上 ltc 标签 0 个模型、ncps 标签 2 个且都是 0 下载;
"CfC network" 全文 0 命中;TorchRL/SB3/RLlib/mctx/Gymnasium 全 0。
★ 对比:LTC 论文 HF 3 个赞 vs Mamba 152 个。
· ★★ 两条对我 brief 的纠正(已接受):
① 不存在 lucidrains 那条线 —— 枚举其全部 400 个公开仓库,
liquid|ltc|cfc|circuit 零匹配;lucidrains/liquid-neural-networks 是 404。
ncps 纯粹是 mlech26l + raminmh。
② "Liquid AI 还在推液态网络"是品牌错觉 —— LFM2 技术报告
(作者含 Hasani、Lechner)写的是 *"gated short convolutions with a small
number of grouped query attention blocks"*,没有 LTC/CfC。
· ★★★ 本会话最重要的落地:ts 逐样本时间
ncps 的 timespans 在 batch>1 时是坏的(issue #83,修复 PR #85 仍未合并),
且 B==units 时静默算错。但 cell 级传 (B,1) 是好的、无需 fork。
我已实现并加了三条自检(core/models.py):
常量 ts 下 (B,1) 与标量差 0.00e+00(等价)
逐样本 ts 下样本间输出差 1.8093(真的生效)
(B,) 形状被守卫挡住
★ 并修正了 core/models.py 里那条过严的结论(原文"LTC 只能接受标量 ts")。
★★★ (B,) 是"只在你想用它的时候才坏"的 bug:
常量 ts 下它和正确路径完全一样(差 0.0),
一旦真传逐样本不同的 ts(那正是用它唯一的理由),差 0.4243 静默算错。
> 规矩:形状错误若只在"常量"下被检验,就等于没检验。
七、★ 顺手修掉的一个"检查器自己有 bug"
tools/check_quotes.py 第一版用 line.split("#", 1)[0] 剥注释再数引号,
但某行有 # 在字符串内部((issue #83)),于是把 #83)") 当注释砍掉,
报成"引号不成对" —— 而那一行完全合法。差点让我去改一段正确的代码。
> ★★ "检查器自己有 bug"是最难发现的一类 —— 它的输出看起来在指控被测对象。
> 规矩:检查器报错时,先验证检查器本身的判据。
已改用 Python tokenizer(分词通过 = 引号全对),全仓复扫 0 假警。