共计 1565 个字符,预计需要花费 4 分钟才能阅读完成。
背景痛点:对抗样本攻击的现实威胁
2017 年,研究人员发现只需在停车标志上贴几个小贴纸,就能让自动驾驶系统将其误识别为限速标志。这种通过精心构造的微小扰动欺骗模型的现象,就是典型的对抗样本攻击。传统模型在干净测试集上可能表现优异,但面对这类攻击时准确率往往暴跌 50% 以上。

- 攻击成本低:FGSM 等算法能在毫秒级生成攻击样本
- 跨模型通用性:一个对抗样本可同时欺骗多种模型架构
- 物理世界生效:打印出的对抗样本仍具攻击性
技术解析:C&W 损失函数的数学本质
公式演变过程
C&W 损失函数由 Carlini 和 Wagner 在 2017 年提出,核心是解决传统对抗训练中存在的梯度掩码问题。其基本形式为:
L(x, x') = ||x - x'||_p + c·f(x')
- 距离项:控制扰动幅度(常用 L2 或 L∞范数)
- 对抗项:确保攻击成功性的判别函数
经过拉格朗日松弛后,最终版本变为:
L(x') = max(||x - x'||_p - τ, 0) + λ·max(Z(x')_t - max{Z(x')_i: i≠t}, -κ)
其中 τ 为扰动阈值,κ 控制置信度。
范数约束对比
| 范数类型 | 扰动特性 | 适用场景 |
|---|---|---|
| L2 | 均匀分散 | 数字图像 |
| L∞ | 局部集中 | 物理攻击 |
代码实现:PyTorch 实战
可微调损失函数实现
class CWLoss(nn.Module):
def __init__(self, kappa=0., p=2):
super().__init__()
self.kappa = kappa # 置信度阈值
self.p = p # 范数类型
def forward(self, adv_logits, target):
# 计算分类概率差值
target_logit = adv_logits.gather(1, target.view(-1,1))
max_other = adv_logits.scatter(1, target.view(-1,1), -float('inf')).max(1)[0]
loss = torch.clamp(max_other - target_logit + self.kappa, min=0.)
return loss.mean()
对抗样本生成器
def generate_adv(model, x, y,
steps=100, lr=0.01,
c=1e-4, kappa=0.):
x_adv = x.clone().requires_grad_(True)
optimizer = optim.Adam([x_adv], lr=lr)
criterion = CWLoss(kappa=kappa)
for _ in range(steps):
logits = model(x_adv)
loss = torch.norm(x_adv - x, p=2) + c * criterion(logits, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 像素值截断
x_adv.data = torch.clamp(x_adv, 0, 1)
return x_adv.detach()
实战指南:调参与优化
- 学习率动态调整
- 初始阶段使用较大学习率(0.1)快速逼近决策边界
-
后期降至 0.001 进行精细调整
-
内存优化技巧
- 使用
torch.utils.checkpoint分段计算梯度 -
对大型 batch 采用梯度累积
-
多 GPU 同步
- 使用
DistributedDataParallel替代DataParallel - 设置
find_unused_parameters=True处理动态计算图
避坑建议
- 数值稳定性 :对 logits 进行
torch.clamp(_, -10, 10)截断 - 早停策略:当验证集准确率连续 3 个 epoch 不提升时停止
- 量化影响:部署时采用 QAT(量化感知训练)保持鲁棒性
延伸思考
- 如何设计针对 C &W 攻击的检测机制?
- 在 NLP 领域如何适配 C &W 损失函数?
- 当攻击者知道防御策略时,如何构建更强的防御体系?
正文完
