跳转到内容
输入关键词后按 Enter 打开第一个结果。

TTT 入门教程:让模型在推理时「边用边学」

面向有深度学习基础、但没接触过 TTT 的读者。从直觉出发,逐步建立完整理解。

1. 为什么需要 TTT?——从一个类比说起

Section titled “1. 为什么需要 TTT?——从一个类比说起”

想象你是一个翻译官,参加一场没有准备的同声传译会议:

  • 传统深度学习模型:你的词汇量和语法知识在会议前就固定了。你可以逐句翻译,但如果会议中出现了之前没见过的新术语、或者某个话题持续讨论了 3 小时,你只能靠”短期记忆”(上下文窗口)来应对。一旦信息量超出短期记忆容量,你就开始遗忘前面的内容。
  • TTT 模型:你不仅在做翻译,还在边翻译边学习。每听一句话,你就更新自己对这场会议的”理解模型”——哪些术语重要、发言者习惯用什么句式、讨论的逻辑脉络是什么。这样即使会议开了 10 小时,你依然能保持高质量的翻译。

这就是 TTT 的核心直觉:在推理(测试)时,不是静态地处理输入,而是持续地从输入中学习,动态更新模型的一部分参数(称为 fast weights),让模型越用越懂当前的任务。

方法短期记忆能否”学习”长度限制
标准 Transformer✅ attention❌ 权重冻结O(n²) 复杂度,长序列昂贵
In-Context Learning (ICL)✅ prompt❌ 权重冻结同上
RNN / SSM (如 Mamba)✅ hidden state❌ 固定更新规则状态大小固定
TTT✅ fast weights边推理边学习可扩展,见下文
  1. 动态适应:模型能根据当前输入”学习”,而不是只靠固定权重
  2. 可扩展的上下文:fast weights 的容量可以很大(利用现有模型参数),不受固定 hidden state 的限制
  3. 与预训练兼容:让现成的预训练大模型也能获得这种能力

TTT 把模型参数分为两类:

  • Slow weights(慢权重):就是普通的模型参数,在预训练中学到,推理时冻结不变。存储的是”通用知识”。
  • Fast weights(快权重):推理时根据当前输入动态更新的一组参数。存储的是”当前任务的上下文信息”。

类比:慢权重是你的长期记忆(会说英语、懂数学),快权重是你在处理当前任务时的工作笔记(这场会议的主题是什么、客户喜欢什么风格)。

对每个输入 token(或一小批 token),TTT 做两件事:

  1. Apply(应用):用当前的 fast weights 处理输入,产生输出
  2. Update(更新):根据当前输入,用梯度下降更新 fast weights
# TTT 的核心循环(伪代码)
fast_weight = copy(slow_weight) # 从慢权重初始化
for token in input_sequence:
# 1. 应用:用当前 fast weight 处理 token
output = forward(token, fast_weight)
# 2. 更新:用梯度下降微调 fast weight
loss = compute_loss(token, fast_weight)
fast_weight = fast_weight - lr * gradient(loss, fast_weight)

这就是 TTT 的本质——推理时也在做小规模的训练,所以叫”Test-Time Training”。

核心思想:用 TTT 层来替代 Transformer 中的 attention 层

  • 每个 TTT 层维护自己的 fast weights
  • 用 self-supervised loss(如重建当前 token 的表示)来更新
  • 在图像分类和 NLP 任务上验证了有效性

局限

  • 架构不兼容:需要从头预训练,无法复用现成的大模型
  • 效率低:逐 token 更新,无法充分利用 GPU 并行
  • 目标不对齐:重建目标(“记住当前是什么”)和语言建模(“预测下一个是什么”)不一致
# 原始 TTT:替代 attention 的独立循环层
class TTTLayer:
def __init__(self):
self.W = nn.Parameter(...) # slow weight
def forward(self, sequence):
fast_W = copy(self.W)
outputs = []
for token in sequence:
out = fast_W @ token # apply
loss = reconstruct(token, out) # 重建当前 token
fast_W -= lr * grad(loss, fast_W) # update
outputs.append(out)
return outputs

核心思想:将 TTT 应用于大语言模型,用 TTT 层替代 attention 或与 attention 并行。

  • 设计了更适合语言建模的 TTT 目标
  • 解决了 TTT 在长序列上的训练稳定性问题
  • 在困惑度和长上下文任务上展现了潜力

局限

  • 仍然需要从头预训练(或大规模持续训练)
  • 计算效率仍然是瓶颈

3.3 In-Place TTT(Feng et al., ICLR 2026 Oral)🔥

Section titled “3.3 In-Place TTT(Feng et al., ICLR 2026 Oral)🔥”

这是 TTT 发展中最重要的一步——让 TTT 变得实用

核心洞察

不要新增或替换任何模块,直接”就地”复用 Transformer 中已有的 MLP 模块。

具体做法:

  • 冻结 MLP 的 gate 和 up 投影(慢权重)
  • 就地更新 MLP 的 down 投影(快权重)
# 标准 Transformer MLP
def mlp(x, W_gate, W_up, W_down):
gate = sigmoid(x @ W_gate.T)
up = x @ W_up.T
z = gate * up # 中间激活
return z @ W_down.T # 输出
# In-Place TTT:只更新 W_down
def in_place_ttt_mlp(chunk, W_gate, W_up, W_down):
# W_gate 和 W_up 冻结(慢权重)
# W_down 作为快权重,每个 chunk 后更新
z = sigmoid(chunk @ W_gate.T) * (chunk @ W_up.T)
# 1. Apply:用当前 W_down 计算输出
output = z @ W_down.T
# 2. Update:用 LM-Aligned 目标更新 W_down
target = compute_target(chunk) # 包含未来信息!
W_down = W_down + lr * (target.T @ z) # 外积累加,高效!
return output

