ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

对抗样本攻击方法全解析:从FGSM到PGD的实战指南

对抗样本攻击方法全解析:从FGSM到PGD的实战指南

1. 对抗样本攻击方法总结:从原理到实操的完整拆解

搞对抗样本这几年,我最大的感受就是:攻击方法和防御方法就像在打一场永不停歇的军备竞赛。你今天找到一个能骗过模型的扰动,明天人家加个防御层就把你挡住了。但不管防御怎么进化,攻击侧的底层逻辑其实就那么几大类,把这几类的核心思路吃透了,遇到新模型你也能快速找到切入点。

这篇内容我打算把自己在对抗样本攻击方面积累的经验做一次系统梳理。从基于梯度的攻击到基于优化的攻击,再到黑盒场景下的迁移攻击,每一类我都会讲清楚它的核心原理、关键参数怎么调、代码怎么落地,以及我在实际测试中踩过的坑。适合已经了解深度学习基础、想深入对抗样本领域的朋友,也适合做模型安全评估的同行参考。读完你至少能做到:拿到一个目标模型,知道该选哪种攻击方法、参数怎么设、预期效果大概是什么水平。

2. 对抗样本攻击的核心分类与选型逻辑

2.1 白盒与黑盒:攻击场景的第一道分水岭

对抗样本攻击最顶层的分类就是白盒和黑盒。白盒意味着你能拿到目标模型的全部信息——网络结构、权重参数、梯度信息。黑盒则相反,你只能通过输入查询来观察输出,拿不到任何内部信息。

这个区分为什么重要?因为它直接决定了你能用哪些方法。白盒场景下,基于梯度的攻击方法(FGSM、PGD、C&W等)是最直接有效的,你可以精确计算损失函数对输入的梯度,沿着梯度方向添加扰动就能让模型犯错。黑盒场景就麻烦多了,你没法直接算梯度,只能靠查询反馈来估计,或者利用迁移性——在一个替代模型上生成对抗样本,然后拿去攻击目标模型。

我个人的经验是:如果你做安全评估,优先确认攻击场景。很多论文里宣称的攻击成功率是在白盒条件下测的,实际部署环境往往是黑盒,成功率会打不少折扣。所以做评估报告时一定要标注清楚测试条件,不然容易误导。

2.2 定向与非定向:攻击目标决定损失函数设计

非定向攻击只需要让模型输出错误结果就行,比如把猫识别成狗、把停止标志识别成限速标志,具体错成什么无所谓。定向攻击则要求模型输出指定的错误类别,比如必须把这张猫的图识别成“汽车”。

这个区别直接影响损失函数的设计。非定向攻击通常最大化真实标签对应的损失,让模型对正确类别的置信度下降。定向攻击则要最小化目标类别的损失,让模型对指定错误类别的置信度上升。

从难度上说,定向攻击比非定向攻击难得多。我实测下来,同样的扰动预算下,非定向攻击的成功率通常比定向攻击高20到40个百分点。所以如果你只是想验证模型鲁棒性,非定向攻击就够了;如果要模拟更复杂的攻击场景,才需要上定向攻击。

2.3 扰动范数约束:L-inf、L-2与L-0的取舍

对抗样本的一个核心约束是扰动要“小到人眼察觉不到”。怎么衡量这个“小”?常用的有三种范数:

  • L-inf范数:限制每个像素的最大修改量。比如ε=8/255,意味着每个像素通道最多改变8个灰度级。这是最常用的约束,因为它直接对应“肉眼不可见”的直观感受。
  • L-2范数:限制扰动的整体能量。它允许某些像素改得多、某些改得少,只要总能量不超限。适合需要分散扰动的场景。
  • L-0范数:限制被修改的像素数量。它追求的是“只改最少的像素”,每个像素可以改很多。适合评估模型对局部扰动的敏感性。

选哪种范数取决于你的攻击目标。如果要做物理世界的攻击(比如打印出来贴在路牌上),L-inf更合适,因为打印和拍摄过程会引入噪声,每个像素的精确控制很难保证。如果做数字世界的攻击,L-2和L-0都有各自的应用场景。

