0


【人工智能课程】计算机科学博士作业三

【人工智能课程】计算机科学博士作业三

来源:李宏毅2022课程第10课的作业

1 图片攻击概念

图片攻击是指故意对数字图像进行修改,以使机器学习模型产生错误的输出或者产生预期之外的结果。这种攻击是通过将微小的、通常对人类难以察觉的扰动应用于输入图像来实现的。图片攻击是对深度学习系统中的鲁棒性和安全性的一种测试,也可以用于欺骗、隐私侵犯、对抗性水印等。以下是一些常见的图片攻击的目的:

  1. 对抗样本研究:通过图片攻击,研究人员可以探索深度学习模型的鲁棒性和对抗样本的生成方法,以便改进模型的安全性和鲁棒性。
  2. 欺骗机器学习模型:攻击者可能希望通过修改图片使其被错误地分类,从而欺骗机器学习模型,例如将停车标志误识别为速限标志。
  3. 隐私攻击:通过修改图片,攻击者可以消除敏感信息,或者使图像模糊以保护隐私。
  4. 对抗性水印:攻击者可能希望通过添加微小的、难以察觉的扰动,来隐藏或改变水印,或者转移水印,以保护知识产权或者追踪盗版图片来源。

总之,图片攻击的目的可以是为了研究、测试模型的鲁棒性,也可以是出于恶意目的,比如欺骗或者损害隐私。在实际应用中,保护和提高模型的鲁棒性,并确保数据的安全与隐私是至关重要的。

2 算法

除了FGSM、IFGSM和MIFGSM之外,还有一些其他流行的图像攻击算法,包括:

  1. DeepFool:它是一种迭代的无目标攻击算法,通过找到沿着特征空间最不相关的方向来生成对抗样本。
  2. CW攻击(Carlini and Wagner攻击):这个算法试图最小化一种特定的损失函数,以欺骗分类器,并在L2和L∞规范下产生对抗样本。
  3. JSMA(Jacobian-based Saliency Map Attack):JSMA算法通过最大化目标函数的梯度,以找到最有效的像素扰动,使图像被错误分类。
  4. EOT(Expectation over Transformation):EOT算法通过对输入图像进行多个随机扰动,然后对这些扰动的预期值进行优化,生成对抗样本。
  5. One-pixel攻击:这种攻击算法仅修改图像中的几个像素,以欺骗分类器,同时尽可能减少对原始图像的影响。

3 Python实现

3.1 下载数据

  1. # 设置环境
  2. !pip install pytorchcv
  3. !pip install imgaug
  4. # 下载数据
  5. !wget https://github.com/DanielLin94144/ML-attack-dataset/files/8167812/data.zip
  6. # 解压
  7. !unzip ./data.zip
  8. !rm ./data.zip

3.2 参数设置

  1. import torch
  2. import torch.nn as nn
  3. device = torch.device('cuda'if torch.cuda.is_available()else'cpu')
  4. batch_size =8# 平均值和标准差是根据cifar10数据集计算的统计数据
  5. cifar_10_mean =(0.491,0.482,0.447)# cifar_10 图片数据三个通道的均值
  6. cifar_10_std =(0.202,0.199,0.201)# cifar_10 图片数据三个通道的标准差# meanstd转换为三维张量,用于未来的运算
  7. mean = torch.tensor(cifar_10_mean).to(device).view(3,1,1)
  8. std = torch.tensor(cifar_10_std).to(device).view(3,1,1)
  9. epsilon =8/255/std
  10. root ='/data'# 用于存储`benign images`的目录

