Browse this library

Chinese source article

5.2.1 · LaCT 与 TTT-E2E

TTT layer 之后的两条改法: LaCT 把内循环块从 16 个 token 放大到 2K 到 1M, 用窗口注意力补局部依赖, 把 GPU 利用率提到 70%; TTT-E2E 干脆不要专门的 TTT 层, 在滑动窗口 Transformer 的后 1/4 块 MLP 上直接做下一个 token 预测的梯度更新, 再用元学习训练初始化.

View original Markdown ↗

1. 问题与 LaCT 的大块更新

问题: 5.1 留下的两个缺口. TTT layers 与 fast weights 的 TTT layer 留下了两个问题.

第一个是硬件. mini-batch 大小 b=16b = 16 时, 每 16 个 token 就要做一次 fast weights 的更新, 中间还要读写 fast weights. 加上 dual form, TTT-Linear 能跑, TTT-MLP 仍被内存 I/O 卡住. 更大的非线性 fast weights 在这个块大小下几乎无法高效实现.

第二个是目标. TTT layer 的内循环在每一层上各自做重建 (式 (2) 的 key-value 重建), 外循环再用下一个 token 预测训练整个网络. 内循环学的东西和最终任务之间, 隔着一个由外循环学出来的投影 θK,θV\theta_K, \theta_V.

LaCT 处理第一个问题, 方向是把块放大到几千个 token 以上. TTT-E2E 处理第二个问题, 方向是让内循环直接优化网络输出端的下一个 token 预测损失. 两篇的作者有交集 (Songlin Yang 是 LaCT 作者, 也是 DeltaNet 和 Gated DeltaNet 的作者; TTT-E2E 与 TTT layer 论文有 Dalal, Li, Sun 等多位共同作者), TTT-E2E 把 LaCT 当作自己推导的起点, 叫它 TTT-KVB (Key-Value Binding).

硬件成本. LaCT (Zhang, Bi, Hong, Zhang, Luan, Yang, Sunkavalli, Freeman & Tan, 2025) 来自 MIT 和 Adobe Research, 论文题目是 Test-Time Training Done Right. 它的起点是一个测量: 以前的 TTT 层每 16 或 64 个 token 更新一次 fast weights, GPU 的 FLOPs 利用率常低于 5%. LaCT 改成每 2048 到 1M 个 token 更新一次, 不写定制 kernel, 纯 PyTorch 实现在 A100 上利用率最高到 70%.

LaCT 先用一个式子说明小块为什么慢. 考虑一个 h×hh \times h 的 fast weight 矩阵和一个 b×hb \times h 的块输入做矩阵乘, BF16 下每个数 2 字节. 计算量是 2h2b2h^2 b 次浮点运算, 访存量是两个输入矩阵加一个输出矩阵 2h2+4hb2h^2 + 4hb 字节. 计算与访存之比:

r=2h2b2h2+4hb=b1+2bh≤min⁡(h2, b)(1)r = \frac{2h^2 b}{2h^2 + 4hb} = \frac{b}{1 + \frac{2b}{h}} \le \min\Big(\frac{h}{2},\ b\Big) \tag{1}

H100 达到峰值算力所需的比值约为 290 FLOPs/字节, 低于它就是访存受限. 代入几组数:

hh bb r=b/(1+2b/h)r = b/(1 + 2b/h) 状态
64 16 16/1.5=10.716/1.5 = 10.7 严重访存受限
64 2048 2048/65=31.52048/65 = 31.5 被 h/2=32h/2 = 32 封顶
512 2048 2048/9=227.62048/9 = 227.6 接近峰值
1024 2048 2048/5=409.62048/5 = 409.6 计算受限

第一行是以前 TTT 层的典型配置. 第二行说明只放大块不够, fast weights 也要大; 第三, 四行说明块和 fast weights 同时放大, 比值才能接近或超过 290. 以前的工作为了在小块上跑快, 写定制 kernel 把 fast weights 留在 SRAM 里, 这要求 fast weights 在各个 SM 内基本独立演化, 对大的非线性 fast weights 和 Muon 这类需要全矩阵运算的更新不成立.

更新与应用. LaCT 沿用 TTT 的两个操作. 设 token 投影出 qi,ki,vi∈Rdq_i, k_i, v_i \in \mathbb{R}^d, fast weights 网络为 fWf_W.

