赞
踩
目录
1.先让模型针对mnist数据集进行识别训练,以得到相应权值
CW算法是一种基于优化的算法,它同时兼顾高攻击准确率和低对抗扰动的两个方面,达到真正意义上对抗样本的效果,即在模型分类出错的情况下,人眼不可查觉。
如果样本攻击成功就要满足两个条件:(1)对抗样本和对应的干净样本应该差距越小越好;(2)对抗样本应该使得模型分类错,且错的那一类的概率越高越好。由这两部分对应两个loss函数。
第一部分,rn对应着干净样本和对抗样本的差,把对抗样本映射到了tanh空间里面,使x可以在-inf到+inf做变换,有利于优化。也可以认为这种方法是一种平滑的梯度下降的方法,消除了在极端区域中陷入平缓而梯度消失的问题。
第二部分,公式中的Z(x)表示的是样本x通过模型未经过softmax的输出向量,对于干净的样本来说,这个向量的最大值对应的就是正确的类别(如果分类正确的话),现在我们将类别t(也就是我们最后想要攻击成的类别)所对应的逻辑值记为Z(An)t,将最大的值(对应类别不同于t)记为max{Z(An)i : i!=t },如果通过优化使得max{Z(An)i : i!=t } - Z(An)t变小,攻击就离成功更近了。k是置信度,可以理解为,k越大,那么模型分错,且错成的那一类的概率越大。最后就是常数c,这是一个超参数,用来权衡两个loss之间的关系,在这个代码中通过二分查找来确定c值。
CW是一个基于优化的攻击,主要调节的参数是c和k。它的优点在于,可以调节置信度,生成的扰动小,可以破解很多的防御方法,缺点是很慢。
1. 选定的mnist数据集,每次导入一种图片进行cw攻击
2. 图片大小 :28x28 标签 : 0~9
3. 初始图片信息为ndarry格式(28,28,3),经过各种操作(如转换为浮点型,resize高宽大小,transpose等),最终转换为可供模型读取的信息格式
1. 我们使用的是alexnet模型和Adam优化器
2. 在进行攻击训练前,已经让alexnet模型针对mnist数据集进行识别的训练,得到了针对mnist数据集的权值
3. 各类参数的设定包括了最大迭代次数,学习率,二分查找最大迭代次数,c的初始值(c为超参数,可以简单理解为两个loss函数在最终loss值中所占比例),k值(置信度),均值,标准差等等
1. 最外层的循环为每次从数据集中导入一种图片,针对于每次导入的那张图片进行cw攻击
2. 紧接着的循环用于尝试不同的c值,通过二分法查找使得攻击效果最好的c值
3. 再内层的循环为针对一张图片的攻击效果的不断优化
(1)将当前噪声与原始样本叠加,形成攻击样本
(2)将攻击样本导入模型,得到梯度和结果
(3)根据模型检测的结果,计算两个loss函数值
loss1:用于挑选指定分类标签和剩下其他分类中概率最大者,计算两者之间的概率差
loss2:用于计算对抗样本和原始数据之间的距离
loss=c*loss1+loss2
(4)进行backward,并调用优化器进行优化。(每次循环前进行梯度清零操作)
1. 设定了show函数,在每张图片完成cw攻击后,同时展示其原始样本,生成的对抗样本,及对应噪声。结果图已在后文展现。
- import cv2
- import torch
- import torchvision
- import numpy as np
- import matplotlib.pyplot as plt
- from torch.autograd import Variable
- from torchvision import models
- import os
- import PIL as Image
- # import Image
- os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
-
-
- def show_images_diff(original_img,original_label,adversarial_img,adversarial_label):
- plt.figure()
- # 归一化
- if original_img.any()>1.0:
- original_img=original_img/255.0
- if adversarial_img.any()>1.0:
- adversarial_img=adversarial_img/255.0
- plt.subplot(131)
- plt.title('Original')
- plt.imshow(original_img)
- plt.axis('off')
- plt.subplot(132)
- plt.title(adversarial_img)
- plt.title('Adversarial')
- plt.imshow(adversarial_img)
- plt.axis('off')
- plt.subplot(133)
- plt.title('Adversarial-Original')
- difference=adversarial_img-original_img
- # (-1,1)->(1,0)
- difference=difference/abs(difference).max()/2.0 +0.5
- plt.imshow(difference,cmap=plt.cm.gray)
- plt.axis('off')
- plt.tight_layout()
- plt.show()
-
- def show_images(original_img):
- plt.figure()
- # 归一化
- if original_img.any()>1.0:
- original_img=original_img/255.0
- plt.subplot(131)
- plt.title('Original')
- plt.imshow(original_img)
- plt.axis('off')
- plt.tight_layout()
- plt.show()
-
- #数据集地址
- images = os.listdir('D:\pycharm\CWattack\pic\MNIST/test/')
- length = len(images)
-
- #选择模型
- device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')
- model=models.alexnet(pretrained=True).to(device).eval()
-
- #设定最大迭代次数、学习率、二分查找最大迭代次数、c的初始值、k值等参数
- max_iterations=1000 # 1000次可以完成95%的优化工作
- learning_rate=0.01
- binary_search_steps=10
- initial_const=1e2
- confidence=initial_const
- k=40
-
- # 像素值区间
- boxmin = -3.0
- boxmax = 3.0
- num_labels=1000 # 类别数
-
- # 攻击目标标签,必须使用one hot编码
- target_label = 6
- tlab=Variable(torch.from_numpy(np.eye(num_labels)[target_label]).to(device).float())
- # np.eye 生成对角矩阵
- shape=(1,3,224,224)
- #均值和标准差
- mean = [0.485, 0.456, 0.406]
- std = [0.229, 0.224, 0.225]
-
-
- # 初始化c的边界
- lower_bound=0
- c=initial_const
- upper_bound=1e10
- # 保存最佳的l2值、预测概率值和对抗样本
- o_bestl2=1e10
- o_bestscore=-1
- o_bestattack=[np.zeros(shape)]
- # 根据像素值的边界计算标准差boxmul和均值boxplus,把对抗样本转换成新的输入newimg
- boxmul=(boxmax-boxmin)/2.0
- boxplus=(boxmin+boxmax)/2.0
-
-
- # 每次导入一张图片进行CW攻击
- for i in range(length):
- # 图片信息导入以及格式转换
- img = cv2.imread('D:\pycharm\CWattack\pic\MNIST/test/' + images[i]) #uint8(64,64,3)
- img2 = np.asarray(img, dtype='float32') #numpy (64,64,3)BGR
- img2 = img2[..., ::-1] #(64,64,3)RGB
- # img2 = np.asarray(img2,dtype='float32')
- img2 = cv2.resize(img2, (224, 224))
- img1 = img2.copy().astype(np.float32)
- img1 /= 255.0
- img1 = (img1 - mean) / std
- img1 = img1.transpose(2, 0, 1)
- img1 = np.expand_dims(img1, axis=0)
-
- # CW攻击过程
- for outer_step in range(binary_search_steps):
- print("o_bestl2={} confidence={}".format(o_bestl2,confidence))
- # 把原始图像转换成图像数据和扰动的形态
- timg=Variable(torch.from_numpy(np.arctanh((img1-boxplus)/boxmul*0.99999)).to(device).float())
- modifier=Variable(torch.zeros_like(timg).to(device).float())
- # 图像数据的扰动量梯度可以获取
- modifier.requires_grad = True
- optimizer=torch.optim.Adam([modifier],lr=learning_rate) # 优化器
- for iteration in range(1,max_iterations+1):
- optimizer.zero_grad()
- # 定义新输入
- newimg=torch.tanh(modifier+timg)*boxmul+boxplus
- output=model(newimg)
- # 定义cw中的损失函数 loss2:计算对抗样本和原始数据之间的距离
- loss2=torch.dist(newimg,(torch.tanh(timg)*boxmul+boxplus),p=2)
- # loss1:挑选指定分类标签和剩下其它分类中概率最大者,计算两者之间概率差
- real= torch.max(output*tlab)
- other=torch.max((1-tlab)*output)
- loss1=other-real+k
- loss1=torch.clamp(loss1,min=0) # 限制范围,截取功能
- loss1=confidence*loss1
- # 计算总的损失函数
- loss=loss1+loss2
- loss.backward(retain_graph=True)
- optimizer.step()
- l2=loss2
- sc=output.data.cpu().numpy()
- # 显示当前运行结果
- if(iteration%(max_iterations//10)==0):
- print("iteration={} loss={} loss1={} loss2={}".format(
- iteration,loss,loss1,loss2))
- if(l2<o_bestl2)and(np.argmax(sc)==target_label):
- print('attack success l2={} target_label={}'.format(l2,target_label))
- o_bestl2=l2
- o_bestscore=np.argmax(sc)
- o_bestattack=newimg.data.cpu().numpy()
-
- # 叠加噪声之后的攻击样本
- adv = o_bestattack[0]
- adv = adv.transpose(1, 2, 0)
- adv = (adv * std) + mean
- adv = adv * 255.0
- adv = np.clip(adv, 0, 255).astype(np.uint8)
- # 调用展示函数展示该图片的原始样本、攻击样本和噪声
- show_images_diff(img2, 0, adv, 0)
-
- # 每轮二分查找结束后,更新c值以及对应的边界
- confidence_old=-1
- if(o_bestscore==target_label)and o_bestscore!=-1:
- # 攻击成功,减小c的值
- upper_bound=min(upper_bound,confidence)
- if upper_bound<1e9:
- print()
- confidence_old=confidence
- confidence=(lower_bound+upper_bound)/2
- else:
- lower_bound=max(lower_bound,confidence)
- confidence_old=confidence
- if upper_bound<1e9:
- confidence=(lower_bound+upper_bound)/2
- else:
- confidence *=10
-
- print("outer_step={} confidence {}->{}".format(outer_step,
- confidence_old,confidence))
运行结果如下:
loss1在前10轮中取值很小,有很多时候是0,我们推断与训练过程中种类的设置有关,需要解决。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。