李宏毅hw-10 ——adversarial attack

一、查漏补缺:
1.关于glob.glob的用法,返回一个文件路径的 列表:

当然,再套用1个sort,就是将所有的文件路径按照字母进行排序了

2.relpath == relative_path返回相对于基准路径的相对路径的函数

二、代码剖析:
1.加载对应的数据 和 引入必要的库+环境设置:
# set up environment
!pip install pytorchcv
!pip install imgaug# download
!wget https://github.com/DanielLin94144/ML-attack-dataset/files/8167812/data.zip# unzip
!unzip ./data.zip
!rm ./data.zipimport torch
import torch.nn as nndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
batch_size = 8
# the mean and std are the calculated statistics from cifar_10 dataset
cifar_10_mean = (0.491, 0.482, 0.447) # mean for the three channels of cifar_10 images
cifar_10_std = (0.202, 0.199, 0.201) # std for the three channels of cifar_10 images# convert mean and std to 3-dimensional tensors for future operations
mean = torch.tensor(cifar_10_mean).to(device).view(3, 1, 1)
std = torch.tensor(cifar_10_std).to(device).view(3, 1, 1)epsilon = 8/255/std #这个epsilon就是边界的限制root = './data' # directory for storing benign images
# benign images: images which do not contain adversarial perturbations
# adversarial images: images which include adversarial perturbations
2.关于Dataset的设计部分的研读:
#引入必要的库
import os
import glob
import shutil
import numpy as np
from PIL import Image
from torchvision.transforms import transforms
from torch.utils.data import Dataset, DataLoader
#定义全局的transform方式
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize(cifar_10_mean, cifar_10_std)
])
#定义这200张adv_picture的攻击方式
#虽然没有看作业视频,但是我估计这个 AdvDataset不过是对选定的200张图片 最终攻击成为 目标的 names
class AdvDataset(Dataset):def __init__(self, data_dir, transform):self.images = []self.labels = []self.names = []'''data_dir├── class_dir│   ├── class1.png│   ├── ...│   ├── class20.png'''for i, class_dir in enumerate(sorted(glob.glob(f'{data_dir}/*'))): #data_dir下面有很多个class_dirimages = sorted(glob.glob(f'{class_dir}/*'))         #class_dir下面有很多的class1.png、class2.png。。。。self.images += images                    #将这个class_dir下面的png的绝对地址依次加到全局的images列表中  self.labels += ([i] * len(images))             #对应的label中加上i这个数值 总共加上该class_dir中的png数目self.names += [os.path.relpath(imgs, data_dir) for imgs in images] #relpath == relative_path相对路径self.transform = transformdef __getitem__(self, idx):image = self.transform(Image.open(self.images[idx]))   label = self.labels[idx]return image, label    #返回 代开后的png+经过transform之后的image对象 以及对应的label(这个label还是原来的label)def __getname__(self):return self.names     #返回的name就是class_dir/class2.png这种东西def __len__(self):return len(self.images)#获取adv_dataloader 和 对应的names
adv_set = AdvDataset(root, transform=transform)
adv_names = adv_set.__getname__()
adv_loader = DataLoader(adv_set, batch_size=batch_size, shuffle=False)print(f'number of images = {adv_set.__len__()}')
3.调用原来训练好的图像分类的model:
# to evaluate the performance of model on benign images
#这个就是原来训练好的图像分类识别的model进行eval,得到对应的dataloader的loss 和 acc
def epoch_benign(model, loader, loss_fn):model.eval()train_acc, train_loss = 0.0, 0.0for x, y in loader:x, y = x.to(device), y.to(device)yp = model(x)loss = loss_fn(yp, y)train_acc += (yp.argmax(dim=1) == y).sum().item()train_loss += loss.item() * x.shape[0]return train_acc / len(loader.dataset), train_loss / len(loader.dataset)
4.总共3中生成adv_image的方式,分别是 fgsm, ifgsm ,mifgsm:

它们的想法都是 输入一张图片,然后利用已经train好的分类器的model得到对应的loss和grad,然后利用这个grad的sign将这张图片在“空间”中“反向”移动(原来我们是" -eta*grad" 现在我们是“+eta*grad”)一些,以致于之后分类器分类出来的和目标label的有区别

(目前mifgsm没有实作,具体实作可以参考这篇paper1710.06081.pdf (arxiv.org))