更新操作在整块 bb 个 token 的损失和上求一次梯度:

g=∇W∑i=1bηi L(fW(ki),vi),W←weight-update(W,g)(2)g = \nabla_W \sum_{i=1}^{b} \eta_i\, \mathcal{L}\big(f_W(k_i), v_i\big), \qquad W \leftarrow \text{weight-update}(W, g) \tag{2}

ηi\eta_i 是每个 token 的学习率, 由输入预测. 应用操作 oi=fW(qi)o_i = f_W(q_i), 块内所有 query 共用同一个更新后的 WW.

fast weights 网络是无偏置的 SwiGLU-MLP, 三个矩阵 W={W1,W2,W3}W = {W_1, W_2, W_3}:

fW(x)=W2[SiLU(W1x)∘(W3x)](3)f_W(x) = W_2\big[\text{SiLU}(W_1 x) \circ (W_3 x)\big] \tag{3}

∘\circ 是逐元素乘. 损失用点积:

L(fW(ki),vi)=−fW(ki)⊤vi(4)\mathcal{L}\big(f_W(k_i), v_i\big) = -f_W(k_i)^\top v_i \tag{4}

与 5.1 的平方误差相比, 点积损失不含 ∥fW(k)∥2\lVert f_W(k) \rVert^2 项, 梯度只朝「让 fW(k)f_W(k) 与 vv 对齐」的方向走, 对 fW(k)f_W(k) 的长度没有约束. fast weights 的幅度要靠下面的归一化来控制.

非线性更新: 归一化与 Muon. fast weights 反复累加梯度, 幅度会爆炸或衰减. 大块意味着更新次数少, 每次更新可以做得更复杂而不拖慢整体. 基础版本是梯度下降后做 L2 归一化:

weight-update(W,g)=L2-Normalize(W−g)(5)\text{weight-update}(W, g) = \text{L2-Normalize}(W - g) \tag{5}

归一化沿输入维度做, 不用显式的权重衰减. 论文给的解释是: 把序列维度看成一个虚拟网络的深度, 每次 TTT 更新是时间上的一个残差, 归一化相当于 Transformer 里的 post-LN, 约束残差路径上的尺度.

Muon 版本把梯度先正交化再更新:

weight-update(W,g)=L2-Normalize(W−Muon(g)),Muon(g)≈UV⊤(6)\text{weight-update}(W, g) = \text{L2-Normalize}\big(W - \text{Muon}(g)\big), \qquad \text{Muon}(g) \approx U V^\top \tag{6}

g=USV⊤g = U S V^\top 是梯度的奇异值分解, Muon 用 Newton-Schulz 迭代近似地把所有奇异值置为 1. 这样 ηi\eta_i 只表示块内 token 之间的相对重要性, 更新的绝对尺度由 Muon 归一化. Muon 只作用在矩阵上, SwiGLU 的三个权重各自处理. 语言建模里还有一个动量版本: M←βM+∑iηi∇WLiM \leftarrow \beta M + \sum_i \eta_i \nabla_W \mathcal{L}_i, 再对 MM 做 Muon.

1.1. 更新与应用的顺序决定了掩码

更新和应用是解耦的, 改变两者的顺序和块大小, 就得到不同的依赖结构. 论文图 3 把它们对应成注意力掩码:

  • 块等于整条序列, 先应用再更新: 相当于全注意力 (双向).
  • 更新和应用交替: 块级因果掩码, 块大小等于 chunk 大小.
  • 交替但先应用后更新 (相对上一种平移一个块): 当前块只看到之前的块, 块内不泄漏未来信息. 语言建模要用这一种.
  • 只在一部分块上更新, 在所有块上应用: 带步长的块级因果掩码. 新视角合成和视频扩散用这一种.

窗口注意力补块内结构. 大块 TTT 的更新对块内 token 求和, 不区分顺序和位置, 块内是一个集合. 文本是一维序列, 视频是网格的序列, 块内的局部结构都很重要. LaCT 在 TTT 层旁边加窗口注意力 (因果或双向), 处理块内的局部依赖, TTT 层的固定容量用于块与块之间的非局部依赖. 所以 LaCT 是一个混合架构: 局部用二次复杂度的注意力, 远程用线性复杂度的 TTT.

