对抗样本之FGSM原理&实战

目录

1、FGSM原理

2、pytorch实现

2.1 建立模型

2.2 FGSM模块

2.3 测试

2.4 可视化对比

2.5 对比样本与对抗样本

1、FGSM原理

论文 Explaining and harnessing adversarial examples.  这篇论文由Goodfellow等人发表在ICLR2015会议上,是对抗样本生成领域的经典论文。

FGSM(fast gradient sign method)是一种基于梯度生成对抗样本的算法,属于对抗攻击中的无目标攻击(即不要求对抗样本经过model预测指定的类别,只要与原样本预测的不一样即可)

我们在理解简单的dp网络结构的时候,在求损失函数最小值,我们会沿着梯度的反方向移动,使用减号,也就是所谓的梯度下降算法;而FGSM可以理解为梯度上升算法,也就是使用加号,使得损失函数最大化。先看下图效果,goodfellow等人通过对一个大熊猫照片加入一定的扰动(即噪音点),输入model之后就被判断为长臂猿

FGSM样本生成

公式

如下图,其中x 是原始样本θ 是模型的权重参数(即w),y是x的真实类别。输入原始样本,权重参数以及真实类别,通过 J 损失函数求得神经网络的损失值,∇x 表示对 x 求偏导,即损失函数 J 对 x 样本求偏导。sign是符号函数,即sign(-2),sign(-1.5)等都等于 -1;sign(3),sign(4.7)等都等于 1。sign函数图如下。

损失只是概率的负对数。损失值通过神经网络反向传播,神经网络的参数根据所使用的优化器进行更新

ϵ(epsilon)的值通常是人为设定 ,可以理解为学习率,一旦扰动值超出阈值,该对抗样本会被人眼识别。

在这里插入图片描述

在这里插入图片描述

之后,原始图像x  + 扰动值 η  = 对抗样本 x + η 。

理解公式后,感觉FGSM并不难。其思想也和dp神经网络类似,但它更像是一个逆过程。我们机器学习算法中无论如何都希望损失函数能越小越好;那对抗样本就不一样了,它本身就是搞破坏的东西,当然是希望损失值越大越好,这样算法就预测不出来,就会失效。

2、pytorch实现

声明:代码来源于pytorch官网,跳转;你要是想看官网直接跳转即可,但是以下的内容我会讲解代码以及自己的理解。

下面代码需要下载预训练模型,将其放在如下代码指定文件夹下,预训练模型下载

pytorch不会 ?见pytorch从基础到实战,做学术可离不开它勒。

2.1 建立模型

from__future__importprint_functionimporttorchimporttorch.nnasnnimporttorch.nn.functionalasFimporttorch.optimasoptimfromtorchvisionimportdatasets,transformsimportnumpyasnpimportmatplotlib.pyplotasplt# 这里的epsilon先设定为几个值,到时候后面可视化展示它的影响如何epsilons=[0,.05,.1,.15,.2,.25,.3]# 这个预训练的模型需要提前下载,放在如下url的指定位置,下载链接如上pretrained_model="data/lenet_mnist_model.pth"use_cuda=True# 就是一个简单的模型结构classNet(nn.Module):def__init__(self):super(Net,self).__init__()self.conv1=nn.Conv2d(1,10,kernel_size=5)self.conv2=nn.Conv2d(10,20,kernel_size=5)self.conv2_drop=nn.Dropout2d()self.fc1=nn.Linear(320,50)self.fc2=nn.Linear(50,10)defforward(self,x):x=F.relu(F.max_pool2d(self.conv1(x),2))x=F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)),2))x=x.view(-1,320)x=F.relu(self.fc1(x))x=F.dropout(x,training=self.training)x=self.fc2(x)returnF.log_softmax(x,dim=1)# 运行需要稍等,这里表示下载并加载数据集test_loader=torch.utils.data.DataLoader(datasets.MNIST('../data',train=False,download=True,transform=transforms.Compose([transforms.ToTensor(),])),batch_size=1,shuffle=True)# 看看我们有没有配置GPU,没有就是使用cpuprint("CUDA Available: ",torch.cuda.is_available())device=torch.device("cuda"if(use_cudaandtorch.cuda.is_available())else"cpu")# Initialize the networkmodel=Net().to(device)# 加载前面的预训练模型model.load_state_dict(torch.load(pretrained_model,map_location='cpu'))# 设置为验证模式. # 详解见这个博客 https://blog.csdn.net/qq_38410428/article/details/101102075model.eval()

Out:

定义的网络模型较为简单,如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QqouDTJj-1620884909006)(C:\Users\刘志远\AppData\Local\Temp\1620882912362.png)]

2.2 FGSM模块

