线性规划可替代权重空间编程 改动减少 8 倍

原标题:Can a Linear Program Do Weight-Space Programming?
78AI 研判分

博主 Nathan Barry 分析 MIT CSAIL 提出的“权重空间编程”后发现,GPT-6 Astra 对 Qwen3.5-0.8B 的权重编辑本质上是靠试错求解一个线性规划问题,耗时约 8 小时、28 次前向传播。改用两次约一分钟的 LP 求解即可达到同等效果,且改动权重数量减少 8 倍。该结果说明权重空间编程的核心机制可被经典优化方法高效复现,对模型权重编辑与免梯度微调路线具有直接参考价值。

报道正文

本文目录10 个章节

上周,MIT CSAIL 发表了Sparks of Weight-Space Programming。给定一个小型网络的原始权重,GPT-6 Astra 能够判断出它被训练来玩哪款游戏。而仅给定一款游戏的规则,它就能从零开始写出一个小型网络的权重,并击败用 PPO 训练了 1 亿步的网络。没有梯度,没有训练循环,只是对权重所计算的内容进行推理。他们将此称为权重空间编程。

在另一项实验中,他们让 Astra 通过编辑权重来提升 Qwen3.5-0.8B 的数学能力。Astra 只改动了 0.016% 的权重,MATH-500 准确率便从 7.9% 跃升至 48.1%。1

查看 Astra 的编辑后,我意识到它的搜索大部分是在通过试错求解一个线性规划。它花了大约 8 小时和 28 次前向传播来选择改动哪些权重以及改动多少。而几次线性规划求解,每次约一分钟,就能完成同样的工作,且改动的权重数量少 8 倍。在这篇文章中,我将逐步拆解这次编辑、说明为什么它是一个线性规划,以及这对修复本身意味着什么。

思考循环#

小型推理模型有一个常见的失败模式:它们会陷入思考循环,反复重复同样的几行内容,而不是完成推理。Qwen3.5-0.8B 尤其容易出现这种情况,其模型卡也说明了这一点。在 MATH-500 上,基础模型 93% 的答案都撞上了 32,768 token 的上限,始终未能得出答案。

这次编辑修复了循环问题,因此它在模型出现循环的任何地方都有帮助。这包括指令遵循:IFEval 从 21% 提升到了 62%。

Qwen3.5-0.8BMATH-500GSM8KIFEval触及 token 上限
基础版7.913.821.093.0%
Astra 的修改版48.167.162.333.1%

在 Gemma 3 270M 上,模型很少出现循环,Astra 无法实质性地提升其数学能力。正如作者所说,编辑权重可以移除一个掩盖某种能力的障碍,但无法添加模型本身不具备的能力。

Astra 如何修复循环#

Transformer 使用残差连接:每一层的输出会加到其输入上,而不是替换它。让一个 token 穿过网络,你会得到一个单一向量,每一层都会向其累加,这被称为残差流(在此模型中为 1,024 维)。当模型陷入循环时,残差流会朝一个一致的方向偏移。Astra 的修复方法是编辑两层,使它们所添加的内容指向相反方向。

寻找循环方向#

Astra 写了四对短文本,每一对都包含一段有效推理和同一推理的循环版本。它将全部八段文本输入模型,并记录某一层中每个 token 的残差流向量。对循环文本取平均得到一个向量,对有效文本取平均得到另一个向量。两者之差归一化后即为循环方向 uu:即模型陷入循环时残差流的移动方向。

编辑权重#

每个 MLP 都以一个矩阵 WW 结尾(称为 down_proj)。在每个 token 处,它将 MLP 的 3,584 维隐藏激活 hh 转换为 1,024 维输出 WhWh,并加到残差流 xx 上:

x←x+Wh,Wh=∑jhj wjx \leftarrow x + Wh, \qquad Wh = \sum_j h_j \, w_j

因此,MLP 的输出始终是同样这 3,584 个向量(即 WW 的列 wjw_j)的加权和。WW 决定了这些向量是什么;激活值 hjh_j 决定了每个 token 处每个向量被添加多少。

每一列都部分指向 uu 方向。这个量 u⊤wju^\top w_j 就是当 hjh_j 活跃时,第 jj 列将模型推向循环的程度。Astra 的编辑减去它的一个倍数 α\alpha:

wj→wj−α (u⊤wj) uw_j \to w_j - \alpha \, (u^\top w_j) \, u

当 α=1\alpha = 1 时,沿 uu 的分量消失,因此该列不再将模型推向循环。对第 15 层和第 19 层的每一列执行此操作后,在 GSM8K 和 MATH 训练问题上的准确率从 9% 提升到了 33%。当 α=6\alpha = 6 时,该分量被翻转:原本沿 uu 写入 +a+a 的列现在写入 −5a-5a,并在被使用时将模型推离循环。

每个被编辑的列都按同一向量 uu 的倍数发生变化。因此,整个编辑就是一个方向 uu 加上每列一个数值,vj=−α (u⊤wj)v_j = -\alpha\,(u^\top w_j),对于未被改动的列,该值为零。这就是一个秩为 1 的改动:

ΔW=u v⊤\Delta W = u\,v^\top

在每个 token 处,它向残差流中加入 (v⋅ht) u(v \cdot h_t)\,u:即一定量的 uu,其大小由被编辑列的活跃程度决定。其他方向均不改变。

剩下的就是选择 vv:编辑哪些列,以及 α\alpha 应该取多大。Astra 通过反复试验得出了结果,在一批新的训练问题上逐一测试每次编辑:

在层 15 和 19 上编辑准确率
基础模型~9%
每一列,α = 133%
每一列,α = 243%
每一列,α = 348%
随机方向(对照)12.5%
前 64 列,α = 655%

比 α=1\alpha = 1 更用力地推动效果更好,而随机方向则毫无作用。最终的编辑只对每层中在循环文本上写入 uu 最多的 64 列使用了 α=6\alpha = 6。

时间花在了哪里#

论文公开了 Astra 的完整日志:每一次工具调用、每一次前向传播、它写给自己的每一条笔记。Astra 有一个加载了权重的 Python 内核,以及 50 次前向传播的预算,每次都是模型在其选择的训练问题或文本上的一次批量运行。

编辑在大约 10 小时后被冻结,最后 17 次传播重新测试了它,没有做任何改动。2 在这 10 个小时中,找到 uu 花了 15 分钟。找到 vv 花了大约 8 小时。

选择 v 是一个线性规划#

Astra 在寻找一个 vv,它能强力地将循环 token 推离 uu,同时几乎不触及有产出的 token。由于在 token tt 处的推动是 v⋅htv \cdot h_t,对 vv 是线性的,所以这两个要求都是线性不等式。

我从基础模型自身的轨迹中标注了 token:循环 token(RR),位于循环深处,以及有产出 token(PP),远在任何循环开始之前,3 并记录了它们在层 15 和 19 的激活 hth_t。每一个都成为一个约束,LP 选择具有最小 L1 范数 ∑j∣vj∣\sum_j |v_j| 的 vv:

min⁡v∑j∣vj∣s.t.v⋅ht≤−δt∈R(至少距离 u 有 δ)∣v⋅ht∣≤εt∈P(至多 ε)\begin{aligned} \min_v \quad & \sum_j |v_j| \\ \text{s.t.} \quad & v \cdot h_t \le -\delta && t \in R \quad \text{(至少距离 } u \text{ 有 } \delta\text{)} \\ & |v \cdot h_t| \le \varepsilon && t \in P \quad \text{(至多 } \varepsilon\text{)} \end{aligned}

在实践中,没有 vv 能满足每一个约束,所以每个约束都得到一个带惩罚的松弛变量。

最小化 L1 倾向于使 vv 稀疏。L1 球是一个菱形,当你把它增大直到它触及可行域时,它通常触及一个角,在那里大多数坐标恰好为零。所以 LP 既选择列,也选择数量。

为了每层恰好得到 8 列,我保留了效果最大的 8 列,并将其余列固定为零后再次求解。4

这取代了 Astra 耗时 8 小时的搜索(包括其列选择和 α\alpha 的选取),只需解几个 LP 即可完成。现成的求解器(HiGHS)在这些约束上每次都要花 20 多分钟,所以我写了一个 GPU 求解器(PDHG,即 PDLP 背后的算法),大约一分钟内就能达到其最优解的 0.2% 以内。5

结果#