3.3 导入数据

  1. import os
  2. import glob
  3. import shutil
  4. import numpy as np
  5. from PIL import Image
  6. from torchvision.transforms import transforms
  7. from torch.utils.data import Dataset, DataLoader
  8. transform = transforms.Compose([
  9. transforms.ToTensor(),
  10. transforms.Normalize(cifar_10_mean, cifar_10_std)])classAdvDataset(Dataset):def__init__(self, data_dir, transform):
  11. self.images =[]
  12. self.labels =[]
  13. self.names =[]'''
  14. data_dir
  15. ├── class_dir
  16. │ ├── class1.png
  17. │ ├── ...
  18. │ ├── class20.png
  19. '''for i, class_dir inenumerate(sorted(glob.glob(f'{data_dir}/*'))):
  20. images =sorted(glob.glob(f'{class_dir}/*'))
  21. self.images += images
  22. self.labels +=([i]*len(images))
  23. self.names +=[os.path.relpath(imgs, data_dir)for imgs in images]
  24. self.transform = transform
  25. def__getitem__(self, idx):
  26. image = self.transform(Image.open(self.images[idx]))
  27. label = self.labels[idx]return image, label
  28. def__getname__(self):return self.names
  29. def__len__(self):returnlen(self.images)
  30. adv_set = AdvDataset(root, transform=transform)
  31. adv_names = adv_set.__getname__()
  32. adv_loader = DataLoader(adv_set, batch_size=batch_size, shuffle=False)print(f'number of images = {adv_set.__len__()}')

3.4 工具函数

(1)评估模型在良性图像上的性能

  1. # 评估模型在良性图像上的性能defepoch_benign(model, loader, loss_fn):
  2. model.eval()
  3. train_acc, train_loss =0.0,0.0for x, y in loader:
  4. x, y = x.to(device), y.to(device)
  5. yp = model(x)
  6. loss = loss_fn(yp, y)
  7. train_acc +=(yp.argmax(dim=1)== y).sum().item()
  8. train_loss += loss.item()* x.shape[0]return train_acc /len(loader.dataset), train_loss /len(loader.dataset)

(2)

  1. # 执行对抗性攻击 并生成对抗性示例defgen_adv_examples(model, loader, attack, loss_fn):
  2. model.eval()
  3. adv_names =[]
  4. train_acc, train_loss =0.0,0.0for i,(x, y)inenumerate(loader):
  5. x, y = x.to(device), y.to(device)
  6. x_adv = attack(model, x, y, loss_fn)# obtain adversarial examples
  7. yp = model(x_adv)
  8. loss = loss_fn(yp, y)
  9. train_acc +=(yp.argmax(dim=1)== y).sum().item()
  10. train_loss += loss.item()* x.shape[0]# store adversarial examples
  11. adv_ex =((x_adv)* std + mean).clamp(0,1)# to 0-1 scale
  12. adv_ex =(adv_ex *255).clamp(0,255)# 0-255 scale
  13. adv_ex = adv_ex.detach().cpu().data.numpy().round()# round to remove decimal part
  14. adv_ex = adv_ex.transpose((0,2,3,1))# transpose (bs, C, H, W) back to (bs, H, W, C)
  15. adv_examples = adv_ex if i ==0else np.r_[adv_examples, adv_ex]return adv_examples, train_acc /len(loader.dataset), train_loss /len(loader.dataset)# 创建存储对抗性示例的目录defcreate_dir(data_dir, adv_dir, adv_examples, adv_names):if os.path.exists(adv_dir)isnotTrue:
  16. _ = shutil.copytree(data_dir, adv_dir)for example, name inzip(adv_examples, adv_names):
  17. im = Image.fromarray(example.astype(np.uint8))# 图片数据需要转成 uint8
  18. im.save(os.path.join(adv_dir, name))

3.5 攻击算法

(1)fgsm算法

  1. deffgsm(model, x, y, loss_fn, epsilon=epsilon):
  2. x_adv = x.detach().clone()# 用良性图片初始化 x_adv
  3. x_adv.requires_grad =True# 需要获取 x_adv 的梯度
  4. loss = loss_fn(model(x_adv), y)# 计算损失
  5. loss.backward()# fgsm: x_adv上使用梯度上升来最大化损失
  6. grad = x_adv.grad.detach()
  7. x_adv = x_adv + epsilon * grad.sign()return x_adv

(2)ifgsm算法

  1. # 在“全局设置”部分中将alpha设置为步长 # alpha和num_iter可以自己决定设定成何值
  2. alpha =0.8/255/ std
  3. defifgsm(model, x, y, loss_fn, epsilon=epsilon, alpha=alpha, num_iter=20):
  4. x_adv = x
  5. # num_iter 次迭代for i inrange(num_iter):
  6. x_adv = fgsm(model, x_adv, y, loss_fn, alpha)# 用(ε=α)调用fgsm以获得新的x_adv# x_adv = x_adv.detach().clone()# x_adv.requires_grad = True # loss = loss_fn(model(x_adv), y) # loss.backward() # grad = x_adv.grad.detach()# x_adv = x_adv + alpha * grad.sign()
  7. x_adv = torch.max(torch.min(x_adv, x+epsilon), x-epsilon)# x_adv 裁剪到 [x-epsilon, x+epsilon]范围return x_adv