语言建模里, 窗口注意力是滑动窗口, 窗口大小等于块大小 (2048 或 4096), 和 fast weights 网络共用 Q, K, V (按 GAU 的做法), 再给 Q, K 加逐通道的缩放和平移.

上下文并行. 大块还带来一个便利. 一个块内的梯度是 token 梯度之和, 可以把块里的 token 切到多张卡上, 各自算梯度, 再全局求和:

g=∑j=1shards∇W∑i=1sηiLi(7)g = \sum_{j=1}^{\text{shards}} \nabla_W \sum_{i=1}^{s} \eta_i \mathcal{L}_i \tag{7}

ss 是每个分片的 token 数. 这和数据并行在形式上相同, 只是「参数」换成了 fast weights, 「数据」换成了块内的 token. 新视角合成的训练用了这种并行, 吞吐开销只有 1% 到 3%. 小块的 TTT 层很难这样切, 只能按 head 做张量并行.

状态大小到底怎样算. LaCT 所说的「状态」指每一层随序列更新的三块 SwiGLU 权重, 与前向过程中暂存的激活分开统计. 设模型维度为 dd, TTT 分成 HH 个 head, 每个 head 的输入维度 dh=d/Hd_h=d/H, SwiGLU 中间维度为 mhm_h. 单层 fast weights 的参数量是

Slayer=H(dhmh+mhdh+dhmh)=3Hdhmh.(8)S_{\text{layer}} =H(d_hm_h+m_hd_h+d_hm_h) =3H d_hm_h. \tag{8}

若令 mh=ρdhm_h=\rho d_h, 则

Slayer=3ρHdh2=3ρd2H.(9)S_{\text{layer}}=3\rho H d_h^2=\frac{3\rho d^2}{H}. \tag{9}

这个式子解释了论文附录里一个容易忽略的选择: TTT head 越少, 单个 head 越宽, fast-weight 状态反而越大. 语言模型默认只用 4 个 TTT head, 与窗口注意力不必使用相同的 head 数. 这和普通多头注意力的直觉不太一样; 普通注意力的投影矩阵总大小大致保持 O(d2)O(d^2), LaCT 的 fast weights 则在每个 head 内独立成网, head 切得越碎, 被 1/H1/H 压掉的二次项越多.

表里的 2304d2304d 也是总状态量, 不是某一个矩阵的宽度. 以论文 3B 配置的模型维度代入后, 它对应各层各 head 的 W1,W2,W3W_1,W_2,W_3 之和. GLA 的 384d384d 和 DeltaNet 的 128d128d 用同一口径统计递归状态, 因而「6 倍」「18 倍」比较的是随序列变化的状态容量, 不包含所有方法共有的静态网络参数.

这里还要分清 状态容量 和 可无损记住多少 token. SS 个浮点数只给出存储通道的规模, 不意味着能按地址取回 SS 个 token. 每块梯度把许多 token 的贡献相加后写进同一组矩阵, 不同 key 的更新会互相干扰; Muon 与 L2 归一化稳定了尺度, 却没有给每条信息分配独立地址. 所以扩大状态通常能改善平均损失, 但不会自动得到 KV cache 那种逐 token 的精确寻址.

一个块究竟何时可见. 把第 jj 块记为 CjC_j, 块开始时的状态为 Wj−1W_{j-1}. 因果语言建模采用 apply-then-update:

Oj=fWj−1(Qj),Gj=∇W∑i∈CjηiL(fWj−1(ki),vi),Wj=Φ(Wj−1,Gj).(10)O_j=f_{W_{j-1}}(Q_j),\qquad G_j=\nabla_W\sum_{i\in C_j}\eta_i\mathcal L(f_{W_{j-1}}(k_i),v_i),\qquad W_j=\Phi(W_{j-1},G_j). \tag{10}

于是 LaCT 分支计算 OjO_j 时只含 C1,…,Cj−1C_1,\ldots,C_{j-1} 写入的状态, 当前块 CjC_j 要到下一块才进入 fast weights. 当前块内部的因果关系由并行的滑动窗口注意力承担. 窗口大小等于块大小并非随手选的超参数, 它刚好补上 fast weights 晚一块生效留下的空档. 如果窗口小于块, 同一块里相距超过窗口的 token 既没有进入旧状态, 又不在局部注意力内, 中间会出现真正的依赖盲区.