我测试了两种 LP 编辑。两者都使用 Astra 的层。一种使用 Astra 的方向 uu。另一种使用启发式方向:用一个简单的重复检测器,将模型自身轨迹中的 token 标记为循环或有效,然后取它们平均残差流之差。这与 Astra 使用的配方相同,只是去掉了手写文本,因此不涉及 LLM。我在一个单独的 128 题开发集上调整了 LP 的设置;图表和表格中的所有内容都来自从未用于拟合或调优的数据。

| 更改的权重 | GSM8K 测试 | MATH-500 | IFEval | | --- | --- | --- | --- | --- | | 基础模型 | 0 | 14.1 | 7.0 | 22.9 | | Astra 的编辑 | 130,188 | 68.2 | 50.9 | 61.9 | | LP,Astra 的方向 | 16,291 | 69.6 | 51.7 | 59.7 | | LP,启发式方向 | 16,271 | 65.4 | 47.8 | 60.4 |

在 Astra 的指导下,LP 在每个基准上都与 Astra 的编辑效果相当(在噪声范围内),而改动的权重少了 8 倍。使用启发式方向时,它能达到约 93% 的效果。

另外还发现了几点:

  • 搜索很重要,而 LP 取代了它。 在开发集上,沿用 Astra 的配方(前 64 列,α=6\alpha = 6)作用于启发式方向、不再重新搜索,得分为 44.5。LP 的得分为 54.7。
  • 不同的列,同样的修正。 LP 的 8 列与 Astra 的 64 列仅共享 3 列(第 15 层)和 1 列(第 19 层)。许多稀疏解都有效;关键在于沿 uu 的总推力。
  • 随机方向毫无作用。 在开发集上,同样大小的随机 uu 得分为 10.2,而基础模型为 10.9。

引导向量也能完成同样的工作#

编辑只能通过激活值来区分循环 token 和有效 token,而循环在充分展开之前无法从激活值中识别出来。6 因此,在开发集上,让 LP 只对类循环 token 施加推力,效果并不比对所有 token 施加推力更好。

LP 在第 15 层的 8 列在 89% 的 token 上处于激活状态,而且它们添加的推力在 token 之间几乎没有变化,因此该编辑接近于沿 uu 的恒定推力。恒定推力不需要权重编辑。它可以直接作为引导向量添加,即在每个 token 处向残差流添加一个固定向量。

下表将 LP 编辑沿 uu 的平均推力以三种强度添加到第 15 层和第 19 层的未编辑模型上:

引导强度(× LP 编辑的平均推动力)开发集MATH-500
0.5×51.6
1×57.850.8
2×31.2

作为对比,在相同的运行中:LP 编辑在 dev 集上得分为 62.5,在 MATH-500 上为 53.2,Astra 的编辑为 59.4 和 50.0,基础模型为 10.9 和 7.0。这里的 MATH-500 每道题只取一个样本。

在 1× 下,引导向量基本恢复了全部修复效果。窗口很窄:在 0.5× 时循环又出现了,而在 2× 时循环停止了,但推理却崩溃了。

唯一的区别在于交付方式。LP 编辑是一个普通的检查点;而引导向量需要在推理时额外添加代码。

局限性与后续工作#

这只是一个模型。LP 仍然依赖 Astra 来提供层,而且最佳结果也使用了 Astra 的方向。启发式方向在没有 LLM 的情况下也能完成大部分工作,但并非全部。

循环也被证明可以通过恒定推力来修复,因此 LP 的逐 token 约束最终并没有那么重要。一个应该改变某些 token 而保持其他 token 不变的行为,会是更好的测试。在没有智能体的情况下选择层是另一个未解决的问题。

最后,这仅在消除循环上进行了测试。许多其他行为,如拒绝或谄媚,可以通过在残差流中添加或移除单个方向来引导。7 如果一个行为可以用一个方向来引导,那么选择如何将其构建到权重中应该是同一个 LP,但这仍需要测试。

代码、编辑和完整说明都在 GitHub 上。

引用#

请按以下方式引用本工作:

文本
Barry, Nathan. "Can a Linear Program Do Weight-Space Programming?"
nathan.rs (Nov 2026). https://nathan.rs/posts/weight-space-lp.

或使用 BibTex 引用:

文本
@article{barry2026wslp,
  title   = "Can a Linear Program Do Weight-Space Programming?",
  author  = "Barry, Nathan",
  journal = "nathan.rs",
  year    = "2026",
  month   = "Nov",
  url     = "https://nathan.rs/posts/weight-space-lp"
}