(3)mifgsm算法

  1. defmifgsm(model, x, y, loss_fn, epsilon=epsilon, alpha=alpha, num_iter=20, decay=1.0):
  2. x_adv = x
  3. # 初始化 momentum tensor
  4. momentum = torch.zeros_like(x).detach().to(device)# num_iter 次迭代for i inrange(num_iter):
  5. x_adv = x_adv.detach().clone()
  6. x_adv.requires_grad =True
  7. loss = loss_fn(model(x_adv), y)
  8. loss.backward()# TODO: Momentum calculation
  9. grad = x_adv.grad.detach()+(1- decay)* momentum
  10. momentum = grad
  11. x_adv = x_adv + alpha * grad.sign()
  12. x_adv = torch.max(torch.min(x_adv, x+epsilon), x-epsilon)# x_adv 裁剪到 [x-epsilon, x+epsilon]范围return x_adv

(4)EOT算法

  1. defeot_attack(model, x, y, loss_fn, epsilon=0.03, num_samples=10, sigma=0.1):
  2. best_adv_example =None
  3. best_adv_loss =float('inf')for _ inrange(num_samples):
  4. perturbation = torch.randn_like(x)* sigma
  5. x_adv = x + perturbation
  6. x_adv = torch.clamp(x_adv,0,1)# 将像素值限制在合理范围内# 使用 fgsm 得到对抗样本
  7. x_adv = fgsm(model, x_adv, y, loss_fn, epsilon)# 计算对抗样本的损失
  8. adv_loss = loss_fn(model(x_adv), y).item()# 保留损失最小的对抗样本if adv_loss < best_adv_loss:
  9. best_adv_example = x_adv.detach()
  10. best_adv_loss = adv_loss
  11. return best_adv_example

3.6 算法评估

准确率越低越好,损失越大越好

(1)基准模型

  1. from pytorchcv.model_provider import get_model as ptcv_get_model
  2. model = ptcv_get_model('resnet110_cifar10', pretrained=True).to(device)
  3. loss_fn = nn.CrossEntropyLoss()
  4. benign_acc, benign_loss = epoch_benign(model, adv_loader, loss_fn)print(f'[ Base(未Attack图片评估) ] benign_acc = {benign_acc:.5f}, benign_loss = {benign_loss:.5f}')

[ Base(未Attack图片评估) ] benign_acc = 0.95000, benign_loss = 0.22678

(2)FGSM算法

  1. adv_examples, fgsm_acc, fgsm_loss = gen_adv_examples(model, adv_loader, fgsm, loss_fn)print(f'[ Attack(FGSM Attack图片评估) ] fgsm_acc = {fgsm_acc:.5f}, fgsm_loss = {fgsm_loss:.5f}')# create_dir(root, 'fgsm', adv_examples, adv_names)

[ Attack(FGSM Attack图片评估) ] fgsm_acc = 0.59000, fgsm_loss = 2.49272

(3)I-FGSM算法

  1. adv_examples, ifgsm_acc, ifgsm_loss = gen_adv_examples(model, adv_loader, ifgsm, loss_fn)print(f'[ Attack(I-FGSM Attack图片评估) ] ifgsm_acc = {ifgsm_acc:.5f}, ifgsm_loss = {ifgsm_loss:.5f}')
  2. create_dir(root,'ifgsm', adv_examples, adv_names)

[ Attack(I-FGSM Attack图片评估) ] ifgsm_acc = 0.01000, ifgsm_loss = 17.30204

(4)EOT算法

  1. adv_examples, ifgsm_acc, ifgsm_loss = gen_adv_examples(model, adv_loader, eot_attack, loss_fn)print(f'[ Attack(I-FGSM Attack图片评估) ] ifgsm_acc = {ifgsm_acc:.5f}, ifgsm_loss = {ifgsm_loss:.5f}')
  2. create_dir(root,'eot', adv_examples, adv_names)

[ Attack(I-FGSM Attack图片评估) ] ifgsm_acc = 0.21000, ifgsm_loss = 5.35198