这也说明块大小的两面性. 把 bb 从 16 放到 2048, 更新次数从 T/16T/16 降到 T/2048T/2048, 大矩阵乘更容易吃满 GPU; 与此同时, 一次更新混合的 token 增加 128 倍, 状态响应新信息的频率下降. 图像集合的一张图、视频的若干连续帧都有天然块边界, 文本没有. 因此 LaCT 在文本上必须同时依靠更大的非线性状态、Muon 和窗口注意力, 大块本身只解决系统效率, 不负责补回顺序信息.

LaCT 的任务与消融. ### 1.2. 三类任务

论文 Table 1 汇总了三个实验 (状态大小指每个块的 fast weights 大小, dd 是模型维度):

任务 数据结构 chunk 大小 状态大小 模型规模 最大长度
新视角合成 图像集合 整条序列 6d26d^2 0.3B 1M
自回归视频扩散 图像序列 3 帧 3d23d^2, 0.75d20.75d^2 1.3B, 14B 56,160
语言建模 一维序列 2K, 4K 0.75d20.75d^2 0.7B, 3B 32,768

新视角合成. 给定一个静态场景的 NN 张带相机位姿的图, 渲染新视角. 窗口注意力正好覆盖一张图的 token, TTT 层用所有输入图的 token 更新一次 fast weights, 再应用到输入和目标 token 上. 更新阶段相当于 prefill, 应用阶段相当于并行 decode; 渲染新视角时, 每个 TTT 层就是一个静态权重层. 论文 Table 2 在 A100 上用 48 张 512×512 输入 (196K 输入 token, 4K 解码 token) 比较: 全注意力 prefill 16.1 秒, 渲染 2.3 FPS; Perceiver 式注意力 16.8 秒, 34.4 FPS; LaCT 1.4 秒, 38.7 FPS, 质量与全注意力相当. 在 960×536 的场景数据上, 输入较少时质量超过 3D Gaussian Splatting, 一直到 128 张输入 (约 1M token) 仍有竞争力; 对照的 LongLRM 只能处理 32 张.

语言建模. 在 Long-Data-Collections 上训练, 760M 模型 40B token (窗口 2048), 3B 模型 60B token (窗口 4096), 上下文 32,768, RoPE base 取 1M. 对照全注意力, 以及加了同样滑动窗口的 GLA 和 DeltaNet. 3B, 32K, A100-40GB 上的训练吞吐 (token/秒) 与状态大小:

方法 状态大小 吞吐 更新规则
Transformer 随长度增长 4.1K
Transformer SWA 窗口内 6.4K
GLA SWA 384d384d 5.0K St←St−1Diag(αt)+vtkt⊤S_t \leftarrow S_{t-1}\text{Diag}(\alpha_t) + v_t k_t^\top
DeltaNet SWA 128d128d 5.1K St←St−1(I−βtktkt⊤)+βtvtkt⊤S_t \leftarrow S_{t-1}(I - \beta_t k_t k_t^\top) + \beta_t v_t k_t^\top
LaCT GD 2304d2304d 5.0K W←L2norm(W−∑iηi∇WLi)W \leftarrow \text{L2norm}(W - \sum_i \eta_i \nabla_W \mathcal{L}_i)
LaCT Muon 2304d2304d 4.3K 动量 + Muon + L2norm

LaCT 的状态是 GLA 的 6 倍, DeltaNet 的 18 倍, 吞吐相当 (Muon 版慢约 14%). 结果 (论文图 5): 两个规模上, LaCT 在靠后位置的逐 token 损失都低于 GLA 和 DeltaNet, S-NIAH 检索精度也更高; Muon 版始终好于动量版.

自回归视频扩散. 把预训练的 Wan 2.1 文生视频扩散模型 (双向注意力) 微调成自回归模型: 所有双向注意力层换成 LaCT 层加滑动窗口注意力. 序列里交替排列加噪块和干净块, 只在干净块上更新 fast weights, 在每个块上应用, 保证每次去噪只用到已经生成好的帧. 对照滑动窗口注意力单独使用, Mamba 2 加滑动窗口, 以及全块因果注意力. LaCT 的验证损失与全注意力相当, 好于另外两个线性基线. 14B 模型最长生成 56,160 个视觉 token.

