昨晚为什么没有正式训练
昨晚我们原本准备启动一轮长训练。最后 GPU 没有进入正式任务,不是基础设施故障,也不是因为害怕实验失败,而是预注册的 smoke gate 阻止了它。
这次 gate 做了它应该做的事:在几分钟内告诉我们,当前结构虽然已经能够施加“压缩压力”,但还没有充分学会“有限空间里应该保存什么”。如果在这个状态下直接训练一夜,我们更可能得到一个更熟练的语言捷径,而不是更可靠的 TreeHeap 私有协议。
这篇文章把 D07、D07R1 和 D07R2 三轮实验放到一张图里,解释我们已经解决了什么、失败在哪里,以及下一步为什么要从“自由查询”转向“结构覆盖”。
1. 先区分两个问题
前一阶段的 D06 已经做出了一个可工作的压力板:递归深度越浅,可使用的协议槽位越少;递归深度越深,可使用的槽位越多。
若完整深度为 D=7,输入有效长度为 L,深度 d 的容量近似为:
B(d) = max(2, ceil(L * 2^(d-D)))
d=5 -> 约 1/4 容量
d=6 -> 约 1/2 容量
d=7 -> 完整容量
这解决的是容量控制:我们已经可以把一块板压成四分之一、二分之一或完整大小。
但容量控制不等于语义压缩。给模型四个槽位,并不会自动让四个槽位分别学会“人物、动作、对象、时间”。模型也可能把四个槽位都用来保存同一类高频信号。
所以 D07 研究的是第二个问题:
在容量受限时,梯度能否自己形成 Encoder 与 Decoder 共同理解的私有协议?
2. D07 的数据流到底是什么
D07 没有人工提供缩句、语法标签或目标前缀。它只把源句写入冻结的 source TreeHeap,然后允许若干个 query 从 root 出发,递归读取左右子堆,形成有限数量的协议槽位。
source sentence
-> frozen source TreeHeap H
-> recursive READ queries
-> B(d) protocol slots
-> recursive FOLD into a protocol TreeHeap
-> shared recursive READ / decoder
-> reconstruct the full target sentence
训练目标仍是完整目标句的 token 交叉熵。目标 token、目标长度和参考译文都不能进入压缩器,也不能参与容量计算。
因此,这不是把正确答案偷偷截短后交给模型。它是一项最小的码率-失真试验:
递归深度 d -> 可用容量,也就是码率
完整句 NLL -> 重建误差,也就是失真
如果它成功,梯度应该在有限槽位中形成某种可读协议。我们不预先规定协议必须长得像人类语法,只要求它确实携带输入信息,并且能帮助 Decoder。
3. 三把因果尺子
只看训练 NLL 下降是不够的。Decoder 即使完全忽略输入,也可能通过学习目标语料的高频词和常见句式降低 NLL。
因此我们固定同一个测试集,做三种读法:
| 读法 | 操作 | 它在检查什么 |
|---|---|---|
native |
使用当前样本自己的协议槽位 | 正常路径 |
shuffle |
换成另一个样本的槽位 | 协议是否保存了“这是哪个输入” |
zero |
把所有协议槽位置零 | 协议总体上是在帮助还是干扰 Decoder |
指标写成:
delta_shuffle = NLL(shuffle) - NLL(native)
delta_zero = NLL(zero) - NLL(native)
正数表示干预使结果变差,也就是 native 协议具有正向贡献。
预注册门槛要求:至少两个深度中,delta_shuffle 和 delta_zero 都不小于 +0.10。这个门槛不神圣,但它是在看结果之前写下的,不能因为结果只差一点就临时修改。
4. 第一轮:NLL 大降,却是语言捷径
D07 训练了 120 steps。三个深度的 valid NLL 都大幅下降:
| depth | 初始化 NLL | 训练后 NLL | 下降 |
|---|---|---|---|
| 5 | 21.865 | 8.291 | 13.574 |
| 6 | 23.473 | 8.006 | 15.467 |
| 7 | 25.018 | 7.987 | 17.030 |
如果只看这张表,实验似乎非常成功。但因果干预给出了相反答案:
| depth | delta_shuffle |
delta_zero |
|---|---|---|
| 5 | +0.060 | -1.902 |
| 6 | +0.056 | -1.523 |
| 7 | +0.067 | -1.513 |
zero 反而比 native 好很多。这说明协议槽位不是 Decoder 的有效信息源,而是干扰源。NLL 的下降主要来自可训练 Decoder 学会了目标语料的边际分布。
本科生可以把它理解成一次闭卷考试:
我们以为学生在读题;
但把题目拿走以后,学生分数反而更高;
说明学生主要是在背答案分布,题目本身还会干扰他。
所以第一轮不能证明私有协议。
5. 第二轮:冻结语言捷径,输入身份出现了
D07R1 冻结了继承的语言骨架,只允许压力协议两端的递归映射学习。这样 Decoder 不能再通过修改词频输出层独自降低损失。
训练 300 steps 后:
| depth | delta_shuffle |
delta_zero |
|---|---|---|
| 5 | +0.587 | -1.440 |
| 6 | +0.618 | -1.360 |
| 7 | +0.617 | -1.358 |
这一次 shuffle 明显变差。它证明槽位不是常量,也不是完全相同的词频模板:槽位已经携带了“当前输入是谁”的样本相关信息。
但是 zero 仍然更好。也就是说,槽位里虽然有信息,但它进入冻结 Decoder 时的整体坐标或幅度不合适,干扰大于帮助。
这像是收到了一封确实属于你的加密邮件,但直接把密文当正文显示。寄件人身份对了,内容接口却没有对齐。
6. 第三轮:小流量接入,方向终于变正
D07R2 没有改变数据、容量公式、FOLD 或损失,只在协议进入 Decoder 前增加一个所有深度共享的有界增益:
gain = sigmoid(a)
slot_used = gain * slot
增益从约 0.0180 开始,训练后为 0.0204。这相当于先用很小的流量接入旧 Decoder,让两边逐步建立坐标关系,而不是第一步就用满幅状态覆盖旧参考系。
600 steps 后,因果符号第一次全部转正:
| depth | delta_shuffle |
delta_zero |
|---|---|---|
| 5 | +0.096 | +0.036 |
| 6 | +0.139 | +0.071 |
| 7 | +0.142 | +0.064 |
这张表可以支持两个有限结论:
- 打乱样本会变差,协议包含输入身份信息;
- 清空协议也会变差,协议开始对 Decoder 产生正向贡献。
但 zero 损失只有 +0.036 到 +0.071,没有达到预注册的 +0.10。因此严格结论仍然是:
smoke_blocks_formal
这不是“差一点就算通过”。它表示方向修正了,但信号还太弱,不值得立即投入一夜长训练。
7. 为什么深度增加没有带来可见的新信息
D07R2 中,深度 5、6、7 的可用槽位数量不同,理论上应该对应不同码率。但自由生成样例几乎相同,BLEU4 都约为 0.642,没有出现我们期待的“深度增加后细节逐渐补全”。
训练日志还给出了一条重要线索:递归 READ 的分支熵在若干训练阶段迅速接近 0。熵接近 0 表示左右选择变得极其确定,query 不再同时探索多个候选分支。
已经观察到的事实是:
- 不同深度生成几乎相同;
- 增加容量带来的 NLL 边际收益很小;
- 部分递归分支熵接近 0;
shuffle损失明显大于zero损失。
当前最合理、但尚未被直接证明的推断是:
多个自由 query 可能收敛到了少数相似路径或相似子堆。它们能携带样本指纹,所以 shuffle 有明显影响;但新增槽位重复读取相近内容,所以清空全部槽位造成的净损失仍然很小,深度之间也没有形成分辨率差异。
这里必须诚实地保留“可能”。当前日志只测了每步分支熵,没有直接计算不同槽位之间的路径重叠率。因此我们还不能写成“已经证明所有槽位读取同一个节点”。
8. 下一步:从自由竞争改为结构覆盖
当前每个槽位都像一名自由记者:大家可以去整棵树的任何地方采访。梯度会把所有记者派往最容易降低 NLL 的热门地点,却没有动力保证有人覆盖其他区域。
下一步候选不是给槽位写入“主语、谓语、宾语”等人工语义,而是给它们最小的 TreeHeap 地址责任:
depth 5: 少量槽位,各自负责较大的 subheap
depth 6: 更多槽位,各自负责更小的 subheap
depth 7: 继续细分 frontier,覆盖更细的地址区域
每个槽位只能在自己的 subheap 内使用同一个共享 READ kernel 学习压缩。也就是说:
结构先验只规定“去哪里读”
梯度仍然决定“在那里保留什么”
这和 flat array 切片不同。分区依据的是递归 TreeHeap 地址与 subheap frontier;不同深度的分区由同一棵树递归细化,局部读取仍共享同一组 kernel 参数。
它也不是提前定义语言含义。某个槽位最终保存动作、对象、时序还是别的隐态,仍由完整目标重建损失决定。
9. 新候选必须怎样被证明
下一轮不能只看 NLL。至少要提前登记四组指标:
- 覆盖率:有多少 source leaf 被至少一个槽位的主要路径覆盖;
- 重叠率:不同槽位的路径或终点有多大比例重合;
- 输入因果性:继续比较 native、shuffle 和 zero;
- 容量边际收益:新增槽位是否带来新的 NLL 收益与可见生成差异。
还需要两个重要对照:
| 对照 | 目的 |
|---|---|
| 自由 query | 判断结构 ownership 是否真的减少重复读取 |
| 随机打乱 ownership | 判断收益来自 TreeHeap 邻接结构,还是仅仅来自把槽位强行分开 |
只有当“结构覆盖”同时降低槽位重叠、提高 source 覆盖,并让 native 对 zero 的优势稳定超过预注册门槛,才允许进入正式长训练。
10. 当前航线结论
D07 三轮实验没有证明 TreeHeap 私有协议已经形成,但它排除了三个容易混淆的故事:
NLL 大降,不等于输入协议形成;
槽位包含样本信息,不等于槽位对 Decoder 有帮助;
增加槽位数量,不等于增加了互补信息。
我们现在可以更准确地描述工程状态:
递归深度压力已经能限制容量;有界增益已经让协议贡献从负转正;尚未解决的是有限槽位如何分工覆盖 TreeHeap,并在容量增加时带来互补信息。
所以昨晚没有正式训练,是一次有效停止。船没有停在原地,我们只是确认下一步应该修方向分配,而不是继续给同一套 query 增加燃料。
完整 Claim、代码与 Evidence 位于 SameTime 开放仓库,对应 D07、D07R1 与 D07R2 记录。
作者说明: TreeHeap 的递归深度压力、有限协议槽位与结构覆盖候选来自 Houming818 与 Codex 的共同讨论。本文公开成功、失败、推断边界与下一步证伪条件,供读者复现和审计。
License: GPLv3。