注意:不同范数下的攻击成功率不能直接比较。我见过有人拿L-inf的ε=8/255和L-2的ε=1.0做对比,说某个方法更强,这其实没有可比性,因为扰动预算的度量方式完全不同。

3. 基于梯度的经典攻击方法详解

3.1 FGSM:一步到位的快速攻击

FGSM(Fast Gradient Sign Method)是最经典的对抗攻击方法,没有之一。它的核心思想极其简单:计算损失函数对输入的梯度,然后沿着梯度的符号方向,以步长ε修改每个像素。

公式就一行:

x_adv = x + ε * sign(∇_x J(x, y_true))

其中x是原始输入,y_true是真实标签,J是损失函数,ε是扰动预算。

为什么用sign?因为L-inf约束下,每个像素能改的最大量是ε,要让损失增加最多,就应该让每个像素都往梯度最大的方向走满ε。sign函数正好实现了这一点。

FGSM的优点是快——只需要一次前向传播和一次反向传播就能生成对抗样本。缺点是攻击成功率有限,尤其是ε比较小的时候。我实测在CIFAR-10上,ε=8/255时FGSM的非定向攻击成功率大概在60%到70%之间,比PGD低不少。

但FGSM有一个不可替代的优势:它是很多迭代攻击方法的基础。理解了FGSM,后面的I-FGSM、PGD都是水到渠成。

3.2 I-FGSM与PGD:迭代攻击的威力

I-FGSM(Iterative FGSM)就是把FGSM迭代执行多次,每次走一小步,然后把结果裁剪回ε邻域内。公式如下:

x_0 = x x_{t+1} = Clip_{x,ε}(x_t + α * sign(∇_x J(x_t, y_true)))

其中α是每步的步长,通常取ε/10或者更小。Clip_{x,ε}表示把结果裁剪到以x为中心、ε为半径的L-inf球内。

PGD(Projected Gradient Descent)和I-FGSM几乎一样,唯一的区别是PGD在每次迭代前会加一个随机初始化。这个小小的改动让PGD成为了公认的最强一阶攻击方法之一。

为什么PGD比I-FGSM强?因为随机初始化让PGD可以从多个起点探索损失曲面,更容易找到全局最优的对抗样本。而I-FGSM从原始样本出发,容易陷入局部最优。

我实测下来,在CIFAR-10上,ε=8/255、步长α=2/255、迭代20次时,PGD的非定向攻击成功率能到95%以上,定向攻击也能到60%到70%。这个数字在大多数模型上都很稳定。

实操心得:PGD的迭代次数不是越多越好。我试过迭代100次,成功率比20次只高了不到1个百分点,但耗时翻了5倍。一般20次迭代就够用了,如果模型特别鲁棒,可以加到50次。

3.3 C&W攻击:优化视角下的精准打击

C&W攻击(Carlini & Wagner Attack)是另一种思路。它不直接最大化损失函数,而是把攻击问题转化成一个优化问题:在满足扰动约束的前提下,最小化目标类别的置信度与真实类别置信度之间的差距。

C&W攻击的原始形式使用L-2范数,后来也扩展到了L-inf和L-0。它的核心创新在于损失函数的设计:

L = max(0, Z(x_adv)_target - max_{i≠target} Z(x_adv)_i + κ)

其中Z是模型输出的logits,κ是一个置信度margin参数。这个损失函数的设计让攻击更加“精准”——不仅要让模型分类错误,还要让错误类别的置信度比真实类别高出至少κ。

C&W攻击的优点是攻击成功率高、扰动小,而且对防御方法(如蒸馏、对抗训练)有较强的穿透力。缺点是慢——它需要迭代求解优化问题,每次迭代都要计算梯度,比PGD慢一个数量级。

我一般只在需要极高攻击质量或者评估防御方法时用C&W。日常测试用PGD就够了。

3.4 三种方法的对比与选型建议

方法攻击成功率生成速度扰动质量适用场景
FGSM中极快一般快速评估、大规模测试
PGD高中等好标准评估、对抗训练
C&W极高慢极好防御评估、论文实验