消融与局限. 论文在新视角合成和语言建模上做了四组消融 (图 7, 图 8):

  • 状态大小: 越大越好, 两个任务一致. 最大配置每块 12d212d^2, fast weights 合计占模型权重的 40%; 论文统计的以前方法只占 0.1% 到 5%.
  • 优化器: Muon 好于普通梯度下降和动量.
  • 线性对非线性: SwiGLU fast weights 即使状态更小, 也好于线性 fast weights fW(x)=Wxf_W(x) = Wx.
  • 块级递推对逐 token 递推: 新视角合成里, 相同状态大小下线性的大块递推好于线性的逐 token 递推 (双向 Mamba 2). 语言建模里, 线性大块递推 (状态 0.25d20.25d^2, 与 GLA SWA 相同) 一开始不如 GLA SWA, 论文认为是文本没有天然的块结构; 换成更大的非线性状态 (1.5d21.5d^2) 加 Muon 之后, 超过了所有逐 token 递推的基线.

这组结果表明, 对文本而言大块本身是一个劣势, 是靠更大的状态和更好的优化器补回来的.

局限方面, 论文自己列了三条: 任务覆盖仍有限 (新视角合成带位姿输入, 无位姿重建没做); 语言建模受算力限制, 没有测推理能力, 也没有测参数规模的扩展, 而固定状态模型的主要弱点恰好被认为是推理; 视频生成缺少可靠的可扩展性指标, 只报了验证损失.

TTT-E2E: 直接在下一个 token 预测上学. TTT-E2E (Tandon, Dalal, Li, Koceja, Rød 等, 2025) 的摘要第一句是: 把长上下文语言建模表述为持续学习问题, 而不是架构设计问题. 这里的「持续学习」指序列内: 模型读一条很长的上下文时, 一边读一边用读过的部分训练自己, 把上下文压进权重. 读完这条上下文, 状态就丢弃了.

论文先用一个刻意简化的架构说明机制: 把 Transformer 的所有自注意力层去掉, 只留 MLP. 这个模型没有任何历史记忆, 实际上是一个 bigram 模型.

给它记忆的方法是在上下文上训练它. 记网络为 ff, 权重 WW, tt 时刻的下一个 token 预测损失:

ℓt(W)=CE(f(xt−1;W),xt)(11)\ell_t(W) = \text{CE}\big(f(x_{t-1}; W), x_t\big) \tag{11}

CE 是交叉熵. 推理阶段对 t=1,…,Tt = 1, \dots, T 依次做梯度下降:

Wt=Wt−1−η ∇ℓt(Wt−1)(12)W_t = W_{t-1} - \eta\, \nabla \ell_t(W_{t-1}) \tag{12}

模型输出 p^T+1=f(xT;WT)\hat{p}_{T+1} = f(x_T; W_T). x1x_1 的信息就这样通过一步梯度存进了 MLP, 预测 x3x_3 时可以用上.

训练阶段: 元学习初始化. W0W_0 怎么来? 注意 ℓt(Wt−1)\ell_t(W_{t-1}) 本身就是「看了 x0,…,xt−1x_0, \dots, x_{t-1} 之后预测 xtx_t」的测试损失. 一条序列上的测试损失是

L(W0;X)=1T∑t=1Tℓt(Wt−1)(13)\mathcal{L}(W_0; X) = \frac{1}{T}\sum_{t=1}^{T} \ell_t(W_{t-1}) \tag{13}

直接在大量训练序列上最小化式 (13), 训练损失与测试损失一致, 论文称之为端到端 (E2E). 对照的做法是忽略推理阶段的更新, 只优化

Lnaive(W0;X)=1T∑t=1Tℓt(W0)(14)\mathcal{L}_{\text{naive}}(W_0; X) = \frac{1}{T}\sum_{t=1}^{T} \ell_t(W_0) \tag{14}

这就是普通预训练, 也是动态评估 (dynamic evaluation) 文献的主流做法, 论文称之为 TTT-naive. 玩具例子上 (论文图 2 右), TTT-naive 只比无注意力基线好一点, TTT-E2E 几乎追上全注意力.

对式 (13) 求 ∇W0\nabla_{W_0} 要穿过式 (12) 里的梯度, 也就是对梯度求梯度. 在元学习的术语里, 对 L\mathcal{L} 的梯度步是外循环, 对 ℓ\ell 的是内循环.

只看一句「梯度的梯度」很容易把计算量想错. 对一步更新求导可得

