使用foolbox前需确保模型返回logits而非softmax概率,预处理须与训练一致(如归一化封装进wrapper),攻击应选pgd等可靠算法,鲁棒性评估须明确ε并验证攻击成功率。

用Foolbox生成对抗样本前,先确认模型输入格式是否匹配
Foolbox默认要求模型预测函数返回 logits(未归一化的原始输出),而不是 softmax 概率。如果你的 PyTorch 模型 forward 返回 torch.nn.functional.softmax(..., dim=1),直接传给 Foolbox 会导致攻击失败或误判鲁棒性——因为梯度在 softmax 后被压缩,攻击难以收敛。
实操建议:
- 包装模型时,确保预测函数返回
model(x)(即 logits),不要加 softmax; - 如果是 scikit-learn 分类器(如
RandomForestClassifier),需用decision_function而非predict_proba; - 验证方式:对一个干净样本输入,检查输出 shape 是否为
(1, num_classes)且数值无明显归一化迹象(如各行和不≈1)。
选择攻击算法要看模型类型和实际威胁假设
不是所有攻击都适合评估鲁棒性。比如 FGSM 快但容易被防御策略(如梯度掩码)误导;PGD(ProjectedGradientDescent)是更可靠的基准,因为它多步迭代、可微、能穿透多数浅层防御。
常见组合与注意点:
- 白盒攻击(已知模型结构+参数):优先用
PGD或CarliniWagnerL2Attack; - 黑盒攻击(仅 API 查询):用
BoundaryAttack,但耗时高,建议限制max_queries=5000; - 图像分类任务中,避免直接用
DeepFool评估防御模型——它依赖局部线性假设,在防御模型上常过早终止,低估脆弱性。
计算鲁棒精度时,别跳过预处理一致性校验
很多鲁棒性下降其实源于预处理 bug:训练时用了 transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),但 Foolbox 攻击时忘了在攻击前/后对扰动做逆归一化,导致扰动被缩放错位,评估结果失真。
关键步骤:
- 把归一化操作封装进模型 wrapper,让 Foolbox 始终看到「原始像素空间」输入;
- 或者手动在攻击前用
denormalize,攻击后再normalize回去,确保扰动 Δ 是在 [0,1] 或 [0,255] 空间生效; - 打印攻击前后样本的
torch.max(torch.abs(adversarial - original)),确认其值落在你设定的 ε(如 0.031 for Linf=8/255)附近,否则预处理链肯定出错了。
对抗样本评估必须控制扰动强度并报告攻击成功率
只报「鲁棒准确率 = 对抗样本中预测正确的比例」不够。同一模型在 ε=0.01 下可能达 92%,但在 ε=0.03 下暴跌至 41%——不标 ε 就等于没指标。
实操要点:
- 固定 ε(如
LinfNormMetric(eps=8/255)),并在报告中明确写出; - 记录
attack.success_rate(),低于 95% 说明攻击本身没跑通,鲁棒性数字不可信; - 对每个样本单独调用
attack(model, inputs, labels),别 batch 攻击——Foolbox 的 batch 支持不稳定,易因单个失败样本中断整个批次。
真正难的是让攻击既充分又可控:太弱,测不出漏洞;太强,结果脱离现实威胁。ε 和步数得按数据集和任务反复试,没有通用值。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