(5)基于Ensemble 模型的IFGSM算法

  1. classensembleNet(nn.Module):def__init__(self, model_names):super().__init__()
  2. self.models = nn.ModuleList([ptcv_get_model(name, pretrained=True)for name in model_names])
  3. self.softmax = nn.Softmax(dim=1)defforward(self, x):
  4. ensemble_logits =0for i, m inenumerate(self.models):
  5. ensemble_logits += m(x)return ensemble_logits/len(self.models)
  6. model_names =['nin_cifar10','resnet20_cifar10','preresnet20_cifar10']
  7. ensemble_model = ensembleNet(model_names).to(device)
  8. loss_fn = nn.CrossEntropyLoss()
  9. adv_examples, ifgsm_acc, ifgsm_loss = gen_adv_examples(ensemble_model, adv_loader, ifgsm, loss_fn)print(f'[ Attack(I-FGSM Attack图片评估) ] ifgsm_acc = {ifgsm_acc:.5f}, ifgsm_loss = {ifgsm_loss:.5f}')# create_dir(root, 'ensemble_model_ifgsm', adv_examples, adv_names)

[ Attack(I-FGSM Attack图片评估) ] ifgsm_acc = 0.00000, ifgsm_loss = 13.37727

(6)基于Ensemble 模型的EOT算法

  1. classensembleNet(nn.Module):def__init__(self, model_names):super().__init__()
  2. self.models = nn.ModuleList([ptcv_get_model(name, pretrained=True)for name in model_names])
  3. self.softmax = nn.Softmax(dim=1)defforward(self, x):
  4. ensemble_logits =0for i, m inenumerate(self.models):
  5. ensemble_logits += m(x)return ensemble_logits/len(self.models)
  6. model_names =['nin_cifar10','resnet20_cifar10','preresnet20_cifar10']
  7. ensemble_model = ensembleNet(model_names).to(device)
  8. loss_fn = nn.CrossEntropyLoss()
  9. adv_examples, ifgsm_acc, ifgsm_loss = gen_adv_examples(ensemble_model, adv_loader, eot_attack, loss_fn)print(f'[ Attack(I-FGSM Attack图片评估) ] ifgsm_acc = {ifgsm_acc:.5f}, ifgsm_loss = {ifgsm_loss:.5f}')
  10. create_dir(root,'ensemble_model_eot', adv_examples, adv_names)

[ Attack(I-FGSM Attack图片评估) ] ifgsm_acc = 0.08000, ifgsm_loss = 3.68992

3.7 可视化

  1. import matplotlib.pyplot as plt
  2. classes =['airplane','automobile','bird','cat','deer','dog','frog','horse','ship','truck']
  3. plt.figure(figsize=(10,20))
  4. cnt =0for i, cls_name inenumerate(classes):
  5. path =f'{cls_name}/{cls_name}1.png'# 未Attack图片(benign image)
  6. cnt +=1
  7. plt.subplot(len(classes),4, cnt)
  8. im = Image.open(f'./data/{path}')
  9. logit = model(transform(im).unsqueeze(0).to(device))[0]
  10. predict = logit.argmax(-1).item()
  11. prob = logit.softmax(-1)[predict].item()
  12. plt.title(f'benign: {cls_name}1.png\n{classes[predict]}: {prob:.2%}')
  13. plt.axis('off')
  14. plt.imshow(np.array(im))# Attack后图片(adversarial image
  15. cnt +=1
  16. plt.subplot(len(classes),4, cnt)
  17. im = Image.open(f'./ensemble_model_ifgsm/{path}')
  18. logit = model(transform(im).unsqueeze(0).to(device))[0]
  19. predict = logit.argmax(-1).item()
  20. prob = logit.softmax(-1)[predict].item()
  21. plt.title(f'adversarial: {cls_name}1.png\n{classes[predict]}: {prob:.2%}')
  22. plt.axis('off')
  23. plt.imshow(np.array(im))
  24. plt.tight_layout()
  25. plt.show()

可以从图中可以看到,图片的识别出现了错误,说明图片攻击成功。

在这里插入图片描述


本文转载自: https://blog.csdn.net/weixin_43935696/article/details/136500831
版权归原作者 Better Bench 所有, 如有侵权,请联系我们删除。

“【人工智能课程】计算机科学博士作业三”的评论:

还没有评论