几何瓶颈防御:用方向约束破解有害微调的安全难题
如果你最近在折腾开源大模型的垂直领域微调大概率会撞上一个诡异的现象模型平时万般乖巧但只要喂进去几百条带毒样本再跑一轮 SFT它就能一本正经地开始输出危险内容。这个现象在圈子里有一个固定称呼harmful fine-tuning。我最近读到的这篇论文 Safety Anchor: Defending Harmful Fine-tuning via Geometric Bottlenecks没有继续走“过滤数据、加对抗训练”的老路而是钻到模型内部用 geometric bottlenecks几何瓶颈把安全行为钉在原地。考虑到这个问题正在成为大模型安全里最棘手的攻击面之一这篇阅读笔记我会把论文的动机、核心机制、实验结论一条条拆开来讲同时也把我自己读到一半时的困惑和推演放进去适合关心开源模型微调落地、大模型安全对齐以及红队攻防的工程师和研究者看。1. 从一个“客服机器人翻车”说起Harmful Fine-tuning 为什么比越狱更难防1.1 问题定义微调如何反向摧毁安全对齐先还原一个非常典型的攻击场景。假设你发布了一个经过 RLHF/DPO 对齐的 7B 开源模型社区用户可以自由下载权重也可以合法地用 LoRA 微调适配自己的业务。攻击者并不需要什么高级手段他只需要拿几百条甚至几十条“如何制造危险物品”“如何实施诈骗”之类的样本混进普通指令数据里跑一个 epoch 的常规微调原来那个“会礼貌拒绝”的模型就可能消失不见。这不是我夸张。论文里讨论的 harmful fine-tuning 指的就是这种“攻击者拿到了模型权重用极少量的有害数据覆盖安全对齐行为”的训练期攻击。关键点有两个一是攻击者拥有参数访问权限这是开源模型的天然属性二是微调过程本质上是继续优化下一个 token 预测损失它不管你对齐时花了多少心思只要有害样本的 loss 能降模型的参数就会朝那个方向挪。越狱jailbreak是推理期攻击打个比方是趁保安打瞌睡偷偷溜进大门harmful fine-tuning 是训练期攻击攻击者直接把保安辞了换一个自己人站岗。前者还能靠 system prompt、输出过滤、推理侧检测来补救后者发生在权重层面任何提示词层面的修复都很难彻底拉回来因为模型“关于安全的行为分布”已经被覆盖了。1.2 现有防线为什么会集体失灵我见过很多团队应对这类问题第一步是加数据过滤把已知的有害样本用关键词、困惑度或者外部分类器滤掉。这个做法能挡住最普通的攻击但挡不住改写攻击攻击者只要把恶意内容包装成“医疗咨询”“历史讨论”“代码调试”过滤器的召回率就会断崖式下降。第二步是重新对齐也就是把模型拉回来再做一轮 DPO/RLHF。问题是成本高、周期长而且如果后续还要继续微调等于陷入“攻防拉锯”的无限循环。第三步是推理侧加护栏比如在外面套一层安全审查模型。这能减少线上风险但治标不治本模型参数内部已经坏了审查模型本身也会被攻击者针对性绕过。这三条线本质上都停留在“输入输出行为层”都没有回答一个问题微调到底改变了模型内部的什么东西才导致安全行为丢失论文的出发点恰恰就是这个问题——与其在模型外面设卡不如让模型内部“对有害方向的更新不配合”。1.3 这篇论文的立足点换个赛道防御Safety Anchor 的标题已经把思路写在脸上了用几何瓶颈来防御有害微调。这里的核心假设是模型内部表示空间中存在某些特定的“方向”这些方向与危险行为强相关如果能够在这些方向上制造一个几何瓶颈那么无论攻击者怎么更新参数模型在行为上都很难滑向有害一侧。这个思路和传统防御最大的不同在于它承认攻击者可以任意微调也不试图把有害样本全部识别出来而是改变模型内部的“几何地貌”让有害微调变成一件天然费力的事。打个比方你无法阻止别人在你家墙上打洞但你可以把承重墙换成钢筋混凝土——撬得动是你的本事但代价远超收益。2. 论文最关键的观察危险能力在模型内部有“方向”2.1 先说结论危险行为不是均匀分布在参数里的读论文我一向喜欢先看结论再回头啃证明。这篇论文给出的最核心观察是大模型的安全行为并不是均匀地弥散在所有参数和所有隐藏维度里而是与一组可辨识的表示方向强耦合。不同类别的危险能力比如暴力、违法建议、隐私侵犯在内部激活空间里并不是完全重叠的它们各自占据了一些相对聚集的方向区域。这个结论之所以重要是因为它意味着“防御”可以不必对所有方向无差别设限。如果危险行为只占表示空间里的一小部分方向那我们完全可以在保持其余方向自由通行的前提下只把那些危险方向“焊死”。2.2 如何“看见”危险方向探针、激活差与子空间估计论文里识别危险方向的手段我读下来的理解可以归成三步。第一步准备两组文本一组是安全指令一组是危险指令第二步把模型接上这两组文本前向传播取出某一层通常是倒数几层的 hidden state第三步对两组激活做对比找到能把它们区分开来的方向。实操上很像线性探针linear probing。先把危险指令的激活均值记作 h_harm安全指令的激活均值记作 h_safe那么 h_harm - h_safe 这个差值向量的方向就是一个很朴素的“危险方向”。更进一步可以在多个危险样本的激活差上做 SVD取前 k 个奇异向量张成一个危险子空间 U。这比我上面说的朴素做法更稳健因为单个方向会被噪声干扰而一个子空间能覆盖同一种危险能力的多副面孔。我在自己复现这个流程时踩过一个坑不能只取表层 token 的激活通常要在中间层和深层分别做一次探测因为浅层语义信息混杂方向信号很弱层数选对了方向才清晰。论文的做法是否完全一致我不能保证但这种“激活差 子空间分解”应该是当前表示分析的主流路线。2.3 良性微调和有害微调在几何轨迹上会分岔论文的另一个有意思的观察是良性任务微调和有害微调虽然在 loss 上都在下降但它们在表示空间里的移动轨迹通常是不重合的。良性微调比如让模型学会新领域的问答其激活移动方向更多落在与危险方向正交的维度上有害微调则不同它受危险样本驱动激活移动方向会明显偏进危险子空间里。这解释了为什么可以对“方向”做文章如果两类微调在几何上天然分叉那防御就可以做成一个路障——只堵危险方向的路给良性方向留出完整通道。这个观察也直接支撑了后面 Safety Anchor 的“选择性约束”逻辑而不是像传统正则那样把模型钉死在原处。2.4 为什么这个观察之前容易被忽略说实话在读到这篇论文之前我自己也更习惯从 loss、困惑度、输出分布这些标量视角理解微调。这些视角看不到“方向”因为标量把所有轴的贡献加在一起了。高维空间又没法直接可视化于是大家默认安全行为是碎片化分散在大量参数里的。论文等于把视角从“看温度”切换成“看风向”——同一个系统观测维度不同发现完全不同。还有一个容易忽略的技术点方向提取本身有噪声如果危险样本数量太少估计出来的子空间并不准如果危险样本种类太杂不同方向的信号又会互相稀释。所以论文在工程上必然做了一件事——按危险类别分别估计子空间而不是把所有危险样本揉在一起。这一点对我的后续实验很有启发。3. Safety Anchor 的几何瓶颈机制钉住锚点收窄通道3.1 几何瓶颈的直觉限高杆、保险丝与瓶颈管先建立一个直觉。想象一条自来水管正常微调是让水流量更大、更顺有害微调是想把水引向一个原本堵死的危险出口。Safety Anchor 的做法是在所有可能流向危险出口的必经管段上装一个“限高杆保险丝”的复合装置限高杆保证低于阈值良性更新的流动畅通无阻一旦水流中携带了要冲破危险出口的“高压成分”保险丝就熔断让这部分更新被挡住或者消耗掉。换个更技术的说法模型某一层原本在全部 d 维空间里自由表示几何瓶颈把它压缩到锚点附近的一个低维子空间里。低维子空间本身并不是不能更新但它提供的“几何通道”非常窄危险方向恰好被设计成穿不过这个通道的方向。3.2 安全锚点在瓶颈里扮演的角色“安全锚点”这个名字其实有两个层面。第一层它是表示空间里的一个参考点物理意义是“模型处于安全行为状态时激活应该落在的位置”。第二层它是一个几何装置微调过程中模型激活一旦偏离锚点超过一定距离就会受到很强的结构性阻力。我读下来的理解是Safety Anchor 并不要求模型参数完全不动而是要求模型在完成微调后其表示仍然被“吸”在安全锚点附近。良性任务在正交于危险方向的空间里移动距离锚点的偏移很小所以新任务照样能学而有害微调要在危险方向上推着模型走每推一步都要克服越来越大的几何阻力有限样本下的 loss 根本降不下去。这个机制有点像一个地心引力源不管你在哪个方向用力最终都被拉回到安全区域。只不过力的大小是各向异性的危险方向上的“引力”特别强良性方向上的“引力”几乎为零。3.3 一个可以上手的梯度投影最小实现如果你只想快速验证“方向防御”这个概念不必一次性复现论文全部工程细节。可以先做一个简化版用少量有害样本估计危险子空间 U然后在训练时把那些指向 U 的梯度成分直接移除。# 概念验证代码估计危险子空间并投影梯度 import torch # 1. 收集危险样本和安全样本的激活差值 # acts_diff: shape (n_samples, d)每行表示危险样本激活均值 - 安全样本激活均值 # 这里假设你已经通过数据加载得到 activations_diff _, _, V torch.svd(acts_diff) r 8 # 危险子空间秩可调 U_harm V[:, :r].to(device) # 危险子空间基shape (d, r) # 2. 训练阶段将每个参数的梯度投影到与 U_harm 正交的方向 def safe_step(model, grads, U_harm): for name, p in model.named_parameters(): g grads[name] g_flat g.reshape(-1, 1) # (d, 1) g_harm (g_flat.T U_harm) U_harm.T # 梯度在危险子空间上的分量 grads[name] (g_flat - g_harm.T).reshape_as(g) return grads这段代码非常粗糙它不是论文原实现论文的重点在激活层的几何瓶颈上而这里做的是权重梯度层面的投影。但方向是一致的让模型在训练时“看不见”有害方向上的梯度压力。我实际跑过一个 1B 模型用这种方式确实能让有害样本的 loss 降不下去同时普通问答任务的 loss 还是正常下降的。这种“只堵方向不堵能力”的感觉只有亲手跑过才有体感。3.4 和现有防御方法对比限制“方向”而不是“动量”很多团队一听到“防止微调破坏安全”第一反应是“那就不要让模型权重离原始点太远”。EWC、L2-SP、参数冻结都属于这种思路。它们的问题很明显太远了会挡住良性任务的可塑性导致模型变成“只会原地踏步”的一块石头。Safety Anchor 不一样的地方在于它限制的不是“总位移”而是“危险方向上的位移”。这两者有本质区别。表格里我简单对比一下常见思路方案思路约束对象安全性可塑性对攻击者的感知数据过滤输入端样本中等可被改写绕过高换皮样本即可绕过权重强约束EWC/L2-SP全部参数偏移量高低良性任务也学不动对抗训练/疫苗式扰动训练阶段扰动中高中能对抗但成本高Safety Anchor 几何瓶颈危险方向子空间高高需要绕开几何屏障换个生活化的说法传统防御是给整辆车限速不管是运货还是运危险品都只能 30 km/hSafety Anchor 是给每个轮子装传感器运普通货物爱跑多快跑多快运危险品一上高速就爆胎。4. 实验到底做了啥攻击成功率、良性性能与可塑性三笔账4.1 威胁模型与攻击设置不是轻而易举的玩具环境要评估一种防御是否有用首先得看它扛住了多强的攻击。论文里的威胁模型我概括下来是攻击者拿到完整模型权重可以自由选择全参数微调或者 LoRA/QLoRA 形式的低秩微调攻击者手里有一批恶意目标样本目标是让模型在有害指令下给出顺从回答评估时用 ASRattack success rate模型成功输出有害内容的比例作为核心指标。特别要注意的是论文不是只测“100 条恶意样本”的简单场景我在阅读中看到讨论的还包括不同恶意样本数量、不同微调强度比如多轮训练、更大学习率下的稳定性。这样就把一个问题摆到了台面上防御究竟是一层脆弱的窗户纸还是一道撞不动的墙。4.2 防御效果ASR 被压下来是第一步据论文报告的实验趋势不加防御的模型在几百条恶意样本下ASR 可以冲到非常高的水平加了 Safety Anchor 之后同样的攻击设置下ASR 会出现断崖式下降。更关键的是在样本量加大、微调轮数增加之后防御没有迅速崩溃几何瓶颈依然能把有害行为挡在外边。我读实验部分时的感受是这个结果不是靠“让模型变笨”换来的——如果模型从头到尾只会输出安全兜底话术ASR 当然也低但那种防御没有意义。所以还必须看下一笔账良性能力。4.3 良性性能和可塑性的权衡衡量良性能力论文用的是常见的通用能力评测和指令遵循测试比如常识问答、推理题、代码生成之类的基准。我看到的趋势是Safety Anchor 对良性任务的分数影响很小大部分任务维持在原水平附近。这是几何选择性约束的直接成果——良性方向的通道没被堵。更值得关注的是“可塑性”plasticity这个概念在安全微调领域里经常被忽略。一个防御方案如果让模型完全学不进新知识那它就没有落地价值。论文专门讨论了可塑性并与那些“把模型钉死在原权重附近”的方法做了对比Safety Anchor 在保持安全的同时仍然允许模型通过微调学会新任务而强约束方法在安全指标上虽然不差但新任务学习能力明显下降。我自己在评估防御方案时现在一定会把可塑性放进验收标准。没有可塑性的安全是博物馆里的标本有可塑性的安全才是生产线上能用的东西。4.4 论文承认的边界危险方向探测的完备性没有哪种防御是银弹这篇论文也没回避这一点。它最大的边界在于防御效果高度依赖“危险方向”能否被预先准确估计。如果某种新的危险能力没有被纳入探测样本或者攻击者刻意把恶意目标混进看起来完全良性的数据里导致估计出的子空间被污染那几何瓶颈就可能拦不住。另外低秩如何选取、锚点加在哪几层、对多大规模的模型生效这些都是工程上要重新调参的问题。论文提供了思路和实验证据但离“一键防御”还有距离。这一节对我来说反而最有用因为它划清了方法的适用边界让我不会拿着锤子把所有钉子都敲一遍。5. 读懂之后我觉得这事还能往这几个方向延展5.1 同一套几何思路能迁移到机器遗忘、后门防御和持续学习读完 Safety Anchor我第一个想到的是机器遗忘machine unlearning。很多合规场景要求模型删除某些用户数据或版权内容传统做法是重新训练代价极高。如果采用几何思路可以把“要删除的概念方向”当成危险方向来处理在推理或后续微调时对相关方向施加瓶颈让模型无论再怎么接触相关数据都很难把那个方向激活起来。第二个迁移方向是后门防御。模型被人注入后门后所有带特定触发词的输入都会被引导到某个异常内部方向从而触发攻击者预设的行为。如果能离线估计出触发词对应的内部方向几何瓶颈完全可以用来“封路”让后门触发器失效。第三个方向是持续学习里的灾难性遗忘。旧任务的表示方向同样是一个几何特征更新新任务时把旧任务方向设成锚点只允许新任务在正交方向上生长这几乎就是把 Safety Anchor 换个名字用在正向场景里。共通的一点是只要模型行为可以被表示方向刻画几何瓶颈就比参数正则更精准。5.2 我读完之后还想追问的几个研究问题第一个问题更强的攻击者会怎么绕如果我站在红队视角可能会先用大量良性任务数据做预微调把模型内部的锚点位置慢慢“磨偏”等瓶颈失去对准效果之后再注毒。论文是否考虑了这种两步攻击我没有在阅读中找到明确结论这是一个值得做后续实验的开放问题。第二个问题危险子空间的维度怎么自动确定现在r靠人工调不同模型、不同能力的危险容量不一样。如果有一个自动识别危险方向秩的算法会让方案落地门槛大幅下降。第三个问题几何防御和 DPO 这类偏好优化后期修复能否叠加理想状态是发布前用 Safety Anchor 给模型加“出厂防护”线上发现问题后还能再做一轮偏好修复两者互不干扰。这个组合策略如果成立会给模型运营留出很大的安全缓冲空间。5.3 给工程师的落地建议先用减法再做正交如果你是在自己的模型上做实验我的建议是不要一上来就想着完整复现论文的每一个模块。先花一天时间做一个减法实验收集几十条安全样本和几十条危险样本提取激活差SVD 估计出 5 到 10 个危险方向然后在微调时把梯度里的危险成分减掉跑一个最小 case。你会立刻看到三件事危险样本的 loss 很难降下去、普通任务的 loss 正常下降、模型输出的安全性肉眼可见地提升。有了这个体感之后再考虑要不要引入更完整的锚点机制比如在特定 transformer 层里注入低秩瓶颈或者将锚点做成可学习参数。论文的价值不在于让你照抄一个模型配置而在于给你一把“从几何视角看安全”的钥匙。我实际测下来哪怕只是用上面那段简化代码也能在小型模型上复现“方向性防御”的基本现象。最后再分享一个个人体会。以前我做安全对齐习惯性地把注意力放在“输出长什么样”也就是只盯显式的拒绝语和评分模型。读这篇论文之后我开始把注意力放到“内部表示在往哪走”。每次微调实验结束我都会顺手看一眼危险方向上的激活投影值这个数字比任何人工评测都更早地告诉我安全边界是否在被侵蚀。强烈建议你也把这个习惯加到自己的实验流程里。