# FGSM attack codedeffgsm_attack(image,epsilon,data_grad):# 使用sign(符号)函数,将对x求了偏导的梯度进行符号化sign_data_grad=data_grad.sign()# 通过epsilon生成对抗样本perturbed_image=image+epsilon*sign_data_grad# 做一个剪裁的工作,将torch.clamp内部大于1的数值变为1,小于0的数值等于0,防止image越界perturbed_image=torch.clamp(perturbed_image,0,1)# 返回对抗样本returnperturbed_image

2.3 测试

由于FGSM算法一次迭代即可,所以没必要单独加个train模块,直接在测试模块实现就行

deftest(model,device,test_loader,epsilon):# 准确度计数器correct=0# 对抗样本adv_examples=[]# 循环所有测试集fordata,targetintest_loader:# Send the data and label to the devicedata,target=data.to(device),target.to(device)# Set requires_grad attribute of tensor. Important for Attackdata.requires_grad=True# Forward pass the data through the modeloutput=model(data)init_pred=output.max(1,keepdim=True)[1]# get the index of the max log-probability# If the initial prediction is wrong, dont bother attacking, just move onifinit_pred.item()!=target.item():continue# Calculate the lossloss=F.nll_loss(output,target)# Zero all existing gradientsmodel.zero_grad()# Calculate gradients of model in backward passloss.backward()# Collect datagraddata_grad=data.grad.data# Call FGSM Attackperturbed_data=fgsm_attack(data,epsilon,data_grad)# Re-classify the perturbed imageoutput=model(perturbed_data)# Check for successfinal_pred=output.max(1,keepdim=True)[1]# get the index of the max log-probabilityiffinal_pred.item()==target.item():correct+=1# 这里都是为后面的可视化做准备if(epsilon==0)and(len(adv_examples)<5):adv_ex=perturbed_data.squeeze().detach().cpu().numpy()adv_examples.append((init_pred.item(),final_pred.item(),adv_ex))else:# 这里都是为后面的可视化做准备iflen(adv_examples)<5:adv_ex=perturbed_data.squeeze().detach().cpu().numpy()adv_examples.append((init_pred.item(),final_pred.item(),adv_ex))# Calculate final accuracy for this epsilonfinal_acc=correct/float(len(test_loader))print("Epsilon: {}\tTest Accuracy = {} / {} = {}".format(epsilon,correct,len(test_loader),final_acc))# Return the accuracy and an adversarial examplereturnfinal_acc,adv_examples

这个函数看起来很多,其中有很多操作都是为后面的可视化做准备,这里我说下比较重要的代码

重要的肯定就是损失函数关于x的偏导,如何求出喽。

model.zero_grad(): PyTorch文档中提到,如果grad属性不为空,新计算出来的梯度值会直接加到旧值上面。 为什么不直接覆盖旧的结果呢?这是因为有些Tensor可能有多个输出,那么就需要调用多个backward。 叠加的处理方式使得backward不需要考虑之前有没有被计算过导数,只需要加上去就行了。我们的情况很简单,就一个输出,所以需要使用这条语句

loss.backward()这条语句并不会更新参数,它只会求出各个中间变量的grad(梯度)值,当然也求出了损失函数关于x的偏导啦

data_grad = data.grad.data:由于前面使用了loss.backward() ,所以data这个tensor的grad属性,自然就有值了,还是损失函数对于x的偏导值

2.4 可视化对比

accuracies=[]examples=[]# Run test for each epsilonforepsinepsilons:acc,ex=test(model,device,test_loader,eps)accuracies.append(acc)examples.append(ex)plt.figure(figsize=(5,5))plt.plot(epsilons,accuracies,"*-")plt.yticks(np.arange(0,1.1,step=0.1))plt.xticks(np.arange(0,.35,step=0.05))plt.title("Accuracy vs Epsilon")plt.xlabel("Epsilon")plt.ylabel("Accuracy")plt.show()

Out:

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DvgZtpPf-1620884909008)(C:\Users\刘志远\AppData\Local\Temp\1620884610752.png)]

2.5 对比样本与对抗样本

# Plot several examples of adversarial samples at each epsiloncnt=0plt.figure(figsize=(8,10))foriinrange(len(epsilons)):forjinrange(len(examples[i])):cnt+=1plt.subplot(len(epsilons),len(examples[0]),cnt)plt.xticks([],[])plt.yticks([],[])ifj==0:plt.ylabel("Eps: {}".format(epsilons[i]),fontsize=14)orig,adv,ex=examples[i][j]plt.title("{} -> {}".format(orig,adv))plt.imshow(ex,cmap="gray")plt.tight_layout()plt.show()

Out:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容