为什么选 W_down?

MLP 本质上是一个 key-value memory(Geva et al., 2020)。中间激活 z 是 “key”,W_down 把 key 映射成 “value”。更新 W_down 就是在告诉模型:“对于你刚刚看到的这些 key,它们应该对应什么 value”。这非常自然。

解决了什么:架构不兼容问题。

不需要从头预训练,只需要对现有模型做短时间的持续训练(约 20B tokens),就能让 MLP 兼具”慢权重”和”快权重”的双重身份。

好处:所有现存的预训练模型(Qwen、LLaMA 等)都可以通过持续训练获得 TTT 能力。

解决了什么:目标函数不对齐问题。

传统 TTT 的重建目标是在说”记住当前 token 是什么”。但这不是语言建模要做的事——语言建模要做的是”预测下一个 token 是什么”。

In-Place TTT 的目标函数包含未来 token 的信息(通过因果卷积 Conv1D 引入):

# 传统 TTT 的目标:重建当前 token
target_recon = project(current_token) # 只用当前信息
# In-Place TTT 的目标:包含未来信息
# Conv1D 通过因果 padding 看到"右侧"的未来 token
target_aligned = project(Conv1D(embeddings))
# → 教模型"根据当前,预测未来可能是什么"

论文在理论上严格证明了:LM-Aligned 目标能让正确答案的得分显著增加,而重建目标几乎无效。这是理论指导设计的典范。

解决了什么:计算效率问题。

逐 token 更新太慢(串行),所以把序列分成较大的 chunk(512~1024 tokens),每个 chunk 内部并行计算,chunk 之间串行更新。

# Chunk-wise 更新 + Prefix Sum 并行化
chunks = split(sequence, chunk_size=512)
deltas = []
for chunk in chunks:
z = compute_activation(chunk, W_gate, W_up)
target = compute_target(chunk)
deltas.append(target.T @ z) # 并行计算每个 chunk 的增量
# Prefix sum:计算累积更新
prefix_sums = parallel_prefix_sum(deltas)
# 并行应用:每个 chunk 用之前所有 chunk 的累积更新
for i, chunk in enumerate(chunks):
W_down_i = W_down_0 + lr * prefix_sums[i-1]
output_i = activation_i @ W_down_i.T

由于更新规则是外积累加,具有结合律,可以通过 prefix sum 实现高效的 context parallelism。这让 In-Place TTT 在长序列上的训练和推理都很快。

In-Place TTT 的核心优势体现在长上下文场景:

上下文长度基线 (Qwen3-4B)+ In-Place TTT提升
4k96.696.1-0.5
8k94.195.6+1.5
64k74.378.7+4.4
128k74.877.0+2.2
256k(外推)41.743.9+2.2

关键观察

  • 短上下文(4k)时基线已经够强,TTT 反而略有噪声
  • 上下文越长,TTT 优势越大——这正是它的设计目标
  • 在 500M 到 14B 参数的模型上都有效,说明方法具有很好的通用性
  1. 架构兼容:不需要改模型结构,通过持续训练就能”激活”TTT 能力
  2. 理论支撑:LM-Aligned 目标有严格的理论分析,不是拍脑袋的设计
  3. 工程实用:大 chunk size、prefix sum 并行化、低开销,适合实际部署
  4. 长上下文优势明显:随着序列长度增加,优势持续增长
  5. 通用性强:从小模型(500M)到大模型(14B)都有效
  1. 短上下文下可能有退化:attention 已经够用时,额外的 TTT 可能引入噪声
  2. 需要持续训练:虽然是”即插即用”的,但仍需数十亿 tokens 的持续训练,不是零成本的
  3. decode 阶段效率待评估:论文主要讨论 prefill 阶段,自回归生成的逐 token decode 开销需要更多研究
  4. 目标函数局限:LM-Aligned 目标专为下一个 token 预测设计,对其他任务(如指令跟随、多轮对话)的效果还需探索
  1. 自适应 TTT:根据输入复杂度自动决定是否启动、更新多少层、chunk 多大
  2. TTT + MoE:MoE 的 expert 天然可以看作 fast weights,二者结合可能很有前景
  3. TTT 用于后训练:在 SFT / RLHF 阶段引入 TTT,增强指令跟随能力
  4. 多模态 TTT:将 TTT 推广到视觉、音频等模态
  5. TTT 的理论上限:给定 fast weights 的大小,信息容量极限是多少?

TTT 让模型在推理时”边用边学”。In-Place TTT 通过就地复用现有 MLP 模块,让 TTT 从”学术概念”变成了”可部署的工程方案”,尤其擅长处理超长上下文。


  1. Sun et al. “Test-Time Training with Self-Supervision for Generalization under Distribution Shifts” (ICML 2022)
  2. Sun et al. “TTT Layers: A New Building Block for Efficient Inference and Learning” (2024)
  3. Feng et al. “In-Place Test-Time Training” (ICLR 2026 Oral) — 论文 | 代码
  4. Geva et al. “Transformer Feed-Forward Layers Are Key-Value Memories” (EMNLP 2020)