什么是 Looped Transformer:用共享层增加计算深度,从原理到推理 Infra
Loop Transformer 通常指 Looped Transformer(循环 Transformer):将同一个 Transformer 层或层组反复应用到不断变化的隐藏状态上,让模型用共享参数执行更多轮计算。 每轮的权重可以相同,但输入状态不同,因此每轮做出的更新也不同。
它让“有多少参数”和“输出一个 token 前经过多少计算”不再紧密绑定。普通深层网络通常靠堆叠更多独立层增加深度;循环结构则允许复用一组层,增加有效计算深度。这个方向与推理时计算、潜在空间推理有关,但不能直接推导出“循环越多必然越聪明”。
本文解释的是这一类架构,而非某一个同名产品。资料核验于 2026 年 9 月 17 日;论文实验、本文教学算例与工程推论分别标明。先了解基本 Transformer 即可阅读。
1. 循环的到底是什么?
普通 Transformer 的一个简化写法是:
\[ h_{\ell+1}=F_{\theta_\ell}(h_\ell),\qquad \ell=0,\ldots,L-1. \]
不同层一般具有不同参数 \(\theta_\ell\)。Looped Transformer 的典型写法则是:
\[ h^{(r+1)}=F_\theta(h^{(r)}),\qquad r=0,\ldots,R-1. \]
这里的上标 \(r\) 表示深度方向的迭代次数,不是生成了多少个 token。\(h^{(r)}\) 可以是整段序列的隐藏表示矩阵;在自回归服务中,也可以结合历史缓存计算当前 token 的表示。循环体可以只有一层,也可以包含若干层。某些设计还会反复注入原始输入表示或引入迭代位置编码,所以不同论文的递推式并不完全相同。Universal Transformer 是理解深度递归与自适应停止的重要早期工作。
绿色方框是同一模块的三次调用,不是三份参数。每次调用仍要执行 Attention 和 MLP 等计算;变化的是隐藏状态。
这与四种常见的“循环”需要区分:
| 机制 | 反复更新的对象 | 关键区别 |
|---|---|---|
| 自回归生成 | token 序列 | 每次生成下一个 token,本身不意味着层之间共享参数 |
| 显式 CoT | 文本形式的中间步骤 | 通过生成推理文本扩展计算与上下文 |
| Looped Transformer | 模型内部的隐藏表示 | 可在输出新 token 之前执行更多轮共享层计算 |
| Agent 工具循环 | 动作、工具结果和环境状态 | 是模型外部的控制流程,可以使用循环或普通模型 |
这些机制可以组合。例如,一个循环模型也可以生成 CoT,并在 Agent 系统中调用工具。
2. 为什么重复相同权重,不会只得到相同结果?
只有将完全相同的输入反复送入同一个确定性函数,输出才必然相同。循环网络送回的是上一轮更新后的状态。
考虑一个与 Transformer 无关、仅用于理解递推的教学算例:想估计数值 10,使用固定规则
\[ h^{(r+1)}=h^{(r)}+\tfrac12(10-h^{(r)}),\qquad h^{(0)}=0. \]
| 轮次 | 隐藏状态的标量类比 | 距离目标的误差 |
|---|---|---|
| 0 | 0 | 10 |
| 1 | 5 | 5 |
| 2 | 7.5 | 2.5 |
| 3 | 8.75 | 1.25 |
| 4 | 9.375 | 0.625 |
规则始终没有改变,状态却不断修正。这里把目标 10 直接提供给更新规则,是为了演示“同一函数可以逐轮改进状态”;真实模型并不会直接拿到正确答案。
真实 Transformer
学到的更新远比这个例子复杂,也没有上述误差减半的保证。更新可能改进表示,也可能振荡、丢失信息,或者很快不再变化。因此,训练必须让循环模块学会一种可反复应用的变换,而不是仅仅把现有模型的
forward() 多调用几次。
Reasoning with Latent Thoughts 在合成推理任务以及部分语言模型实验中研究了这一点:某些问题需要足够深的计算链,但未必需要每一步都有独立参数。这是特定任务和实验条件下的证据,不是所有任务都能用小模型循环替代大模型的定理。
3. 参数、有效深度与计算量,要算三笔账
考虑一个由输入模块、循环核心和输出模块组成的教学架构:输入模块 2 层,核心 4 层,输出模块 2 层。核心执行 \(R\) 次,则:
\[ D_{\mathrm{effective}}=2+4R+2. \]
不计辅助参数,独立层组仍是 \(2+4+2=8\) 层。假设每层的参数量和执行成本相同,并忽略 embedding、输出词表投影等开销,可以得到:
| 核心循环次数 | 独立层数 | 有效层调用次数 | 以 R=1 的整次前向为基准的层调用成本 |
|---|---|---|---|
| 1 | 8 | 8 | 1 倍 |
| 2 | 8 | 12 | 1.5 倍 |
| 4 | 8 | 20 | 2.5 倍 |
| 8 | 8 | 36 | 4.5 倍 |
这是教学账本,不是某款 GPU 的延迟测试。 输出头成本、Attention 长度、并行效率和缓存读写都会影响实测速度。
循环模型主要节省的是相对于同等展开深度模型的独立参数。相应地,权重和优化器状态可以较少;前向计算、反向计算和中间激活仍需单独核算。完整反向传播要穿过展开的计算图,共享参数会汇总来自多次调用的梯度,并不意味着只对其中一次调用求导。
跨层参数共享也有更早的代表:ALBERT。但“共享参数”和“推理时可以自由增加循环且持续获益”是两项不同能力;后者还需要相应的训练与验证。
4. 几篇代表工作分别解决了什么?
这不是完整论文目录,而是一条从机制到模型的阅读线。
| 工作 | 值得理解的贡献 | 阅读时保留的边界 |
|---|---|---|
| Universal Transformers,2018 / ICLR 2019 | 在深度方向重复更新,并研究逐位置动态停止 | 早期任务结果不能直接外推到今天的大规模聊天模型 |
| Looped Transformers as Programmable Computers,2023 | 构造特定权重,让循环 Transformer 执行程序与迭代算法 | 是可表达性与构造性研究,不等于普通预训练会自动学会任意程序 |
| Reasoning with Latent Thoughts,2025 | 分析循环、有效深度及推理能力之间的关系 | 理论构造及指定任务上的经验规律,都有各自假设 |
| Huginn / Recurrent Depth,2025 | 将深度递归扩展到 3.5B 参数、800B 训练 tokens 的语言模型 | 模型规模、训练数据量和推理计算量是不同指标 |
| Ouro / LoopLM,2025,后续修订至 2026 | 将潜在迭代与深度分配纳入预训练,报告 1.4B、2.6B 模型及 7.7T-token 训练规模 | 比较模型大小时,还需核对训练数据、推理预算和基准设置 |
| Hyperloop Transformers,2026 | 在循环核心间加入 hyper-connections,研究参数效率 | 论文条件下约减少一半参数,不表示延迟或总显存也减半 |
Huginn 是理解具体架构的好例子:论文采用 prelude → recurrent core →
coda,并将输入表示注入递归核心;训练中使用变化的循环深度与截断反向传播。核心问题是学出可重复执行的更新,而不只是机械地复用层。其官方代码给出了模型与训练实现,阅读时可从
recpre/raven_modeling_minimal.py 和
recpre/model_dynamic.py 入手。
不要把论文中的“计算量相当于更大模型”写成“参数量变大了”,也不要写成“在所有任务上等价于那个大模型”。前者是计算账本,后者是能力判断,需要独立实验。
5. 它与 CoT、Coconut、测试时训练有什么关系?
显式 CoT 把中间过程写成 token。循环深度则把额外计算放在内部状态更新中,可以增加内部计算而不增加相应数量的文本位置。不过,每一轮仍然需要时间和资源;少生成文字不自动等于总成本更低。
Coconut 也是潜在空间推理:把模型最后的隐藏状态作为后续输入 embedding,而不先解码成词。它与循环模型关系密切,但不能完全画等号。比较具体实现时,应看反馈发生在整个模型输入端还是内部层组,是否增加序列位置,以及训练如何支持这种反馈。
可以用下面三个问题区分概念:
- Test-time compute:推理时是否多花了计算?增加循环、生成更多 CoT、采样多个候选都可以属于它。
- Latent reasoning:中间处理是否发生在连续隐藏表示中?这是对表示与计算方式的描述。
- Test-time training:推理阶段是否更新了模型参数?普通的循环前向通常保持权重不变,因此不属于测试时训练。
“Latent thought”也不保证每轮都对应一句可读的推理步骤。隐藏状态可能同时编码多种信息;给每轮强行配一句解释,可能只是事后猜测。要声称某个可读轨迹忠实反映内部计算,需要额外证据。
6. 训练时如何学会循环,什么时候该停?
最简单的训练方式是固定 \(R\),展开循环后用最终输出计算 next-token loss。若希望在多个深度工作,可以让训练覆盖不同的 \(R\)。一个说明这种目标的通用写法是:
\[ \mathcal L(\theta)=\mathbb E_{x,\,R\sim q}\left[-\sum_t\log p_\theta(x_{t+1}\mid x_{\leq t},R)\right]. \]
这里 \(q\) 是训练时的计算深度分布。覆盖多个深度有助于建立适应性,但不保证无限外推。 训练只见过少量循环,测试时突然执行上千轮,可能使表示进入没有被优化过的区域。
为了控制成本,工程上可能使用激活重计算、截断反向或停止策略。它们的含义不同:重计算是在需要时重新得到中间激活;截断反向则省略部分较早路径的梯度,改变了梯度估计,不能描述为完全无损的节省。
停止规则也有不同选择:固定预算、学习出来的 halting 概率,或根据连续两轮输出变化来决定。Universal Transformer 与 Ouro 分别提供了动态计算的不同研究路径;具体损失和停止规则应以对应论文为准。
一种便于理解、但需要校准的工程启发是比较两轮分布:
\[ \mathrm{KL}\bigl(p^{(r)}\,\|\,p^{(r-1)}\bigr)<\varepsilon. \]
分布接近只能说明“模型不怎么改变判断了”,不能证明判断正确。比较质量时还应计入为检查停止条件而执行的输出头成本,并设置最大循环预算。
7. 对推理 Infra 最重要的变化:缓存与调度
以下是从架构推出的工程分析,不是对某个推理引擎当前支持情况的承诺。
7.1 共享权重,不代表共享 KV 值
假设某层的 Key 投影是:
\[ K^{(r)}=h^{(r)}W_K. \]
即便 \(W_K\) 相同,只要 \(h^{(r)}\) 不同,\(K^{(r)}\) 就通常不同。Value 同理。按展开深度精确缓存时,需要区分循环轮次与核心内部层号;若用共享缓存、覆盖旧缓存或重计算,必须明确额外假设和质量影响。
一个具体算例:核心有 4 个 Attention 层,循环 8 次;8 个 KV heads,每头维度 128,BF16 每元素 2 字节。如果完整缓存全部 32 次核心层调用,那么每个历史 token 的核心 KV 占用是:
\[ 2\times 32\times 8\times128\times2 =131072\ \text{bytes}=128\ \text{KiB}. \]
4096 个 token 对应 512 MiB,尚未包括输入/输出模块、batch 与分配开销。若误按“只有 4 个独立核心层”来算,会低估 8 倍。这是指定缓存方案下的教学计算,不是所有循环模型的固定占用。
Huginn 论文专门探索过 KV-cache sharing 和早停后的缓存处理;这些属于经过实验的设计选择,不能从权重共享直接推出它们对任何模型都无损。论文第 6 节
7.2 输出长度相同,任务成本也可能差很多
两个请求都生成 100 个 token,其中一个每 token 循环 4 次,另一个循环 32 次,调度负担显然不同。至少应记录:输出 token 数、循环次数分布、循环模块耗时、首 token 延迟、总延迟和成功率。
如果同一 batch 中各请求的循环深度不同,执行还可能出现拖尾;分组、动态批处理与提前退出需要共同设计。token/s 仍然有用,但不足以独立描述模型完成了多少内部计算,以及这些计算带来了多少质量收益。
7.3 与 Agentic RL 结合时,计算预算进入策略契约
沿着上一篇 LLM Infra 与 Agentic RL Infra 学习路线 往下看,会多出一个容易忽略的问题:
即使权重和输入 token 相同,rollout 用 8 轮、训练端用 32 轮,输出概率通常也不同。
因此,记录和复算行为概率时,需要考虑循环预算、停止规则,以及随机初始状态或随机深度等因素。固定预算可以作为条件;若深度或停止动作是随机采样的,还需定义概率是条件概率还是包含该随机过程的联合/边缘概率,不能只保存一个整数就认为问题解决了。
这是工程与算法设计建议,而非某篇论文已验证的通用 RL 配方。相应的最小检查是:固定权重、实际输入、预算和随机性控制,先测 rollout 与训练端的 logprob 一致性,再研究跨预算训练或重要性修正。
8. 怎样做一个有解释力的入门实验?
先实现一个小型、因果 Attention 的共享层模型,在可自动验证的合成任务上研究循环。下面是表达结构的伪代码,省略了层定义、mask 和缓存处理,不能当作完整可运行训练脚本:
1 | |
实验分成三个对照,而不是只和一个更浅的模型比较:
- 相近参数量:小型普通模型与循环模型,看看额外计算带来了什么。
- 相近有效深度:循环模型与展开深度相同的独立层模型,比较参数效率。
- 相近计算或延迟预算:在同一硬件、同一任务上比较成功率与成本,避免把多花计算误称为架构无条件更优。
对循环次数 \(R=1,2,4,8,16\) 画出正确率、延迟和峰值显存三条曲线。固定测试集、输出预算与解码设置;标出哪些 \(R\) 在训练中出现过。报告曲线是否饱和或回落,不要只展示最有利的那一个点。
评估时还要区分训练总 tokens、训练 FLOPs、参数量和推理成本。Ouro 等工作的意义在于展示一个值得研究的方向,不能只拿小模型参数量与对手比较,就忽略预训练规模和循环成本。
自测:4 层核心执行 8 次,是 32 层模型吗?
它有 32 次核心层调用,但只有 4 层核心的独立参数。可以说“核心有效深度为 32”,不能直接称为“32 个独立层”。输入、输出模块还要另外计算。
自测:不生成推理文字,是否就没有中间计算开销?
不是。循环仍要执行算子、读写隐藏状态和缓存。它改变了计算发生的位置及参数组织方式,并没有取消计算。
自测:可以把任意现有 LLM 的中间层重复十次吗?
技术上可以修改执行图,但该模型未必学过这样的状态分布。需要验证稳定性、输出质量、位置与缓存语义;增加调用次数本身不提供效果保证。
9. 继续阅读的顺序
先读 Universal Transformers 建立递归与停止的概念,再读 Reasoning with Latent Thoughts 理解“深度与参数量分离”的研究问题。接着用 Huginn 论文和官方实现连接模型结构、训练和缓存。
之后可以按兴趣分支:通过 Ouro 研究预训练与计算深度分配,通过 Hyperloop 研究参数效率,通过 Coconut 比较不同潜在反馈路径。如果更关心理论,再读 Looped Transformers as Programmable Computers 与官方代码。
贯穿这些工作的核心问题是:在给定参数、数据与计算预算下,怎样让反复使用的计算模块持续完成有用的状态更新? 回答它,需要同时观察模型质量、迭代稳定性和系统成本。
点赞与评论
喜欢这篇文章?点个赞,或留下你的想法。登录 GitHub 后即可参与。
如果评论无法加载,请检查网络连接后刷新页面。