#定义FGSM一次就达到目的的攻击方式的对应的函数
# perform fgsm attack
def fgsm(model, x, y, loss_fn, epsilon=epsilon):x_adv = x.detach().clone() # initialize x_adv as original benign image xx_adv.requires_grad = True # need to obtain gradient of x_adv, thus set required gradloss = loss_fn(model(x_adv), y) # calculate lossloss.backward() # calculate gradient# fgsm: use gradient ascent on x_adv to maximize lossgrad = x_adv.grad.detach()x_adv = x_adv + epsilon * grad.sign() #直接一锤定音,grad.sign就是正取1,负取-1,一拳超人return x_adv#总共有fgsm , ifgsm ,mifgsm 这3种model,最开始只要理解fgsm的工作方式就好了
# alpha and num_iter can be decided by yourself ,
alpha = 0.8/255/std #其实我觉得,按照李宏毅老师的讲法,这个alpha应该是8/255/std也就是和epsilon的大小一致才对
#哦!原来这里是ifgsm,所以会有20个iter,所以alpha的数值 只取到 epsilon的1/10
def ifgsm(model, x, y, loss_fn, epsilon=epsilon, alpha=alpha, num_iter=20): #参数是model,x图像,y标签,总共20个iterx_adv = x# write a loop of num_iter to represent the iterative timesfor i in range(num_iter):# x_adv = fgsm(model, x_adv, y, loss_fn, alpha) # call fgsm with (epsilon = alpha) to obtain new x_advx_adv = x_adv.detach().clone()x_adv.requires_grad = True # need to obtain gradient of x_adv, thus set required gradloss = loss_fn(model(x_adv), y) # calculate lossloss.backward() # calculate gradient# fgsm: use gradient ascent on x_adv to maximize lossgrad = x_adv.grad.detach()x_adv = x_adv + alpha * grad.sign() #得到攻击之后的图像x_adv',计算方法和李宏毅老师讲到的一致x_adv = torch.max(torch.min(x_adv, x+epsilon), x-epsilon) # clip new x_adv back to [x-epsilon, x+epsilon]return x_adv#让我再看看这个mifgsm到底是个啥东西呢,也就是要额外加上一个momentum的处理 和 decay是吧
#其实,这个mifgsm就是再ifgsm的基础上,类似于原来gradient descend可能遇到的问题一样,都要借助前一次的momentum动量进行处理
def mifgsm(model, x, y, loss_fn, epsilon=epsilon, alpha=alpha, num_iter=20, decay=1.0):x_adv = x# initialze momentum tensormomentum = torch.zeros_like(x).detach().to(device) #一开始设定的momentum的数值就是和x的大小完全一样的全0# write a loop of num_iter to represent the iterative timesfor i in range(num_iter):x_adv = x_adv.detach().clone()x_adv.requires_grad = True # need to obtain gradient of x_adv, thus set required gradloss = loss_fn(model(x_adv), y) # calculate lossloss.backward() # calculate gradient# TODO: Momentum calculation# grad = .....#。。。有待进一步添加计算momentum的代码,应该会用到参数里面的decay这个参数x_adv = x_adv + alpha * grad.sign()x_adv = torch.max(torch.min(x_adv, x+epsilon), x-epsilon) # clip new x_adv back to [x-epsilon, x+epsilon]return x_adv
5.调用上面的fgsm或者ifgsm生成对应 adv_image并进行存储,之后再用model进行预测:
# perform adversarial attack and generate adversarial examples
#调用上述定义的 adv_attack的方法,并且生成对应的 图片的攻击后 图像
def gen_adv_examples(model, loader, attack, loss_fn):model.eval()adv_names = []train_acc, train_loss = 0.0, 0.0for i, (x, y) in enumerate(loader):x, y = x.to(device), y.to(device)x_adv = attack(model, x, y, loss_fn) # obtain adversarial examples ,获取到攻击后的图像yp = model(x_adv)       #攻击后的图像的预测结果yploss = loss_fn(yp, y)    #和原来label之间的losstrain_acc += (yp.argmax(dim=1) == y).sum().item()train_loss += loss.item() * x.shape[0]#上面已经用model生成了我们需要的x_adv的攻击后图像,下面只是对这张图像进行 反向还原罢了# store adversarial examplesadv_ex = ((x_adv) * std + mean).clamp(0, 1) # to 0-1 scaleadv_ex = (adv_ex * 255).clamp(0, 255) # 0-255 scaleadv_ex = adv_ex.detach().cpu().data.numpy().round() # round to remove decimal part,利用round函数取出小数点adv_ex = adv_ex.transpose((0, 2, 3, 1)) # transpose (bs, C, H, W) back to (bs, H, W, C)adv_examples = adv_ex if i == 0 else np.r_[adv_examples, adv_ex]return adv_examples, train_acc / len(loader.dataset), train_loss / len(loader.dataset)#将adv攻击之后的图片 和 对应的攻击需要 绑定的label存储到对应的文件路径种
# create directory which stores adversarial examples
def create_dir(data_dir, adv_dir, adv_examples, adv_names):if os.path.exists(adv_dir) is not True:_ = shutil.copytree(data_dir, adv_dir)for example, name in zip(adv_examples, adv_names):im = Image.fromarray(example.astype(np.uint8)) # image pixel value should be unsigned intim.save(os.path.join(adv_dir, name))
6.实例化已经train过的model 和 需要使用的loss_fn:
from pytorchcv.model_provider import get_model as ptcv_get_model#这里直接使用了已经train好的ciFar-10的图像分类识别的model
model = ptcv_get_model('resnet110_cifar10', pretrained=True).to(device)
loss_fn = nn.CrossEntropyLoss() #loss直接使用crossEntropybenign_acc, benign_loss = epoch_benign(model, adv_loader, loss_fn)
print(f'benign_acc = {benign_acc:.5f}, benign_loss = {benign_loss:.5f}')
7.上面都是定义哈,这里才是真正的调用fgsm 和 ifgsm生成对应的 adv_图像:
#调用fgsm的结果是:
adv_examples, fgsm_acc, fgsm_loss = gen_adv_examples(model, adv_loader, fgsm, loss_fn)
print(f'fgsm_acc = {fgsm_acc:.5f}, fgsm_loss = {fgsm_loss:.5f}')create_dir(root, 'fgsm', adv_examples, adv_names)
adv_examples, ifgsm_acc, ifgsm_loss = gen_adv_examples(model, adv_loader, ifgsm, loss_fn)
print(f'ifgsm_acc = {ifgsm_acc:.5f}, ifgsm_loss = {ifgsm_loss:.5f}')create_dir(root, 'ifgsm', adv_examples, adv_names)
8.总共10个类别的CiFAR-10,每个类别分别show出1张攻击前后的图像 以及 经过同一个model的预测结果:
#这里做的事情,就是输出利用这个训练好的model,分别输入攻击前 和 攻击后的图片, 然后得到的各自的pred的概率
import matplotlib.pyplot as pltclasses = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']plt.figure(figsize=(10, 20))
cnt = 0
for i, cls_name in enumerate(classes): #10个种类,每个种类展示1.png那个图片攻击前后的识别结果path = f'{cls_name}/{cls_name}1.png'# benign imagecnt += 1plt.subplot(len(classes), 4, cnt)im = Image.open(f'./data/{path}')   #这一段 和 下面一段的唯一的区别 只是打开的图片的文件不同罢了logit = model(transform(im).unsqueeze(0).to(device))[0]predict = logit.argmax(-1).item()prob = logit.softmax(-1)[predict].item()plt.title(f'benign: {cls_name}1.png\n{classes[predict]}: {prob:.2%}')plt.axis('off')plt.imshow(np.array(im))# adversarial imagecnt += 1plt.subplot(len(classes), 4, cnt)im = Image.open(f'./fgsm/{path}')logit = model(transform(im).unsqueeze(0).to(device))[0]predict = logit.argmax(-1).item()prob = logit.softmax(-1)[predict].item()plt.title(f'adversarial: {cls_name}1.png\n{classes[predict]}: {prob:.2%}')plt.axis('off')plt.imshow(np.array(im))plt.tight_layout()
plt.show()
9.对1张狗狗的图像,用原来的model可以识别它是dog,但是经过adv_攻击后的图像在model中识别就会变成cat,
最后,我们将这个adv_攻击图像 经过1个JPEG压缩,然后再通过model识别,就成功抵御了这个adv_攻击:
#这一部分只不过是对上面的那段代码的 单次循环的版本而已
# original image
path = f'dog/dog2.png'
im = Image.open(f'./data/{path}')
logit = model(transform(im).unsqueeze(0).to(device))[0]
predict = logit.argmax(-1).item()
prob = logit.softmax(-1)[predict].item()
plt.title(f'benign: dog2.png\n{classes[predict]}: {prob:.2%}')
plt.axis('off')
plt.imshow(np.array(im))
plt.tight_layout()
plt.show()# adversarial image 
adv_im = Image.open(f'./fgsm/{path}')
logit = model(transform(adv_im).unsqueeze(0).to(device))[0]
predict = logit.argmax(-1).item()
prob = logit.softmax(-1)[predict].item()
plt.title(f'adversarial: dog2.png\n{classes[predict]}: {prob:.2%}')
plt.axis('off')
plt.imshow(np.array(adv_im))
plt.tight_layout()
plt.show()

