对抗训练深度实战:从 Min-Max 鲁棒优化、PGD-AT 到 TRADES 与认证鲁棒性的工程全解
一个在干净样本上 99% 准确率的卷积网络,只要被贴上肉眼不可见的对抗扰动,预测就会瞬间翻车——这是 2014 年 Goodfellow 等人揭示的"对抗样本"现象,也是深度学习从实验室走向安全敏感场景(自动驾驶、金融风控、医疗影像)时绕不开的一道坎。本文不重复"攻击与防御"的通览,而是聚焦对抗训练(Adversarial Training, AT)这一把模型从被动防御转为主动免疫的核心工程方法论:从鲁棒优化的第一性原理,到 PGD-AT、TRADES 的工程实现,再到鲁棒性与准确性的权衡、评估陷阱与认证鲁棒性。它是模型提取(16064)、成员推断(16068)之外,ML 安全攻防体系必须补齐的"主动训练侧"拼图。
一、为什么需要对抗训练:从脆弱性到鲁棒优化
标准经验风险最小化(ERM)只关心在独立同分布测试集上的平均误差,目标为:
min_θ E_(x,y)~D [ L(f_θ(x), y) ]
但它对输入空间里"与 x 距离极近"的邻域完全无约束。攻击者只需在 Lp 范数球内寻找一个扰动 δ,使模型误分类:
x' = x + δ, s.t. ||δ||_p ≤ ε
其中 L∞ 是最常用的威胁模型(每个像素的改动量都被 ε 同时限制),L2 则对应更自然的视觉扰动。这类扰动对人类不可感知,却能让 SOTA 模型以接近 100% 的概率失守。
对抗训练的本质,是把"对邻域鲁棒"这一约束显式写进训练目标,从被动地事后检测攻击,转为主动地在训练阶段构造最坏情况样本并拟合。它不是某一种攻击的 patches,而是让模型在分布意义上变"稳"。
二、第一性原理:Min-Max 鲁棒优化
对抗训练的标准形式是 min-max 鲁棒优化(Madry et al., 2018):
min_θ E_(x,y)~D [ max_{||δ||_p ≤ ε} L(f_θ(x+δ), y) ]
外层 min_θ 优化模型参数,使最坏情况下的损失最小;内层 max_δ 在 ε 球内寻找让当前模型损失最大的扰动。两层合在一起,等价于最小化对抗风险而非经验风险。
关键洞察有三点:
- 内层最大化是个约束优化问题,本身就是一个"攻击"(在训练侧使用),但它服务于训练而非破坏。
- 当内层用真实最大值求解时,训练得到的是真正对 Lp 球鲁棒的模型;若内层只做近似,可能陷入后面会讲的"梯度混淆"陷阱。
- 对抗风险 ≥ 经验风险,因此对抗训练必然带来某种权衡,这是第四节的核心。
需要强调:对抗训练防御的是白盒最坏情况(攻击者也拥有模型权重),这与基于"隐藏梯度"的混淆式防御有本质区别。
三、PGD 对抗训练:工程上的黄金基线
最实用的对抗训练算法是 PGD(投影梯度下降)对抗训练。每步先对输入施加随机初始化扰动,再用 K 步 PGD 把损失推到局部最大,最后用被扰动后的样本计算梯度更新权重。随机初始化是必须的,否则 PGD 可能只覆盖零扰动附近的极小值,训练出的鲁棒性是不完整的。
一个可直接落地的 PyTorch 实现如下:
import torch
import torch.nn.functional as F
def pgd_attack(model, x, y, eps=8/255, alpha=2/255, steps=10, norm="Linf"):
"""内层最大化:在 eps 球内寻找使损失最大的扰动(训练侧使用)。"""
x_adv = x.clone().detach()
# 随机初始化,避免收敛到平凡极小值
x_adv = x_adv + torch.zeros_like(x_adv).uniform_(-eps, eps)
for _ in range(steps):
x_adv.requires_grad_(True)
with torch.enable_grad():
logits = model(x_adv)
loss = F.cross_entropy(logits, y)
grad = torch.autograd.grad(loss, x_adv)[0]
if norm == "Linf":
delta = torch.sign(grad) * alpha
else: # L2
delta = grad / (grad.norm(dim=(1,2,3), keepdim=True) + 1e-8) * alpha
x_adv = x_adv.detach() + delta
# 投影回 eps 球并夹回合法像素范围
delta_total = torch.clamp(x_adv - x, min=-eps, max=eps)
x_adv = torch.clamp(x + delta_total, min=0.0, max=1.0).detach()
return x_adv
def adv_train_step(model, x, y, opt, eps=8/255, alpha=2/255, steps=10):
"""外层最小化:用 PGD 生成的样本更新权重。"""
model.train()
x_adv = pgd_attack(model, x, y, eps, alpha, steps)
logits = model(x_adv)
loss = F.cross_entropy(logits, y)
opt.zero_grad()
loss.backward()
opt.step()
return loss.item()
落地的几个工程要点:
- eps 的选择:CIFAR-10 上 8/255(L∞)是社区标准,ImageNet 常用 4/255;过大训练不稳定,过小鲁棒性名存实亡。
- K 与 α 的关系:K·α 大致决定攻击强度,但中间步数过少会欠攻击,过多则训练过慢;10 步 PGD 是性价比基线。
- 与正常样本混合:纯对抗训练会让 natural accuracy 明显下滑,实践中常把 batch 拆成一半正常、一半对抗(或半监督),缓解权衡。
- 权重衰减要调小:对抗训练对权重衰减更敏感,沿用 ERM 的超参往往过正则。
四、TRADES:把"准确性—鲁棒性"权衡显式化
PGD-AT 隐含地牺牲了自然准确率。TRADES(Zhang et al., 2019)把这种权衡写成一个可调节的正则项,让工程师能用 λ 显式控制:
min_θ E [ L(f_θ(x), y) + λ · LKL( f_θ(x) || f_θ(x+δ*) ) ]
其中第一项是正常分类损失(保准确性),第二项是"对抗样本与原始样本输出分布的 KL 散度"(促鲁棒性),δ* 由内层攻击求得,λ 越大鲁棒性越强、自然精度越低。它从信息论角度把鲁棒性解释为"对输入扰动的输出不变性"。
对应的 PyTorch 片段:
def trades_loss(model, x, y, eps=8/255, alpha=2/255, steps=10, beta=6.0):
# 内层:生成对抗样本(用 KL 更关注输出分布变化)
x_adv = pgd_attack(model, x, y, eps, alpha, steps) # 复用上文攻击函数
logits_clean = model(x)
logits_adv = model(x_adv)
# 第一项:自然样本分类损失
nat_loss = F.cross_entropy(logits_clean, y)
# 第二项:KL 散度(从 clean 指向 adv 的输出分布)
kl = F.kl_div(
F.log_softmax(logits_adv, dim=1),
F.softmax(logits_clean, dim=1),
reduction="batchmean",
)
return nat_loss + beta * kl
TRADES 的工程价值在于:调一个 β 就能在"更准"和"更稳"之间滑动,而不必重新设计整个训练循环。它也因此成为很多鲁棒基准(如 RobustBench)的参赛默认配置。
五、快速对抗训练:把成本压下来
PGD-AT 每个 batch 要做 K 次前向+反向,训练成本是 ERM 的 K 倍以上,在大模型上难以承受。快速对抗训练是近年工程热点:
- FGSM-RS(免费对抗训练雏形):一步 FGSM 但配合随机初始化与"标签保留"技巧,把成本压到接近 ERM,但曾被指出存在"灾难性过拟合"(在单个 epoch 内鲁棒性突然崩塌)。
- Free AT:复用一次前向的梯度来更新对抗扰动,把 K 步攻击的开销摊薄到多步参数更新里,理论上零额外前向成本。
- YOPO / Fast AT:通过"只在网络前几层更新扰动"等近似,进一步加速,代价是鲁棒性略打折扣。
工程取舍很清楚:若追求最强鲁棒性(安全关键系统),老老实实用多步 PGD-AT 或 TRADES;若要在训练预算内获得"够用"的鲁棒性,快速 AT 是合理折中,但务必用 AutoAttack 复核,避免快速方法掩盖了真实脆弱性。
六、鲁棒性—准确性的权衡:不是 bug,是几何必然
对抗训练最反直觉的现象是:模型在对抗样本上变稳了,却在干净样本上变笨了。这不是实现 bug,而是风险曲面几何的必然:
- 鲁棒分类边界必须"远离"每类样本的决策边界(留出 ε 余量),这迫使边界更平滑、更保守。
- 在 natural 分布上,平滑边界往往不是最小误差边界,于是 natural accuracy 下滑 5%~15% 是常态。
- 更微妙的是,过度鲁棒训练还可能"记住"攻击分布,导致对未见攻击类型的泛化反而变差。
工程师必须根据业务定调:自动驾驶感知模块宁可 natural 掉 10 个点也要抗对抗贴纸;而推荐系统若只是防刷量,则不必付出这份精度税。对抗训练不是"开了就更强",而是一次明确的安全—精度的产品决策。
七、评估陷阱:别被"虚假鲁棒性"骗了
对抗训练最容易翻车的环节是评估。如果只用自己的 PGD 测自己的 PGD-AT,会得到虚高的鲁棒准确率,原因有三:
- 梯度混淆(Obfuscated Gradients):依赖"梯度消失/随机化/破碎梯度"的防御,会让基于梯度的白盒攻击失效,但攻击者换用基于分数的黑盒或代理模型攻击仍能攻破,属于伪鲁棒。
- 攻击强度不足:用 5 步 PGD 评估一个 10 步 PGD 训练的模型,测出的鲁棒性会偏高。
- 固定步长:α 过大可能越过最优点,反而低估鲁棒性。
社区的标准解法是 AutoAttack——它把多种互补攻击(APGD-CE、APGD-DLR、FAB、黑盒 Square Attack)打包成一个无超参、强力的评测套件,专门用来戳穿梯度混淆。任何对抗训练成果,只要没过 AutoAttack 这一关,都不可信。生产侧建议同时报告:natural accuracy、AutoAttack robust accuracy、以及至少一种黑盒攻击的鲁棒性,三者缺一不可。
八、认证鲁棒性:给"安全"一个可证明的上界
经验对抗训练只能给出"在某个攻击下"的经验鲁棒性,无法保证。认证鲁棒性(Certified Robustness)则提供数学上可证明的保证:存在一个半径 r,使得 Lp 球内任意扰动都不会改变预测。两条主流路线:
- 随机平滑(Randomized Smoothing):对输入加大量高斯噪声训练一个"平滑"分类器,理论上给出 L2 下的认证半径。它不依赖具体攻击,是当前大模型上最实用的认证方法。
- 区间界传播 / IBP(Interval Bound Propagation):在训练时直接传播激活的上下界,让网络在训练阶段就优化认证半径,得到"训练即可认证"的模型,但代价是认证半径偏小、训练较难。
认证鲁棒性目前半径还远小于经验攻击的 ε,属于"安全上限"而非"日常防御",但它是监管、医疗、金融等强合规场景的必经之路。工程上建议:用 PGD-AT/TRADES 拿经验鲁棒性打底,用随机平滑补一层可证明保证,二者是互补而非替代。
九、与 ML 安全系列的协同视角
对抗训练不是孤立的。把它放进本系列已经发布的攻防拼图里看,逻辑立刻闭环:
- 模型提取(16064) 用大量查询克隆你的模型;对抗训练后的模型在查询边界更稳,能提高克隆成本,但无法替代查询监控与水印。
- 成员推断(16068) 利用过拟合泄露训练成员隐私;对抗训练因迫使决策边界更平滑、降低过拟合,客观上会削弱成员推断攻击的成功率——鲁棒性与隐私在这里是正相关的。
- 反过来,攻击者也会用对抗样本做对抗性成员推断 / 逃逸式探测。因此部署侧要把"对抗训练 + 输入异常检测 + 查询限流"组合起来,而非单点依赖。
一句话:对抗训练是模型侧的"疫苗",模型提取与成员推断防御是"门禁与监控",三者共同构成纵深防御。
十、生产落地陷阱清单
| 误区 | 后果 | 工程对策 |
|---|---|---|
| 只用 FGSM 一步攻击训练 | 鲁棒性虚高、易过拟合 | 至少 10 步 PGD,或上 AutoAttack 复核 |
| 评估用自己同款攻击 | 虚假鲁棒性 | 强制 AutoAttack + 黑盒攻击双报告 |
| 忽略 natural accuracy 下滑 | 业务精度崩盘 | 用 TRADES 调 β,混合正常样本训练 |
| eps 照搬论文 | 训练不稳或不鲁棒 | 按数据范围(像素 0~1)重标定 ε |
| 权重衰减沿用 ERM 超参 | 过正则、鲁棒性差 | 调小 weight decay,单独调学习率 |
| 只训分类头不调全网络 | 鲁棒性浮于表面 | 端到端微调,必要时对抗预训练 |
| 部署侧不检测对抗输入 | 被定向逃逸 | 叠加输入异常检测与查询限流 |
| 把认证半径当日常 ε | 合规幻觉 | 认证作上限,经验 AT 作日常防御 |
结论:对抗训练把"鲁棒"从口号变成了可写入损失函数的工程目标。抓住 min-max 优化的本质、用 PGD-AT/TRADES 落地、用 AutoAttack 诚实评估、用认证方法补保证,再与本系列的成员推断、模型提取防御组合成纵深体系——这才是把深度学习真正送上安全关键场景的正确姿势。

发表评论 取消回复