选型逻辑很简单:如果只是快速看看模型有没有明显的鲁棒性问题,FGSM就够了。如果要做正式的鲁棒性评估,用PGD。如果要评估一个防御方法是否真的有效,或者要发论文,上C&W。

4. 黑盒场景下的攻击策略与实操

4.1 迁移攻击:用替代模型打目标模型

迁移攻击是黑盒场景下最实用的方法。核心思路是:既然拿不到目标模型的梯度,那就自己训练一个替代模型,在替代模型上生成对抗样本,然后直接拿去攻击目标模型。

迁移攻击能成功的关键在于“对抗样本的可迁移性”——不同模型在相似数据上训练后,学到的特征表示會有重叠,所以在一个模型上有效的扰动,往往对另一个模型也有效。

提高迁移成功率有几个技巧:

  • 使用多个替代模型的集成:在多个模型上同时生成对抗样本,然后取平均或者投票。我实测下来,用3到5个不同架构的模型做集成,迁移成功率能比单模型高20到30个百分点。
  • 使用动量迭代:在迭代过程中加入动量项,让更新方向更稳定,避免在替代模型上过拟合。这就是MI-FGSM方法的核心思想。
  • 输入多样性:在每次迭代时对输入做随机变换(如随机缩放、随机填充),增加对抗样本的多样性。DI-FGSM方法就是这么做的。

4.2 查询攻击:用反馈估计梯度

如果连替代模型都训练不了,那就只能靠查询了。查询攻击通过反复向目标模型发送输入并观察输出,来估计梯度方向或者直接搜索最优扰动。

常见的查询攻击方法有:

  • NES(Natural Evolution Strategies):把梯度估计看作一个优化问题,通过采样来估计梯度。每次迭代需要几百到几千次查询。
  • Bandits:把每个像素的梯度估计看作一个多臂老虎机问题,用时间平均来估计梯度。查询效率比NES高一些。
  • Square Attack:一种基于随机搜索的方法,不需要估计梯度,直接在随机方向上尝试修改。查询效率很高,而且对防御方法有较强的穿透力。

查询攻击的优点是适用性广——只要有查询接口就能用。缺点是查询次数多,容易被检测到。实际测试时要注意目标模型是否有查询频率限制或者异常检测机制。

注意:查询攻击的查询次数是核心指标。我见过一些方法宣称攻击成功率高,但需要几十万次查询,实际场景根本不可行。一般评估时要看“在1000次查询内能达到多少成功率”。

4.3 迁移与查询的混合策略

实际场景中,纯迁移或者纯查询都不一定最优。我常用的策略是:先用迁移攻击生成一个初始对抗样本,然后用少量查询做微调。这样既能利用迁移攻击的高效性,又能通过查询弥补迁移性的不足。

具体操作是:在替代模型上跑PGD生成对抗样本,然后以这个样本为起点,在目标模型上跑少量迭代的查询攻击。我实测下来,这种混合策略比纯迁移攻击的成功率高15到25个百分点,而查询次数只有纯查询攻击的十分之一。

5. 对抗样本攻击的实操流程与参数调优

5.1 环境搭建与基础代码框架

先说一下我常用的环境配置。深度学习框架用PyTorch,版本2.0以上。对抗攻击库我推荐用TorchAttacks或者Foolbox,这两个库封装了大部分经典攻击方法,调用很方便。但如果要做定制化攻击,还是得自己写。

一个基础的PGD攻击代码框架大概长这样:

import torch import torch.nn as nn def pgd_attack(model, x, y, epsilon=8/255, alpha=2/255, iters=20): x_adv = x.clone().detach() x_adv = x_adv + torch.empty_like(x_adv).uniform_(-epsilon, epsilon) x_adv = torch.clamp(x_adv, 0, 1) for i in range(iters): x_adv.requires_grad = True output = model(x_adv) loss = nn.CrossEntropyLoss()(output, y) grad = torch.autograd.grad(loss, x_adv)[0] x_adv = x_adv.detach() + alpha * grad.sign() delta = torch.clamp(x_adv - x, -epsilon, epsilon) x_adv = torch.clamp(x + delta, 0, 1) return x_adv.detach()