#为啥这里还有1个defence的部分捏,好奇怪哦
#虾米那就是干了这么一件事情,就是对adv攻击之后产生的图片 再通过1个JPEG的压缩,然后再用model进行pred
#观察,这个adv攻击是否就已经失效了
#我觉得,最大的成就感,来源于自己的创造,不是光读懂别人代码就行了,那样也迟早会劝退
#而是要,创造自己的那部分!那样,你才会更想去做这件事情
#所以,就先完成下面这个JPEG压缩的部分吧,有chatGPT,怕什么,什么都可以独立的实现,多花时间,自然能多收获import imgaug.augmenters as iaa# pre-process image
x = transforms.ToTensor()(adv_im)*255
x = x.permute(1, 2, 0).numpy()
x = x.astype(np.uint8)# TODO: use "imgaug" package to perform JPEG compression (compression rate = 70)
# compressed_x =  ... x .. 
seq = iaa.JpegCompression(compression=70)
compressed_x = seq.augment_image(x)logit = model(transform(compressed_x).unsqueeze(0).to(device))[0]
predict = logit.argmax(-1).item()
prob = logit.softmax(-1)[predict].item()
plt.title(f'JPEG adversarial: dog2.png\n{classes[predict]}: {prob:.2%}')
plt.axis('off')plt.imshow(compressed_x)
plt.tight_layout()
plt.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/141633.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【红帽】跟着学习如何使用桌面访问命令行

