TreeHeap 的存在性证明:结构闭包、子结构搜索和前缀压缩
上一篇 SPR-016 说明了一件事:
TreeHeap 不是要推翻机器学习。
TreeHeap 只是把机器学习接到一种高维可寻址结构上。
所以它和 Transformer 在大范式上是一样的:
固定数学算子
+ 可学习参数
+ loss
+ gradient
+ update
Transformer 里:
matmul / softmax / residual add 是固定算子
Wq / Wk / Wv / FFN 是参数
TreeHeap 里应该是:
plus / mod / heap address / kernel_search 是固定算子
arr.value / primitive basis / world model slots 是参数
这会带来一个非常尖锐的问题:
如果学习范式一样,TreeHeap 凭什么存在?
这个问题不能靠口号回答。 它必须靠实验回答。
TreeHeap 的存在性不应该是:
它和 Transformer 完全不同。
而应该是:
在某些结构任务上,TreeHeap 因为显式结构地基,
比普通序列模型更省样本、更能外推、更可解释。
所以这篇文章规划三组 proof 实验。
实验 A:结构闭包和长度外推
实验 B:子结构 kernel 搜索
实验 C:前缀压缩和延迟坍缩
如果这三组实验都失败,TreeHeap 就很可能只是一个复杂包装。
如果其中一两组成立,TreeHeap 就有自己的位置。
实验 A:结构闭包和长度外推
要证明什么
实验 A 要证明的是:
TreeHeap 连续执行 plus 后,仍然是 TreeHeap。
也就是:
H0
plus p0 -> H1
plus p1 -> H2
plus p2 -> H3
...
每一步都保留同一种对象形态:
TreeHeapState = {
arr
root = arr[0]
cursor
base
summary
}
这叫闭包。
闭包不是语言能力。 闭包是数学地基。
如果一个系统每执行一步,结果就不再属于原来的对象空间,那么后面就很难稳定组合。
具体怎么操作
先固定一个最小 TreeHeap 规则:
plus(H, p):
target = (cursor + 1) mod base
arr[target] = p
cursor = target
summary = summarize(arr)
return H
然后生成训练样本。
输入:
[p0, p1, p2, ..., pn]
执行固定 plus 得到标准答案:
H0, H1, H2, ..., Hn
接着问模型几个问题。
Q1: 第 t 步写入的 target address 是什么?
Q2: 当前 arr[k] 里是谁?
Q3: base 满后,哪个旧节点被覆盖?
Q4: root 的左子树/右子树分别有哪些 primitive?
Q5: summary 是否能恢复某个局部结构?
训练时只给短序列。
base = 8
train length <= 8
测试时给更长序列。
test length = 16, 32, 64
如果 TreeHeap 真的把闭包规则放在结构地基里,那么长度变长时不应该突然崩掉。
对比谁
需要至少四个模型:
1. rule TreeHeap
固定 plus,作为上界/标准答案
2. TreeHeap-readable model
输入输出都保留 arr/cursor/base/summary
3. flatten MLP
把状态压平成向量
4. small Transformer
把 primitive 当序列处理
这里的关键不是让 TreeHeap 赢过所有大模型。
关键是:
在小模型、小数据、长外推场景下,
TreeHeap 是否因为结构地基更稳。
为什么可能泛化更好
普通模型如果没有显式结构,需要自己从样本里学:
计数
位置
取模
覆盖
读取
它在训练里只见过 8 步时,可能只是记住:
第 0 到第 7 步怎么做
但测试到了 32 步,它未必自然知道:
第 32 步仍然应该按 mod base 折回。
TreeHeap 不需要学这个。
因为:
mod 是固定地基
cursor 是显式状态
arr 是显式地址空间
plus 保证 TreeHeap -> TreeHeap
所以模型主要学的是:
arr 里的值如何表示
summary 如何读出
而不是从零学习地址系统。
判断指标
实验 A 的指标:
address accuracy
read accuracy
overwrite accuracy
subtree read accuracy
length extrapolation accuracy
sample efficiency
最重要的是:
train length <= 8
test length = 16/32/64
如果 TreeHeap 在长长度上明显更稳,说明结构闭包有价值。
实验 B:子结构 kernel 搜索
要证明什么
实验 B 要证明的是:
TreeHeap 可以像卷积一样,在结构空间里搜索局部模式。
一维卷积搜索的是数组窗口:
[1, 0, 1]
TreeHeap 搜索的是子树或地址窗口:
A
/ \
B C
也可以写成:
[arr[i], arr[left(i)], arr[right(i)]]
具体怎么操作
先定义一个 pattern kernel:
K = root(A, left=B, right=C)
生成很多 TreeHeap。
一部分包含这个 pattern:
exists i:
arr[i] = A
arr[left(i)] = B
arr[right(i)] = C
另一部分不包含。
注意 pattern 要出现在不同地址:
arr[0]
arr[1]
arr[2]
arr[5]
arr[10]
任务:
判断 TreeHeap 里是否存在 K。
TreeHeap 方法:
for each address i:
sub = subheap(H, i)
score[i] = match(sub, K)
answer = max(score)
这就是 TreeHeap 版的卷积搜索。
对比谁
对比模型:
1. TreeHeap kernel_search
2. flatten MLP
3. sequence CNN
4. small Transformer
训练集可以故意限制 pattern 出现位置:
train positions = {0, 1, 2}
测试集放到新位置:
test positions = {6, 10, 13}
这样可以检查模型学的是:
绝对位置
还是:
结构模式
为什么可能泛化更好
如果 pattern 的本质是结构:
A -> (B, C)
那么它出现在 arr[1] 和出现在 arr[10] 应该是同一种局部模式。
TreeHeap kernel_search 的优势是:
同一个 kernel 可以在不同结构地址复用。
这和 CNN 的优势类似:
卷积核在不同像素位置复用。
区别是:
CNN 在一维/二维网格上滑。
TreeHeap kernel 在树/堆地址空间上滑。
如果普通模型学的是绝对位置,它在新地址上会掉。
如果 TreeHeap 学的是局部结构,它应该更稳。
判断指标
实验 B 的指标:
pattern detection accuracy
new-address generalization
new-depth generalization
false positive rate
hit@1 / hit@k
kernel interpretability
training samples needed
最关键的是:
同一个 pattern 出现在训练没见过的新地址时,
TreeHeap 是否仍然能识别。
如果成立,TreeHeap 的子结构搜索就有存在性。
实验 C:前缀压缩和延迟坍缩
要证明什么
实验 C 要证明的是:
TreeHeap 的路径前缀可以带来压缩和候选复用。
这里可以类比 Huffman 编码和 trie。
Huffman 编码里,高频对象用短码,低频对象用长码:
A = 0
B = 10
C = 110
D = 111
这些编码有一个重要性质:
前缀不冲突。
Trie 也类似。
例如很多字符串:
the red ball
the red car
the red cup
可以共享前缀:
the -> red -> {ball, car, cup}
TreeHeap 如果有路径结构,也天然存在前缀:
root
root-left
root-left-right
这意味着:
共享前缀可以共享计算、共享存储、共享概率。
具体怎么操作
构造一批有共享前缀的结构序列:
A B C X
A B C Y
A B D X
A B D Y
A E F X
普通序列会把它们当成五条样本。
TreeHeap/trie-like 表示可以压成:
A
├─ B
│ ├─ C
│ │ ├─ X
│ │ └─ Y
│ └─ D
│ ├─ X
│ └─ Y
└─ E
└─ F
└─ X
这时可以做三类任务。
C1:压缩效率
比较:
普通序列总 token 数
TreeHeap 前缀共享后的节点数
指标:
node_count
description_length
bits_per_sample
compression_ratio
prefix_reuse_rate
如果共享前缀很多,TreeHeap 应该更省。
这不是语言理解。 这是结构压缩。
C2:候选概率容器
给定前缀:
A B C
后面可能是:
X or Y
TreeHeap 可以在前缀节点上保存候选:
A-B-C -> {
X: 0.5
Y: 0.5
}
这就是概率容器。
它不急着坍缩。
后面如果出现额外上下文,再更新:
context says X
P(X) -> 0.9
P(Y) -> 0.1
最后再坍缩。
这对应我们之前一直说的:
不要在信息不足时过早 argmax。
C3:新分支适应
训练见过:
A B C X
A B C Y
测试或增量学习时出现:
A B C Z
如果模型学到了前缀结构,它应该知道:
A B C 是一个已知有效前缀。
Z 是这个前缀下的新分支。
它不需要从零学习整条路径。
这可以测试:
new-branch adaptation speed
也就是加入少量 Z 样本后,模型多快能适应。
为什么可能有效
Transformer 当然也能学前缀。
但 Transformer 通常不会显式把前缀变成共享结构对象。
TreeHeap 如果设计正确,可以直接复用:
共享节点
共享 summary
共享概率容器
共享局部 kernel
这可能带来:
存储压缩
计算复用
候选复用
更慢坍缩
更快新分支学习
这就是实验 C 的价值。
判断指标
实验 C 的指标:
compression_ratio
prefix_reuse_rate
probability calibration
delayed-collapse accuracy
new-branch adaptation speed
negative log likelihood
最关键的是:
TreeHeap 是否能利用共享前缀,
减少存储/样本需求,
并在歧义未消失前保留候选。
三个实验放在一起看
这三组实验分别测不同维度。
| 实验 | 测什么 | 如果成立说明什么 |
|---|---|---|
| A 结构闭包 | 长度外推、地址读写、mod fold | TreeHeap 的显式地址地基有用 |
| B 子结构搜索 | 局部 pattern 在新位置复用 | TreeHeap kernel 像结构卷积一样有效 |
| C 前缀压缩 | 前缀共享、候选保留、新分支适应 | TreeHeap 路径结构有压缩和概率容器价值 |
它们共同回答一个问题:
TreeHeap 是否只是 Transformer 的复杂包装?
如果 A/B/C 都不成立,那么答案可能是:
是,它没有必要存在。
如果 A/B/C 至少成立一部分,那么 TreeHeap 的存在性就变成:
它不是因为学习范式不同而存在。
它是因为结构归纳偏置不同而存在。
下一步工程顺序
我建议不要一起做大实验。
先做最小 proof。
Step 1: A1 address closure
train length <= 8
test length = 16/32/64
Step 2: B1 fixed kernel relocation
train pattern positions = {0,1,2}
test pattern positions = unseen addresses
Step 3: C1 prefix compression accounting
不训练模型,先算 node_count / compression_ratio
Step 4: C2 probability container
在共享前缀节点上保留候选分布
Step 5: C3 new branch adaptation
比较新增 Z 分支需要多少样本
每一步都要有 baseline:
flatten MLP
sequence CNN
small Transformer
rule TreeHeap upper bound
每一步都要输出 evidence:
summary.json
README.md
trace.jsonl
一句话
TreeHeap 的存在性不是证明它“也能学习”。
Transformer 也能学习。
TreeHeap 要证明的是:
显式可寻址结构
+ 子结构 kernel
+ 前缀共享路径
+ 延迟概率坍缩
能不能带来:
更少样本
更长外推
更强结构复用
更高压缩率
更清楚的中间状态
这才是下一阶段真正要 proof 的东西。
License: GPLv3