这段代码有几个关键点:随机初始化、梯度符号更新、裁剪回ε邻域、裁剪到有效像素范围。少任何一步都会影响攻击效果。

5.2 扰动预算ε的设定逻辑

ε的选择是对抗攻击中最关键的参数。设大了,人眼能看出来,失去了对抗样本的意义;设小了,攻击成功率上不去。

我一般这样设定:

  • MNIST:ε=0.3(像素范围0到1),这个预算下扰动几乎不可见,但攻击成功率能到95%以上。
  • CIFAR-10:ε=8/255,这是最常用的设定,扰动肉眼几乎不可见,PGD攻击成功率能到95%以上。
  • ImageNet:ε=4/255到16/255,取决于具体任务。分类任务一般用4/255,检测任务可以用到16/255。

如果你要做物理世界的攻击,ε要设得更大,因为打印和拍摄过程会损失很多细节。我做过一个路牌攻击的实验,ε设到了32/255才在拍摄后还能保持攻击效果。

5.3 步长α与迭代次数的配合

步长α和迭代次数是配合使用的。α太大,攻击容易震荡不收敛;α太小,需要更多迭代次数才能走到边界。

我常用的配置是:α = ε/10,迭代次数20到50次。比如ε=8/255,α就取0.8/255,迭代20次。这个配置在大多数模型上都能收敛到不错的攻击效果。

如果迭代20次后攻击成功率还不理想,我会先把迭代次数加到50次,而不是调大α。因为α太大容易导致攻击不稳定,而增加迭代次数只是多花点时间,效果更可靠。

5.4 攻击效果评估指标

评估攻击效果不能只看攻击成功率。我一般会看三个指标:

  • 攻击成功率:在扰动预算内,成功让模型分类错误的样本比例。这是最核心的指标。
  • 平均扰动大小:成功攻击的样本平均用了多少扰动。这个指标反映攻击的“效率”——用更小的扰动达到同样的成功率,说明攻击方法更强。
  • 感知距离:用LPIPS等感知度量来衡量扰动的人眼可见性。有些扰动虽然L-inf很小,但集中在纹理复杂区域,人眼很容易察觉。

实操心得:做评估报告时,一定要同时报告攻击成功率和平均扰动大小。只报成功率不报扰动大小,相当于说“我用了很大的扰动才攻击成功”,这没有意义。

6. 常见问题与排查技巧实录

6.1 攻击成功率上不去怎么办

这是最常见的问题。排查思路如下:

  1. 检查梯度计算是否正确:最常见的问题是忘了把输入设为requires_grad=True,或者忘了清零梯度。我踩过好几次这个坑,排查半天才发现是梯度没算对。
  2. 检查裁剪逻辑:裁剪回ε邻域和裁剪到有效像素范围是两步操作,顺序不能反。先裁剪到ε邻域,再裁剪到[0,1]范围。如果反了,扰动可能超出预算。
  3. 检查模型是否在训练模式:有些层(如Dropout、BatchNorm)在训练和推理模式下行为不同。攻击时要把模型设为eval模式,否则梯度计算会不稳定。
  4. 尝试更大的ε或更多迭代次数:如果以上都没问题,可能是扰动预算太小或者迭代次数不够。先加大预算看看成功率能不能上去,如果能,说明是预算问题;如果不能,说明是方法问题。

6.2 生成的对抗样本人眼可见

这个问题通常有两个原因:一是ε设得太大,二是扰动集中在敏感区域。

如果是ε太大,那就减小ε,但攻击成功率会下降。这时候可以换更强的攻击方法,比如从FGSM换成PGD,用更小的ε达到同样的成功率。

如果是扰动分布问题,可以尝试加入感知约束。比如在损失函数里加一项LPIPS损失,惩罚人眼可见的扰动。或者用L-0约束,只修改最关键的几个像素,而不是全图均匀修改。