今天我们分享一些红帽Linux的知识,记得关注,会一直更新~ ▶1、以student用户身份并使用student作为密码登录workstation 1.1.在workstation上,从GNOME登录屏幕中单击student用户帐户。系统提示输入密码时,请输入student。 1.2.…

JavaScript系列从入门到精通系列第九篇:JavaScript中赋值运算符和关系运算符以及Unicode编码介绍

一:赋值运算符 1: 右侧的值可以赋值给左侧的变量。 var a 123; console.log(a);//123 2: var a 10; a a 5; a 5; 上边这两个写法是一样的。 3:- var a 10; a a-5; a - 5; 上边这两个写法是一样的。 4:* …

数据备份文件生成--根据表名生成对应的sql语句文件

最近客户有个需求,希望在后台增加手动备份功能,将数据导出下载保存。 当然,此方法不适用于海量数据的备份,这只适用于少量数据的sql备份。 这是我生成的sql文件,以及sql文件里的insert语句,已亲测&#x…

Java抽象类、接口

1.抽象类 1.abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类那么该类就是抽象类。2.抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类3.抽象类,不能使用new关键字来创建对象,它是用来让子类继承的4.抽象方法,只有…

接口测试入门

1. 什么是接口测试 顾名思义,接口测试是对系统或组件之间的接口进行测试,主要是校验数据的交换,传递和控制管理过程,以及相互逻辑依赖关系。其中接口协议分为HTTP,WebService,Dubbo,Thrift,Socket等类型,测试类型又主…

nodejs 如何在npm发布自己的包 <记录>

一、包结构 必要结构: 一个包对应一个文件夹(文件夹名不是包名,但最好与包名保持一致,包名以package.json中的name为主)包的入口文件index.js包的配置文件package.json包的说明文档README.md 二、需要说明的文件 1.配…

【密码学补充知识】

🔑密码学🔒概述 📕 1.基本概念 明文 : 要交换的信息 密文 : 明文经过一组规则变换成看似没有意义的随机消息。 加密 : 明文经过一组规则变换成密文的过程 解密 : 密文恢复出明文的过程 加…

