Model Editing
模型编辑会更改已训练模型中的特定事实或行为,例如修改 LLM 的一条回答,无需重新训练,也不会影响无关输出。
模型编辑是指针对已训练模型中的某一项特定事实或行为进行定向修改,例如改变大型语言模型 (LLM)对“The Space Needle is located in the city of”的回答,同时无需重新训练模型,也不改变模型对无关输入的输出。模型编辑主要用于纠正、更新或添加 LLM 中的事实知识,因为完整重训成本过高,而只针对单个示例进行普通微调往往会导致过拟合或损害其他知识。编辑器要么计算对模型权重进行的小幅局部改动,要么将编辑内容存储在权重之外,并把相关输入路由到该内容。最知名的方法是 Rank-One Model Editing (ROME),由 Kevin Meng、David Bau、Alex Andonian 和 Yonatan Belinkov 提出,并发表于 NeurIPS 2022 的《在 GPT 中定位和编辑事实关联》。
模型编辑的工作方式#
编辑请求会指定一个输入(通常是主体和关系)以及新的输出,例如将 Space Needle 所在城市从西雅图改为巴黎。编辑方法大致分为几类:
- 先定位再编辑:ROME 首先使用因果追踪(一种通过破坏并恢复隐藏状态来定位事实的可解释性技术),找出 GPT 模型回忆事实的位置。决定性计算位于网络中部的前馈 (MLP) 层,具体在主体的最后一个 token 处。ROME 将一个 MLP 的输出投影视为键值记忆,并通过闭式秩一权重更新插入新事实;在 GPT-2 XL 中,它会编辑 48 层中的第 18 层。MEMIT 则将更新分散到多个层中,以便一次插入数千条事实。
- 学习式编辑器:MEND 会训练一个小型超网络,将编辑示例的梯度转换为低秩权重更新,因此即使模型有数十亿个参数,编辑仍然很快。
- 基于记忆的编辑器:SERAC 将编辑内容存储在显式记忆中,并使用范围分类器,将涉及某项编辑的输入发送给一个小型反事实模型,而不改动基础权重。GRACE 会在一个层中插入离散键值适配器码本,以支持长序列编辑。像检索增强生成那样把新事实放进提示词,是这类编辑器中最简单的一种。
ROME 的更新利用了线性层的一个性质:权重矩阵 W 会将存储的键映射到值,而只需添加一个秩一矩阵,就能让新键 k* 获得新值 v*。ROME 使用键的协方差矩阵 C 的逆矩阵对更新加权;C 根据该层已经接收的键估算,估算所用样本来自维基百科文本。这会让改动避开现有键所使用的方向。下面的 PyTorch 示例将该更新应用到一个存储了 5,000 个键的随机层,并与忽略协方差的普通秩一更新进行比较:
import torch
torch.manual_seed(0)
scales = torch.logspace(0, -2, 256) # key dimensions with very different variances, as in real activations
keys = torch.randn(5000, 256) * scales # keys of 5,000 facts the layer already stores
W = torch.randn(128, 256) # the layer maps each key to a value
C = keys.T @ keys / len(keys) # second-moment statistics of the stored keys
k_new = torch.randn(256) * scales # key of the subject to edit
v_new = W @ keys[0] # new value: one already stored for another subject, as in "Seattle" -> "Paris"
# Plain rank-one update vs. ROME's update, which steers the change away from directions stored keys use
plain = W + torch.outer(v_new - W @ k_new, k_new) / (k_new @ k_new)
c_inv_k = torch.linalg.solve(C, k_new)
rome = W + torch.outer(v_new - W @ k_new, c_inv_k) / (k_new @ c_inv_k)
for name, edited in [("Plain rank-one", plain), ("ROME", rome)]:
error = (edited @ k_new - v_new).norm() / v_new.norm()
drift = ((keys @ (edited - W).T).norm(dim=1) / (keys @ W.T).norm(dim=1)).median()
print(f"{name}: new-fact error {error:.4f}, median change on stored facts {drift:.2%}")两种更新都能将新键精确映射到新值,误差为 0.0000。普通更新会使 5,000 个已存储键对应输出的中位数变化 10.99%,而 ROME 的协方差加权更新则变化 5.02%,因此后者对该层已有知识的扰动更小。
评估编辑效果#
编辑效果需要同时从多个属性进行评估。可靠性关注编辑后的输入是否会得到新答案;泛化能力关注改写后的输入是否也能得到新答案;局部性(也称特异性)关注无关输入是否仍保留原答案;可迁移性则关注依赖该事实的推理是否会随之改变。ROME 的作者构建了包含 21,919 项反事实编辑的 CounterFact 数据集,以便同时衡量这些属性,因为早期的基准测试允许方法在不被察觉的情况下牺牲特异性来换取泛化能力。
编辑往往无法通过更难的测试。在包含 5,000 项编辑的 RippleEdits基准测试中,知名编辑器未能对与被编辑事实存在逻辑关联的事实做出一致修改,而简单的上下文内编辑基线得分最高。Gupta 等人发现,依次应用 ROME 和 MEMIT 会让模型遗忘先前的编辑和下游技能;这种遗忘先是逐渐加重,随后会突然加剧,从而限制模型能够吸收的编辑数量。
编辑视觉模型#
同样的秩一机制也适用于图像。Santurkar 等人通过编辑图像分类器,改写某一层应用于视觉概念的规则,例如把雪的表示映射为道路的表示,使模型能够处理雪地道路上的车辆,而无需收集新的训练数据。Ultralytics YOLOE会在导出时对自己的检测头进行无需梯度的编辑:将通过 set_classes() 配置的类别乘入每个分类分支的最终卷积层,使导出的模型无需训练,也无需文本编码器,就能检测新的词汇类别。
模型编辑与相关概念的比较#
- 微调:基于数据集更新大量权重,以改变整体行为。模型编辑针对一组输入输出,同时约束其他所有内容不变。
- 检索增强生成 (RAG):每次请求时都在提示词中提供最新事实,并保持模型不变,因此易于回滚,也能扩展到大量事实。
- 机器遗忘:消除特定训练数据的影响。模型编辑会替换或添加事实,而删除事实的编辑就是机器遗忘的一种形式。
- 任务算术:对完整微调任务产生的权重变化进行相加或相减。模型编辑则作用于单条事实。
- 机制可解释性:解释模型如何进行计算。ROME 的因果追踪源自这一领域,并用于确定编辑针对哪个层。










