使用CleverHans库实现MNIST对抗训练与攻击防御教程
2025-07-07 06:47:43作者:管翌锬
概述
本教程将介绍如何使用CleverHans库在MNIST数据集上实现对抗训练和评估模型对对抗攻击的鲁棒性。CleverHans是一个专注于对抗性机器学习的Python库,提供了多种对抗攻击和防御方法的实现。
环境准备
在开始之前,确保已安装以下依赖:
- PyTorch
- CleverHans
- torchvision
- absl-py
模型架构
教程中提供了两种CNN模型架构:
1. 基础CNN模型
class CNN(torch.nn.Module):
def __init__(self, in_channels=1):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(in_channels, 64, 8, 1)
self.conv2 = nn.Conv2d(64, 128, 6, 2)
self.conv3 = nn.Conv2d(128, 128, 5, 1)
self.fc1 = nn.Linear(128 * 4 * 4, 128)
self.fc2 = nn.Linear(128, 10)
该模型包含三个卷积层和两个全连接层,使用ReLU激活函数。
2. PyNet模型
class PyNet(nn.Module):
def __init__(self, in_channels=1):
super(PyNet, self).__init__()
self.conv1 = nn.Conv2d(in_channels, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 3, 1)
self.dropout1 = nn.Dropout(0.25)
self.dropout2 = nn.Dropout(0.5)
self.fc1 = nn.Linear(9216, 128)
self.fc2 = nn.Linear(128, 10)
PyNet模型来自PyTorch官方MNIST示例,包含两个卷积层、两个dropout层和两个全连接层。
数据加载
def ld_mnist():
train_transforms = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
test_transforms = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
train_dataset = MNISTDataset(root="/tmp/data", transform=train_transforms)
test_dataset = MNISTDataset(root="/tmp/data", train=False, transform=test_transforms)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=128, shuffle=False)
return EasyDict(train=train_loader, test=test_loader)
数据加载函数使用标准的MNIST数据集,应用简单的ToTensor转换,并返回训练和测试数据加载器。
对抗攻击方法
教程中使用了两种经典的对抗攻击方法:
-
快速梯度符号法(FGSM)
- 单步攻击方法
- 计算损失函数相对于输入的梯度
- 使用梯度的符号扰动输入
-
投影梯度下降法(PGD)
- 多步迭代攻击方法
- 被认为是FGSM的"最强"版本
- 在每次迭代中应用小扰动并在允许的扰动范围内投影
训练流程
训练过程支持两种模式:
- 普通训练
- 对抗训练(使用PGD生成的对抗样本)
for epoch in range(1, FLAGS.nb_epochs + 1):
for x, y in data.train:
if FLAGS.adv_train:
x = projected_gradient_descent(net, x, FLAGS.eps, 0.01, 40, np.inf)
optimizer.zero_grad()
loss = loss_fn(net(x), y)
loss.backward()
optimizer.step()
对抗训练通过在训练过程中使用对抗样本代替原始样本,可以提高模型对对抗攻击的鲁棒性。
评估流程
评估阶段测试模型在三种情况下的表现:
- 原始测试数据
- FGSM攻击后的数据
- PGD攻击后的数据
for x, y in data.test:
x_fgm = fast_gradient_method(net, x, FLAGS.eps, np.inf)
x_pgd = projected_gradient_descent(net, x, FLAGS.eps, 0.01, 40, np.inf)
_, y_pred = net(x).max(1)
_, y_pred_fgm = net(x_fgm).max(1)
_, y_pred_pgd = net(x_pgd).max(1)
参数配置
教程提供了几个可配置参数:
nb_epochs
: 训练轮数eps
: 对抗扰动的最大幅度adv_train
: 是否使用对抗训练model
: 选择使用的模型类型(cnn或pynet)
结果分析
运行后会输出三个准确率:
- 原始测试数据的准确率
- FGSM攻击下的准确率
- PGD攻击下的准确率
通过比较这些结果,可以评估模型的鲁棒性。通常,对抗训练会提高模型在对抗攻击下的准确率,但可能会略微降低原始测试数据的准确率。
结论
本教程展示了如何使用CleverHans库实现对抗训练和评估模型对对抗攻击的鲁棒性。对抗训练是提高模型安全性的有效方法之一,特别是在对抗攻击可能存在的应用场景中。通过调整训练参数和模型架构,可以进一步优化模型的性能和鲁棒性。
对于希望深入了解对抗机器学习的开发者,建议尝试不同的攻击参数、探索其他攻击方法,并研究更先进的防御策略。