基于 MATLAB 的电力系统动态分析研究【IEEE9、IEEE68系节点】

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

linux-如何用起来ubuntu

1 Oracle VM VirtualBox安装ubuntu20.04虚拟机 【工具】->【新建】 1.1 虚拟电脑名称和系统类型 【名称】:自定义名称即可 【文件夹】:虚拟机文件将要存储的路径 【虚拟光盘】:将要安装的虚拟机iso文件 1.2 自动安装 【用户名】&…

uniapp:tabBar点击后设置动画效果

APP端不支持dom操作,也不支持active伪类,绞尽脑汁也没办法给uniapp原生的tabBar点击加动画效果,所以最终只能舍弃原生tabBar,改用自定义tabBar。 自定义tabBar的原理是,页面的上部分分别是tabBar对应的页面组件&#…

什么是Selenium?使用Selenium进行自动化测试!

你知道什么是 Selenium 吗?你知道为什么要使用它吗?答案就在本文中,很高兴能够与你共飧。 自动化测试正席卷全球,Selenium 认证是业界最抢手的技能之一。 什么是 Selenium? Selenium 是一种开源工具,用于…

400电话申请流程详解,助您快速办理联通、移动、电信400电话

导语:随着企业业务的发展,越来越多的企业开始关注400电话的申请与办理。本文将为您详细介绍联通、移动、电信400电话的申请流程,帮助您快速办理400电话,提升企业形象和客户服务质量。 一、联通400电话申请流程 咨询与选择&#x…

孤网双机并联逆变器下垂控制策略MATLAB仿真模型

微❤关注“电气仔推送”获得资料 主体模块: 建议使用MATLAB2021b及以上版本打开! 功率计算模块、下垂控制模块、电压电流双环控制模块 系统输出有功功率: 系统输出无功功率: 系统频率变化曲线: 参考文献: 微电网并网运行模式下…

arcgis搭建离线地图服务WMTS

Arcgis搭建离线地图服务WMTS 发布时间:2021-03-04 版权: ARCGIS搭建离线地图服务器,进行离线地图二次开发 2. 离线地图服务发布(WMTS服务) (详细教程:卫星地图_高清卫星地图_地图编辑_离线地…

数据结构上机1

1、题目&#xff1a; 将1~10存入数组a[10]&#xff0c;并将其逆序输出 #define _CRT_SECURE_NO_WARNINGS 1 //(1) 将1~10存入数组a[10]&#xff0c;并将其逆序输出#include <stdio.h>int main() {int a[10];// 将1到10存入数组a[10]for (int i 0; i < 10; i){a[i] i…

Day 02 python学习笔记

python运算符 算术运算符 混合运算的优先级&#xff1a; () 高于 ** * / // % 高于 - 赋值运算符 - * / ** a 1 > a 3 > a a 3 其余同理 注意&#xff1a; python没有自增自减 &#xff08;a a a-- --a&#xff09;…

ad18学习笔记十一:显示和隐藏网络、铺铜

如何显示和隐藏网络&#xff1f; Altium Designer--如何快速查看PCB网络布线_ad原理图查看某一网络的走线_辉_0527的博客-CSDN博客 AD19(Altium Designer)如何显示和隐藏网络 如何显示和隐藏铺铜&#xff1f; Altium Designer 20在PCB中显示或隐藏每层铺铜-百度经验 AD打开与…

404. 左叶子之和

给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 示例 1&#xff1a; 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中&#xff0c;有两个左叶子&#xff0c;分别是 9 和 15&#xff0c;所以返回 24示例 2: 输入: root [1] 输出: 0 //bfs …

4年从外包到外企,一个测试老鸟的自述

4年前&#xff0c;我拖着行李箱来到北京&#xff0c;成为了一名北漂&#xff0c;离开了校园的庇护&#xff0c;只身一人&#xff0c;想要在这片陌生的地方闯出一番名堂&#xff0c;可最后却不得人意&#xff0c;面临着所有北漂群体的共同困局&#xff0c;没有归属感&#xff0c…

一文搞懂 this 指向

目录 一、前言二、箭头函数三、new指向四、bind五、call和apply六、bind call apply区别七、对象&#xff08;obj.&#xff09;八、全局this指向九、不在函数里 一、前言 JS 中 this 指向问题 - 掘金 在JavaScript中&#xff0c;this关键字表示当前执行代码的上下文对象。它的…