∂Wt∂Wt−1=I−ηHt,Ht=∇2ℓt(Wt−1).(15)\frac{\partial W_t}{\partial W_{t-1}} =I-\eta H_t, \qquad H_t=\nabla^2\ell_t(W_{t-1}). \tag{15}

因此后面某个损失传回 W0W_0 时, 要依次乘上这些 Jacobian:

∂ℓt(Wt−1)∂W0=∂ℓt(Wt−1)∂Wt−1∏j=1t−1(I−ηHj).(16)\frac{\partial \ell_t(W_{t-1})}{\partial W_0} =\frac{\partial \ell_t(W_{t-1})}{\partial W_{t-1}} \prod_{j=1}^{t-1}(I-\eta H_j). \tag{16}

实现时不需要显式构造巨大的 Hessian, 自动微分计算的是 Hessian-vector product. 但中间更新的计算图仍要保留或重算, 这就是训练比推理难得多的地方. 推理只执行前向、一次普通反向和参数更新; 训练初始化 W0W_0 时, 外循环还要穿过整串内循环. 二阶指的是外循环对内循环梯度求导, 不是每个推理请求都要再做一次二阶优化.

所以 TTT-E2E 的「端到端」有两层: 推理阶段的内循环直接优化网络最末端的下一个 token 预测损失 (对照 TTT layer 的逐层重建); 训练阶段的外循环直接优化经过 TTT 之后的损失 (对照动态评估).

mini-batch 与滑动窗口. 逐 token 的式 (12) 有两个问题: 串行, 不能并行; 每步只依赖一个 token, 梯度容易偶然爆炸. 换成 mini-batch:

Wi=Wi−1−η 1b∑t=(i−1)b+1ib∇ℓt(Wi−1),i=1,…,T/b(17)W_i = W_{i-1} - \eta\, \frac{1}{b}\sum_{t=(i-1)b+1}^{ib} \nabla \ell_t(W_{i-1}), \qquad i = 1, \dots, T/b \tag{17}

外循环的式 (13) 相应改成块内都用 Wi−1W_{i-1} 计算损失. b=1b = 1 时退回式 (12), (13).

用块写法可以把状态更新时间说得更准确. 第 ii 块的 bb 个 token 先在同一个 Wi−1W_{i-1} 下完成预测, 随后把这 bb 个损失的平均梯度写成 WiW_i. 第 ii 块的信息从第 i+1i+1 块开始通过权重生效. 滑动窗口在块内逐位置移动, 因而当前 token 仍能直接看到窗口内的较早 token; TTT 状态负责的是窗口之外、已经完成更新的旧块.

设滑动窗口为 kk, 更新层的参数量为 PuP_u, 序列长度为 TT. 忽略常数后, prefill 的局部注意力为 O(Tkd)O(Tkd), 内循环前向与反向约为 O(TPu)O(TP_u), 状态存储为 O(Pu)O(P_u). 全注意力 prefill 则有 O(T2d)O(T^2d) 的注意力计算和随 TT 增长的 KV cache. 这就是 TTT-E2E 在足够长的上下文上追过全注意力的来源. 不过 O(TPu)O(TP_u) 的常数很大: 被更新的是后四分之一 Transformer 块里的完整 MLP, 每个 1K 块都要做一次反向, 不能把它与一次便宜的线性递推更新视为同一成本.

以主实验的 T=128T=128K, b=1b=1K, k=8k=8K 为例, 整段 prefill 一共发生 128 次权重更新. 第 1 块的预测可直接使用至多 1K token 的局部历史; 到第 8 块, 窗口已经覆盖 8K, 更早的块则只能通过 W1,…,W7W_1,\ldots,W_7 留下影响; 到第 128 块, 窗口仍只有 8K, 权重状态已经累计 127 次写入. 把 bb 改成 2K 会把更新减到 64 次, 系统吞吐更容易提高, 但每条信息要等更久才能写入, 每次梯度也混合更多 token. 把 kk 改大只增强局部精确访问, 并不增加 fast weights …10828 tokens truncated…只开窗口已达到完整模型,更新分支可能没有被读;若只开快速状态在块内同样好,需要检查参数版本是否泄漏未来。

进一步把快速状态替换成另一序列、在某个块边界清零、或仅删除 needle token 对梯度的贡献。内容特异性能随这些干预有方向地变化,才构成因果证据。状态范数变大、梯度热图醒目或 attention 权重集中都只能说明内部量发生变化,不能单独证明模型利用了那段历史。

