模糊梯度防御的真相:从对抗样本攻防到稳健性评估方法论

发布时间:2026/10/13 8:27:46
模糊梯度防御的真相:从对抗样本攻防到稳健性评估方法论
对抗样本这碗饭吃到今天已经越来越难了。每隔一阵子就会有一个团队宣称自己造出了“无法攻破”的模型但再过几个月往往又有人拿着新的攻击方法把它撞碎。大概在2018年前后那批号称稳健的防御下场尤其惨烈。那段时间我正好在做模型安全评估几乎每个防御方案都要亲手去打一遍打到最后发现一个共性很多防御之所以“看起来稳固”并不是因为它们真的稳而是因为攻击者拿不到有意义的梯度。这篇论文《Obfuscated Gradients Give a False Sense of Security》把这类现象正式命名并系统性地拆掉了所有靠“藏梯度”来防攻击的思路。这篇论文的标题可以直译成“模糊梯度带来虚假的安全感”。它做的事情不是提出一个新的攻击工具而是对当时一大堆已经发表、甚至拿过防御挑战赛名次的防御方案做了一次集中“打假”。作者团队把模糊梯度分成三种形态逐一给出针对性攻击最后结论很干脆这些靠梯度遮蔽撑起来的防御绝大多数都能被绕过。对搞对抗攻防、可信机器学习、模型鲁棒性评估的人来说这篇论文基本属于必读。即使你没打算做攻击它也能帮你建立一个重要的判断标准什么样的防御才值得信。我会按论文的论证主线来拆解先讲它如何定义“模糊梯度”再讲三类梯度遮蔽的内部机制接着展开核心里面最实用的两个攻击方法最后把实验结论和方法论启示一起复盘顺带分享我在实际评估中踩过的坑。1. 论文回顾的核心问题与整体论证思路1.1 背景防御为什么总是看起来很强在对抗样本研究早期防御方的思路其实很朴素既然攻击依赖于梯度那我把梯度搞坏攻击是不是就失效了很多工作也确实沿着这个方向做比如对输入先做去噪、压缩把梯度弄得支离破碎或者给网络加随机性让每次前向计算得到的梯度都不一样还有的用蒸馏这种训练技巧让模型输出变得很平滑把梯度压到几乎消失。这些方案在论文里都报出了很高的抗攻击成功率有些甚至号称把攻击成功率压到了个位数以下。但问题是很多防御的作者只在少数几种经典攻击比如快速梯度符号法 FGSM 或者简单的迭代攻击下做了测试。一旦攻击者换一种不依赖精确梯度的优化方式防御效果就漏了馅。1.2 核心问题什么才算“真正攻不破”论文的核心问题其实是一个评估标准问题你凭什么说一个防御是稳健的作者明确提出了一个判断原则——如果一个防御确实稳健那么无论攻击者怎么绕他都找不到一个足够小的扰动来让模型犯错。反过来如果你只是让基于梯度的搜索失效那只能说明攻击者暂时没找到路不代表路不存在。这个原则看着简单实际操作中很容易被忽略。很多研究者在评估防御时本质上只验证了“某种攻击失败了”而不是“所有可能的攻击都失败了”。论文把这层窗户纸捅破之后整个评估方法论才慢慢走上正轨。1.3 论证主线先定义“模糊梯度”再逐个攻破整篇论文的论证结构可以压缩成三步第一步定义什么是“模糊梯度”。作者把梯度被破坏的情况归纳为三种梯度破碎、随机梯度、梯度消失或爆炸。第二步针对每种梯度遮蔽设计对应的攻击策略。第三步拿这些策略去攻击当时多个号称稳健的防御用实验结果说明“模糊梯度”并不等于安全。这个逻辑最有价值的地方是它没有停留在“我能攻破”这个层面而是把攻破背后的原因抽象成了可复用的方法论。只要防御呈现出这三种梯度遮蔽中的某种特征攻击者就有现成的思路来处理而不是每次都要从零开始逆向。2. 三种梯度遮蔽形态防御为什么会“看着安全”2.1 梯度破碎可微性的错觉第一类叫梯度破碎英文是 shattered gradients。典型现象是你尝试用反向传播计算梯度得到的梯度数值要么是零要么像噪声一样杂乱无章根本没法用来做梯度下降。问题出在防御本身引入了一些不可微或者数值不稳定的预处理模块。最典型的例子是 JPEG 压缩。JPEG 的量化步骤在数学上是不可导的你没法直接对它求梯度。再比如总变差最小化这类方法它们会把输入图像投影到一个“低纹理”的子空间这个投影过程经过多次迭代之后反向传播的梯度几乎处处失效。还有一类基于 top-k 池化的网络结构前向时只保留部分神经元激活反向时大量梯度直接归零也会造成破碎。2.2 随机梯度移动靶的诱惑第二类叫随机梯度stochastic gradients。这类防御的思路是我让模型每次前向都有一点点不一样比如随机裁剪、随机缩放、随机加噪声那么攻击者每次计算出来的梯度都不一样他就没法稳定地沿一个方向更新扰动。这个想法理论上有它的道理但论文指出了致命问题随机化改变的只是单次计算的梯度如果攻击者把多次随机变换的梯度取平均得到的是“期望梯度”这个期望梯度是稳定的而且能反映模型整体的决策倾向。也就是说防御者以为自己是在打移动靶但攻击者直接瞄准靶心的平均位置打。2.3 梯度消失与爆炸饱和层的假象第三类是最经典的梯度消失和爆炸。防御蒸馏就是最好的例子。蒸馏的原理是用一个高温 softmax 产生的软标签去训练学生网络让学生网络的输出变得非常平滑决策边界离数据点很远从而导致模型在大多数输入上的梯度都比较小甚至接近零。这类防御在 MNIST 这类简单数据集上表现特别好因为模型本身就能以极高置信度分类蒸馏之后 logits 确实会被压缩得很厉害。但作者发现梯度小只能骗过那些依赖梯度幅值的攻击如果攻击者改用针对 logits 的优化攻击绕开 softmax 的饱和区还是能找到有效的扰动方向。防御蒸馏成立的前提是有足够的“空间”让所有对抗样本都离决策边界很远但实际数据集往往没有这个条件。下面把三种形态放进一张表里做对比方便随手查阅。梯度遮蔽类型典型防御手段表面现象为什么脆弱对应攻击思路梯度破碎JPEG压缩、总变差最小化、top-k池化梯度接近噪声或大量为零前向过程不可微反向梯度失真可微近似替代随机梯度随机裁剪、随机缩放、随机噪声每次计算梯度都不一样单次梯度不代表整体决策期望梯度梯度消失/爆炸防御蒸馏、逆向交叉熵梯度幅值极小或异常大梯度无法提供有效的方向信息直接优化logits3. 绕过梯度遮蔽的核心攻击方法3.1 BPDA让梯度穿过不可微的墙BPDA 的全称是 Backward Pass Differentiable Approximation简单说就是“前向用真函数反向用近似函数”。这套方法专门用来对付梯度破碎类的防御。假设防御模型的完整前向过程是 f g ∘ h其中 h 是不可微的预处理比如 JPEG 压缩g 是后面正常的分类网络。攻击者做反向传播时真正需要的是 ∂f/∂x但 h 不可导梯度算不出来。BPDA 的做法是前向传播依然老老实实用真实的 h保证你拿到的模型输出没变反向传播时换一个可微的近似函数 h̃ 来替 h 计算梯度。听起来有点不讲武德但论文里明确说这是有理论依据的攻击者其实不需要精确的梯度只需要一个和真实梯度方向足够一致的近似梯度就能持续优化扰动。我用一段伪代码写一下核心逻辑方便理解。# 伪代码BPDA 核心思路 def bpda_attack(x, model, approx_transform, g, num_iters): delta torch.zeros_like(x, requires_gradTrue) for i in range(num_iters): # 前向真实防御过程不可微的变换用真实版本 x_adv x delta x_transformed real_transform(x_adv) # 不可微但只用于前向 logits model(x_transformed) loss attack_loss(logits, target_class) # 反向把变换部分的梯度替换为近似版本 # 关键点让梯度流经 approx_transform 而不是 real_transform loss.backward() grad delta.grad # 更新扰动 delta.data - step_size * grad.sign() delta.grad.zero_() return x delta这里最关键的设计在反向路径的处理。代码层面通常是通过修改 hook 或者自定义反向函数来实现前向走原路反向走近似路。3.2 EOT对随机化取期望瞄准移动靶的圆心EOTExpectation over Transformation直译就是“对变换求期望”。这套方法专门对付随机梯度类的防御。既然模型每次前向都做随机变换那你做一次梯度计算只能反映某个随机状态下的情况很不稳定。EOT 的思路很简单一次梯度更新之前随机采样多个变换分别计算梯度然后取平均。数学上攻击者优化的目标是让“所有随机变换下的平均损失”最大所以梯度方向应该是 E[T(∂L/∂x)]而不是某个 t 下的 ∂L/∂x。实际操作就是把输入来回前向多次每次做不同的随机变换把梯度累积起来除以次数。论文里通常取几十次采样已经足够稳定。EOT 不仅能打随机化的防御还有一个额外收获用 EOT 得到的对抗样本往往在真实环境下也更稳定因为它在多个变换下都有效自然具备一定的迁移性。3.3 综合攻击流程BPDA EOT CW 的组合方式论文里最精彩的部分是把这些方法组合起来用。一个防御可能既有不可微的预处理又有随机模块那你就不能只选一个方法。实际操作流程大概是这样的如果防御有不可微或梯度破碎的模块就用 BPDA 找一个可微近似来替代反向梯度。如果防御还有随机化模块就在 BPDA 的基础上每个批次多采样几个随机变换用 EOT 把梯度平均掉。如果模型还存在梯度消失的问题比如蒸馏后的平滑输出就不要再死磕交叉熵损失了直接换成 CW 攻击那种基于 logits 的损失max(max_i≠t Z_i(x) − Z_t(x) κ)让攻击直接作用在分类器未饱和的输出上。我实际测试下来组合使用比单独使用任何一种方法都稳健。因为很多防御方案为了安全性会叠好几层保护你用单一攻击打不穿一层就卡住了但组合攻击可以同时穿透多层。3.4 实操心得近似函数怎么选BPDA 的效果好坏很大程度上取决于近似函数选得准不准。我自己的经验是优先选择“在局部行为上尽量接近原变换”的显式近似。比如 JPEG 的量化步骤可以做一个软量化把舍入操作替换成带温度系数的平滑函数。另外要注意一个容易踩的坑前向和反向使用不同的函数本质上是把优化问题变成了近似梯度下降方向不一定完全准确。如果近似太差攻击可能走偏甚至不收敛。判断近似质量的简单方法是随机选几个输入对比真实变换前后的距离变化以及近似变换前后的距离变化相差越小越可靠。理论上没有绝对保证但在论文覆盖的多个防御上BPDA 的实际表现相当能打。它的思想也逐渐被后续许多评估工具吸收成为对抗攻击工具箱里的标准配置之一。4. 实验设计与结果解读那些被攻破的防御4.1 评估对象与攻击配置论文回顾实验部分时值得注意一点他们不是只挑软柿子捏而是把一个时期内已经发表、声称有高鲁棒性的代表性防御都拉进来测试范围覆盖多种类型的防御策略。攻击配置上作者没有只跑一种攻击而是分别做了普通迭代攻击、CW 攻击、BPDA、EOT以及它们的组合版本。指标上兼顾了攻击成功率和扰动大小尤其关注那些扰动足够小、人眼几乎看不出来的对抗样本这才是最危险的威胁模型。4.2 关键结果带来的直觉整体结论非常直接绝大多数声称稳健的防御都被成功绕过。原本防御论文里报告的攻击成功率可能只有百分之几但在这些针对性攻击下成功率普遍回升到很高的水平而且扰动量级并没有大到离谱。特别让我印象深刻的是防御蒸馏的结果。原论文在 MNIST 上花了很大力气部署蒸馏给出的结论是攻击成功率极低。但这篇论文在 MNIST 和 CIFAR 上都做了测试发现只要换用直接优化 logits 的 CW 攻击防御蒸馏很快就被击穿。这个结果给了我一个很深的印象一个防御在一个数据集上有效换一个数据集就失效说明它的安全性依赖的是数据集特性而不是真正的鲁棒性机理。4.3 为什么说“模糊梯度不是安全”论文反复强调一个观点模糊梯度既不是防御安全的充分条件也不是必要条件。这句话值得单独琢磨。不是充分条件意思是梯度模糊不代表攻击者找不到对抗样本。你可以通过近似梯度、期望梯度、迁移攻击等非精确信息来搜索对抗样本。不是必要条件意思是即使梯度完全清晰一个模型也可以真正稳健对抗样本根本不存在。梯度信息只是搜索工具模型是否稳健归根结底取决于它是否存在一个足够小的对抗扰动邻域。工具找不到路不代表路不存在。这个区分对研究者特别重要。很多人评估防御时把“攻击失败”和“防御成功”画上等号这是方法论的重大误区。论文的价值就在于把这两件事彻底拆开。5. 对稳健性评估的方法论启示与操作清单5.1 判断防御是否稳健的丈量尺读过这篇论文之后我对“看到一个防御方案怎么快速判断它值不值得信”有了比较稳定的判断框架。核心就看三件事防御方是否展示了多种攻击下的评估结果而不是只挑一两个弱的攻击。是否有尝试针对梯度遮蔽的专项攻击比如 BPDA、EOT 或者迁移攻击。是否公开了模型权重和评估代码让第三方能够复现。如果什么都不开源又宣称“无法攻破”那基本可以直接打一个问号。5.2 我在实际评估对抗防御时固定的五步流程受这篇论文启发我在自己的模型鲁棒性评估项目里固定了一套流程这里分享给你参考。步骤要做什么目的1先跑常规攻击FGSM、PGD、CW建立基线看防御在常见攻击下的表现2检查是否存在可微性问题寻找不可微模块、随机模块、梯度饱和模块3若有不可微模块实现 BPDA 近似攻击绕过梯度破碎和不可微阻断4若有随机模块加入 EOT 期望梯度绕过随机化防御5迁移攻击测试用白盒模型生成对抗样本直接打到目标模型上覆盖“梯度信息完全缺失”的情况这个流程不一定能保证找到所有对抗样本但它覆盖面足够广基本能帮你识别出“假防御”。每做完一个防御评估我都会把前三步当作最低要求缺失任何一步都认为评估不完整。5.3 常见问题与排查技巧实录在复现这套攻击的过程里我遇到过不少问题整理几条对你有用的问题现象可能原因排查与解决BPDA 攻击完全不收敛近似函数与原变换偏差太大把近似函数换回更贴近原变换的形式逐步测试近似误差梯度很大但攻击效果差损失函数选错走了饱和区间改用直接对 logits 优化的 CW 变体EOT 采样次数太少梯度抖动随机变换方差较大增大采样次数或者减小步长攻击在训练集成功但测试集失败过拟合到特定样本构建对抗样本时多做几个初始点保留效果最好的防御代码里掩埋了大量自定义层反向路径可能被手动改写仔细核对前向与反向是否一致必要时自己重写反向函数我自己最常踩的坑是贪图方便直接用现成的攻击库没有针对防御的具体结构做调整。梯度遮蔽类防御恰恰最吃“针对性”你不针对它的遮蔽方式做设计攻击成功率就上不去。这也是为什么论文里的方法论比任何一个具体的攻击工具都值钱。写在最后我在实际项目中试过很多防御方案每次重新读这篇论文都会有新的感受。最初我以为它只是在“证明别人不行”后来才慢慢意识到它真正想立起来的是一套评估的底线不能因为攻击者暂时没找到路就宣布这条路不存在。现在我每评估一个防御都会下意识问自己一句是真的稳健还是梯度又在骗我如果你也想做对抗防御的研究或者正在设计一个号称“安全”的模型我建议先把这篇论文里的方法跑一遍再去谈你的防御效果。这样你会少走很多弯路也能省下不少推翻重来的时间。