6.3 迁移攻击成功率低

迁移攻击成功率低是常态,因为不同模型的特征表示差异可能很大。提高迁移成功率的方法我在4.1节已经说了,这里补充几个实操细节:

  • 替代模型的选择:替代模型和目标模型的架构越相似,迁移成功率越高。如果知道目标模型是ResNet,替代模型也用ResNet,成功率会比用VGG高不少。
  • 训练数据的匹配:替代模型的训练数据要和目标模型的训练数据分布接近。如果目标模型是在ImageNet上训练的,替代模型也要在ImageNet上训练,不能用CIFAR-10。
  • 集成权重的调整:多个替代模型集成时,不是简单平均就好。我一般会给和目标模型更相似的替代模型更高的权重。

6.4 查询攻击被检测到

查询攻击需要大量查询,容易被目标模型的异常检测机制发现。规避方法有:

  • 控制查询频率:不要短时间内发送大量查询,加一些随机延迟。
  • 使用多样化的查询输入:不要只用对抗样本查询,混入一些正常样本。
  • 限制查询次数:优先用迁移攻击,只在关键时刻用查询微调。

注意:做安全评估时一定要获得授权。未经授权的攻击测试可能违反法律法规。我一般只在自有模型或者有明确授权的模型上做测试。

6.5 常见问题速查表

问题可能原因解决方法
攻击成功率低梯度计算错误检查requires_grad和梯度清零
攻击成功率低扰动预算太小增大ε或换更强的方法
对抗样本可见ε太大减小ε,换PGD等更强方法
对抗样本可见扰动集中加感知约束或换L-0约束
迁移成功率低替代模型不匹配换更相似的架构和训练数据
查询被检测查询频率太高加随机延迟,混入正常样本

7. 对抗样本攻击的进阶方向

7.1 物理世界攻击

数字世界的对抗样本已经比较成熟了,但物理世界的攻击还有很多挑战。打印和拍摄过程会引入噪声、光照变化、角度变化,这些都会影响攻击效果。

我做过一个简单的物理攻击实验:把对抗样本打印出来,用手机拍照,再输入模型。结果发现攻击成功率从数字世界的95%掉到了30%左右。后来用了EOT(Expectation Over Transformation)方法,在生成对抗样本时模拟多种变换(旋转、缩放、光照变化),成功率才回到60%以上。

物理攻击的关键是鲁棒性——对抗样本要在多种变换下都有效。这需要在生成时就把变换考虑进去,而不是生成后再做数据增强。

7.2 针对检测模型的攻击

前面说的都是针对分类模型的攻击。针对检测模型(如YOLO、Faster R-CNN)的攻击更复杂,因为检测模型的输出是多个边界框和类别,不是单一的类别概率。

针对检测模型的攻击通常要同时欺骗两个部分:让模型漏检真实目标,或者让模型误检不存在的目标。我常用的方法是把检测损失(分类损失+回归损失)作为攻击目标,用PGD同时优化这两部分。

实测下来,针对检测模型的攻击比分类模型难不少。同样的扰动预算下,分类模型的攻击成功率能到95%,检测模型可能只有60%到70%。这是因为检测模型对局部扰动的敏感性更低,而且有多个输出需要同时欺骗。

7.3 对抗样本的防御与攻击的博弈

最后简单说一下防御侧。常见的防御方法有对抗训练、输入预处理、梯度掩码等。对抗训练是最有效的,但计算成本很高。输入预处理(如JPEG压缩、位深缩减)能挡住一些弱攻击,但对PGD这种强攻击效果有限。梯度掩码容易被BPDA(Backward Pass Differentiable Approximation)方法绕过。

我个人的看法是:没有哪种防御是绝对安全的。攻击和防御的博弈会一直持续下去。做安全评估时,要用多种攻击方法交叉验证,不能只测一种就下结论。

这个方向后续还可以往自动化攻击搜索、多模态对抗样本、大模型对抗攻击等方向扩展。尤其是大模型时代,对抗样本的攻击面和防御面都在快速变化,值得持续关注。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进