从整段似然到在线预序列目标. 评测顺序本身就是目标定义. 测试时训练很容易在 loss 口径上发生含混。对序列 x1:Tx_{1:T},标准自回归负对数似然为 −∑tlog⁡p(xt∣x<t)-\sum_t\log p(x_t\mid x_{<t})。若状态允许在看到 xtx_t 后更新,那么 xtx_t 只能改善 t+1t+1 及以后预测;用更新后的状态再次给 xtx_t 打分,相当于允许模型先看答案再考试。把预测与更新交替写开,合法的预序列过程是

ℓt=−log⁡pθt(xt∣x<t),θt+1=U(θt,∇θtℓt).(24)\ell_t=-\log p_{\theta_t}(x_t\mid x_{<t}),\qquad \theta_{t+1}=U(\theta_t,\nabla_{\theta_t}\ell_t). \tag{24}

chunk 版本将 token 换成块:先用 θc\theta_c 给整块逐位置打分,再用该块 loss 形成 θc+1\theta_{c+1}。只要块内前向保持 causal,所有被计分 token 都没有进入服务自身预测的 fast state。论文中的滑动窗口、缓存复用和并行计算最终都应还原到这个时间次序。

训练时常见的 support/query 划分是同一原则的显式版本。支持段只产生更新,查询段只用于外层评估;滑动执行则让一个位置先作为 query 被计分,随后成为未来位置的 support。两者的目标权重不同:固定 support/query 会丢掉支持段的评测贡献,完整 prequential loss 给每个位置一次预测机会。复现若改变划分比例,既改变训练数据量,也改变一次更新能服务多少后续 token。

更新收益可以分解成梯度对齐. 对一步小更新,查询 loss 的变化可一阶近似为

LQ(θ−ηgS)−LQ(θ)≈−η⟨gQ,gS⟩.(25)L_Q(\theta-\eta g_S)-L_Q(\theta) \approx-\eta\langle g_Q,g_S\rangle. \tag{25}

其中 gSg_S 是支持段梯度,gQg_Q 是查询段梯度。测试时训练有效的最直接条件,是过去 token 的梯度与未来 token 的梯度正对齐。主题延续、重复实体和稳定文体通常提高对齐;主题突变、冲突事实或随机噪声可能产生负对齐。二阶项决定步长较大后的偏离,但一阶内积已经能解释为何同样的更新规则在不同数据上差异很大。

这个量也把 LaCT 的块平均问题具体化。令块梯度 gS=B−1∑igig_S=B^{-1}\sum_i g_i,它与查询梯度的内积是各 token 对齐度的平均。大量无关 token 的期望对齐接近零,却会降低有效信噪比;负对齐 token 会直接抵消关键证据。逐 token 记录 ⟨gi,gQ⟩\langle g_i,g_Q\rangle,再按 surprisal、位置和语义类型分桶,可以检查高损失是否真的预示未来价值。

若外循环训练成功,它会塑造表示,使有未来作用的支持梯度更容易与查询梯度对齐。比较训练初期与收敛后的对齐分布,是验证元学习机制的一条路径。只看到查询 loss 下降,还可能来自更强静态初始化;看到内容相关的梯度对齐经过训练系统性增强,才更接近「学会如何从上下文更新」。

二阶项给出安全步长的局部尺度. 保留二阶展开,查询变化约为

ΔLQ≈−ηgQ⊤gS+η22gS⊤HQgS.(26)\Delta L_Q\approx-\eta g_Q^\top g_S +\frac{\eta^2}{2}g_S^\top H_Qg_S. \tag{26}

第一项是适应收益,第二项是查询曲率带来的惩罚。在 gQ⊤gS>0g_Q^\top g_S>0 且二次型为正时,存在局部最优步长;盲目增大学习率会越过它。若梯度负对齐,任何足够小的正步长都会伤害查询,此时裁剪只能减少损害,无法改变方向。门控应识别负迁移,预条件器则能旋转或缩放更新方向。

按块学习率可以由块表示预测,也能由梯度统计决定。输入门容易学习语义启发,梯度门直接接触惊讶度与一致性。两者都要防止利用未来查询信息:测试时门只能读取当前支持块及已有状态。训练中若门网络看到了 query loss 或未来隐藏表示,部署时无法复现同样决策。

参考文献