FGSM实例:利用fgsm攻击RMB识别模型
提示:文章寫完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔
目錄
一、模型訓(xùn)練總結(jié)回顧
二、對(duì)RMB分類模型進(jìn)行fgsm攻擊
1.fgsm原理
?2.大致思路流程概述
1.求數(shù)據(jù)集中每個(gè)數(shù)據(jù)集的梯度(以供fgsm生成噪聲)
2.通過(guò)fgsm,得到對(duì)抗樣本數(shù)據(jù)集
3.檢驗(yàn)fgsm攻擊效果
3.設(shè)定擾動(dòng)量epsilon和識(shí)別準(zhǔn)確度accuracies
?????????4.定義FGSM攻擊函數(shù)(原理超級(jí)通俗)
?????????5.具體攻擊過(guò)程(僅展示思路,詳細(xì)代碼顯示于文末)
?????????6.攻擊結(jié)果實(shí)例化
代碼展示
成果展示
?三.完整代碼
總結(jié)
一、模型訓(xùn)練總結(jié)回顧
RMB識(shí)別模型的具體訓(xùn)練流程已在之前的文章詳細(xì)敘述,故在此僅聊一聊大致思路
1.數(shù)據(jù)導(dǎo)入:(僅限導(dǎo)入本地已有的數(shù)據(jù)(已分類放置)的方法)
先使用Dataset(包含init,getitem,len函數(shù)),其中我們所需要設(shè)定的就是init函數(shù)和getitem函數(shù)。定義init函數(shù),使其根據(jù)我們所輸入的存儲(chǔ)主路徑將每一張圖片的存儲(chǔ)路徑和圖片類別存放于列表中。定義getitem函數(shù)(需要在DataLoader中通過(guò)index才能進(jìn)行下述操作),使其能夠根據(jù)列表中的路徑提取圖片信息,并執(zhí)行我們所設(shè)定的transform函數(shù),進(jìn)行圖片信息的變換。
再使用DataLoader,這一步不需要我們?nèi)ザx什么,只需要輸入Dataset并設(shè)定一些參數(shù)的值即可(如批大小,每個(gè)epoch是否亂序等等)
2.模型初定義
因?yàn)槭抢^承了nn.Module這個(gè)父類的,所以我們只需要設(shè)定init函數(shù)和forward函數(shù),其中init函數(shù)中設(shè)定自己想要的卷積層和線性層,結(jié)構(gòu)如下:
self.conv1 = nn.Conv2d(輸入層數(shù), 輸出層數(shù), 卷積核大小)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? self.fc1 = nn.Linear(層數(shù)*長(zhǎng)*寬, 想要的數(shù)值)(最終目的是縮小為分類的種類數(shù),但不能直接一步成,必須分成幾次達(dá)成)
而forward函數(shù)則是制定數(shù)據(jù)信息變化過(guò)程先是依次進(jìn)行以下操作,直到無(wú)法繼續(xù)縮小圖片信息為止(長(zhǎng)寬不滿足執(zhí)行條件) ????????
out = F.relu(self.conv1(x)) (長(zhǎng)寬減少,層數(shù)增加)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?執(zhí)行條件:滿足卷積神將網(wǎng)絡(luò)的計(jì)算公式: ???????? N=(W-F+2P)/S+1? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?其中N:輸出大小 ????W:輸入大小 ? ? ?F:卷積核大小 ? ? P:填充值的大小? ? ? S:步長(zhǎng)大小? ? ? ?out = F.max_pool2d(out, 2) (長(zhǎng)寬減半,層數(shù)不變)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 執(zhí)行條件:長(zhǎng)寬為偶數(shù)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
當(dāng)無(wú)法繼續(xù)縮小圖片信息后,執(zhí)行設(shè)定好的線性層即可。
3.定義損失函數(shù)和優(yōu)化器
損失函數(shù)到?jīng)]什么需要我們?nèi)ゲ僮鞯?#xff0c;直接用現(xiàn)成的就行。
優(yōu)化器(optimizer)也直接用現(xiàn)成的,只需要設(shè)定以下學(xué)習(xí)率的大小即可。再將optimizer作為輸入,放在scheduler中,同時(shí)再設(shè)定學(xué)習(xí)率下降策略,即學(xué)習(xí)率縮小倍數(shù)即可。
4.訓(xùn)練過(guò)程
定義數(shù)據(jù)集循環(huán)次數(shù),每輪循環(huán)中,將數(shù)據(jù)集中的圖片信息導(dǎo)入模型得到outputs,將該結(jié)果與實(shí)際結(jié)果導(dǎo)入loss函數(shù),并進(jìn)行backward,根據(jù)梯度,通過(guò)優(yōu)化器改變圖片每個(gè)信息點(diǎn)對(duì)應(yīng)的權(quán)重值。比較outputs中的不同分類的數(shù)值,得出其中每張圖片的最大可能分類(即預(yù)測(cè)結(jié)果),將其與實(shí)際情況比較,得出識(shí)別正確率。
二、對(duì)RMB分類模型進(jìn)行fgsm攻擊
1.fgsm原理
具體內(nèi)容參考此鏈接,寫的很詳細(xì)??https://blog.csdn.net/qq_35414569
一種基于梯度生成對(duì)抗樣本的算法,屬于對(duì)抗攻擊中的無(wú)目標(biāo)攻擊(即不要求對(duì)抗樣本經(jīng)過(guò)model預(yù)測(cè)指定的類別,只要與原樣本預(yù)測(cè)的不一樣即可)
? ? ? ? ? ? ?圖1? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖二(噪聲)? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖三(對(duì)抗樣本)
把圖一喂給模型,模型告訴你57.7%的概率是熊貓,別看概率小,機(jī)器總會(huì)輸出概率值最大的那個(gè)結(jié)果。隨后把圖二加入圖一中,生成一張新的圖三,把圖三喂給模型,模型告訴你99.3%是金絲猴,但肉眼看依然是熊貓,這就是FGSM攻擊方法
?2.大致思路流程概述
前提:已有一個(gè)已經(jīng)訓(xùn)練好的模型
1.求數(shù)據(jù)集中每個(gè)數(shù)據(jù)集的梯度(以供fgsm生成噪聲)
將數(shù)據(jù)集代入模型,求得outputs,將結(jié)果與數(shù)據(jù)集實(shí)際類別輸入到選定的loss函數(shù)中,進(jìn)行backward,并將每張圖片對(duì)應(yīng)梯度收集入列表。
2.通過(guò)fgsm,得到對(duì)抗樣本數(shù)據(jù)集
將數(shù)據(jù)集,收集的梯度列表,當(dāng)前設(shè)定的擾動(dòng)量輸入定義的fgsm中,得到最終的對(duì)抗樣本數(shù)據(jù)集
3.檢驗(yàn)fgsm攻擊效果
將抗樣本數(shù)據(jù)集輸入進(jìn)模型中,得到攻擊后的outputs,比較outputs中的不同分類的數(shù)值,得出其中每張圖片的最大可能分類(即預(yù)測(cè)結(jié)果),統(tǒng)計(jì)該結(jié)果同實(shí)際類別的吻合度,得到收到攻擊后的模型識(shí)別的準(zhǔn)確度
3.設(shè)定擾動(dòng)量epsilon和識(shí)別準(zhǔn)確度accuracies
內(nèi)容如圖所示:
# 這里的擾動(dòng)量先設(shè)定為幾個(gè)值,后面可視化展示不同的擾動(dòng)量影響以及成像效果 epsilons = [0, .05, .1, .15, .2, .25, .3, .35, .4] # 將epsilons中的每個(gè)eps所對(duì)應(yīng)的識(shí)別準(zhǔn)確度放入列表中以供線形圖展示 accuracies = list()4.定義FGSM攻擊函數(shù)(原理超級(jí)通俗)
如圖所示,我們可以假象為每個(gè)圖片信息就是這根曲線上的點(diǎn),該點(diǎn)對(duì)應(yīng)的位置就會(huì)影響對(duì)其類別的判斷,fgsm攻擊的目的就是以盡可能小的移動(dòng)幅度讓該點(diǎn)盡可能的遠(yuǎn)離當(dāng)前位置,故而就得順著梯度最大的方向走,才能達(dá)到最佳效果,即讓每個(gè)圖片信息點(diǎn)所增加的噪聲都能對(duì)其遠(yuǎn)離的行為產(chǎn)生正向作用。
?對(duì)應(yīng)代碼及解釋如下所示:
def fgsm_attack(image, epsilon, data_grad):# 使用sign(符號(hào))函數(shù),將對(duì)x求了偏導(dǎo)的梯度進(jìn)行符號(hào)化(正數(shù)為1,零為0,負(fù)數(shù)為-1)sign_data_grad = data_grad.sign()# 通過(guò)epsilon生成對(duì)抗樣本perturbed_image = image + epsilon * sign_data_grad# 噪聲越來(lái)越大,機(jī)器越來(lái)越難以識(shí)別,但人眼可以看出差別# 做一個(gè)剪裁的工作,將torch.clamp內(nèi)部大于1的數(shù)值變?yōu)?,小于0的數(shù)值等于0,防止image越界perturbed_image = torch.clamp(perturbed_image, 0, 1)# 返回對(duì)抗樣本return perturbed_image5.具體攻擊過(guò)程(僅展示思路,詳細(xì)代碼顯示于文末)
1.設(shè)定循環(huán)的最大輪數(shù)
2.每一輪都將數(shù)據(jù)集中的一個(gè)batch的圖片信息代入模型,求得outputs
3.通過(guò)outputs與圖片實(shí)際類別,輸入loss函數(shù)并進(jìn)行backward,收集每張圖片的梯度信息
4..將數(shù)據(jù),梯度信息,設(shè)定的擾動(dòng)量輸入fgsm函數(shù)中,最終得到對(duì)抗樣本數(shù)據(jù)。
5.可以設(shè)定當(dāng)運(yùn)行了幾個(gè)batch時(shí),顯示當(dāng)前的攻擊信息(如顯示當(dāng)前多個(gè)batch計(jì)算得出的loss的平均值,對(duì)比預(yù)測(cè)結(jié)果與實(shí)際類別得出準(zhǔn)確度等等)
6.攻擊結(jié)果實(shí)例化
注意:x,y值必須是列表的形式
代碼展示
valid_x = epsilons # 設(shè)定的幾個(gè)eps valid_y = accuracies # 每個(gè)eps對(duì)應(yīng)的準(zhǔn)確度plt.plot(valid_x, valid_y, label='Valid')plt.legend(loc='upper right') plt.ylabel('Acc') plt.xlabel('Epsilon') plt.show()成果展示
?三.完整代碼
import os import random import numpy as np import torch import torch.nn as nn import torch.nn.functional as F from torch.utils.data import DataLoader from torch.utils.data import Dataset import torchvision.transforms as transforms import torch.optim as optim from matplotlib import pyplot as plt from PIL import Imagedef set_seed(seed=1):random.seed(seed)np.random.seed(seed)torch.manual_seed(seed)torch.cuda.manual_seed(seed)class RMBDataset(Dataset):def __init__(self, data_dir, transform=None):self.label_name = {"1": 0, "100": 1}self.data_info = self.get_img_info(data_dir) # data_info存儲(chǔ)所有圖片路徑和標(biāo)簽,在DataLoader中通過(guò)index讀取樣本self.transform = transformdef __getitem__(self, index):path_img, label = self.data_info[index]img = Image.open(path_img).convert('RGB') # 0~255if self.transform is not None:img = self.transform(img) # 在這里做transform,轉(zhuǎn)為tensor等等return img, labeldef __len__(self):return len(self.data_info)@staticmethoddef get_img_info(data_dir):data_info = list()for root, dirs, _ in os.walk(data_dir):# 遍歷類別for sub_dir in dirs:img_names = os.listdir(os.path.join(root, sub_dir))img_names = list(filter(lambda x: x.endswith('.jpg'), img_names))# 遍歷圖片for i in range(len(img_names)):img_name = img_names[i]path_img = os.path.join(root, sub_dir, img_name)label = rmb_label[sub_dir]data_info.append((path_img, int(label)))return data_infoclass LeNet(nn.Module):def __init__(self, classes):super(LeNet, self).__init__()self.conv1 = nn.Conv2d(3, 6, 5)self.conv2 = nn.Conv2d(6, 16, 5)self.fc1 = nn.Linear(16*5*5, 120)self.fc2 = nn.Linear(120, 84)self.fc3 = nn.Linear(84, classes)def forward(self, x):out = F.relu(self.conv1(x))out = F.max_pool2d(out, 2)out = F.relu(self.conv2(out))out = F.max_pool2d(out, 2)out = out.view(out.size(0), -1)out = F.relu(self.fc1(out))out = F.relu(self.fc2(out))out = self.fc3(out)return outdef initialize_weights(self):for m in self.modules():if isinstance(m, nn.Conv2d):nn.init.xavier_normal_(m.weight.data)if m.bias is not None:m.bias.data.zero_()elif isinstance(m, nn.BatchNorm2d):m.weight.data.fill_(1)m.bias.data.zero_()elif isinstance(m, nn.Linear):nn.init.normal_(m.weight.data, 0, 0.1)m.bias.data.zero_()set_seed() # 設(shè)置隨機(jī)種子 rmb_label = {"1": 0, "100": 1}# 參數(shù)設(shè)置 MAX_EPOCH = 10 BATCH_SIZE = 5 LR = 0.001 log_interval = 10 val_interval = 1# ============================ step 1/5 數(shù)據(jù) ============================split_dir = os.path.join(".", "RMB_data", "rmb_split") train_dir = os.path.join(split_dir, "train") valid_dir = os.path.join(split_dir, "valid")norm_mean = [0.485, 0.456, 0.406] norm_std = [0.229, 0.224, 0.225]train_transform = transforms.Compose([transforms.Resize((32, 32)),transforms.RandomCrop(32, padding=4),transforms.ToTensor(),transforms.Normalize(norm_mean, norm_std), ])valid_transform = transforms.Compose([transforms.Resize((32, 32)),transforms.ToTensor(),transforms.Normalize(norm_mean, norm_std), ])# 構(gòu)建MyDataset實(shí)例 train_data = RMBDataset(data_dir=train_dir, transform=train_transform) valid_data = RMBDataset(data_dir=valid_dir, transform=valid_transform)# 構(gòu)建DataLoder train_loader = DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True) valid_loader = DataLoader(dataset=valid_data, batch_size=BATCH_SIZE)# ============================ step 2/5 模型 ============================ net = LeNet(classes=2) net.initialize_weights()# ============================ step 3/5 損失函數(shù) ============================ criterion = nn.CrossEntropyLoss() # 選擇損失函數(shù)# ============================ step 4/5 優(yōu)化器 ============================ optimizer = optim.SGD(net.parameters(), lr=LR, momentum=0.9) # 選擇優(yōu)化器 scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1) # 設(shè)置學(xué)習(xí)率下降策略# ============================ step 5/5 訓(xùn)練 ============================ train_curve = list() valid_curve = list()for epoch in range(MAX_EPOCH):loss_mean = 0.correct = 0.total = 0.net.train()for i, data in enumerate(train_loader):# forwardinputs, labels = dataoutputs = net(inputs)# backwardoptimizer.zero_grad()loss = criterion(outputs, labels)loss.backward()# update weightsoptimizer.step()# 統(tǒng)計(jì)分類情況_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).squeeze().sum().numpy()# 打印訓(xùn)練信息loss_mean += loss.item()train_curve.append(loss.item())if (i+1) % log_interval == 0:loss_mean = loss_mean / log_intervalprint("Training:Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(epoch, MAX_EPOCH, i+1, len(train_loader), loss_mean, correct / total))loss_mean = 0.scheduler.step() # 更新學(xué)習(xí)率def fgsm_attack(image, epsilon, data_grad):# 使用sign(符號(hào))函數(shù),將對(duì)x求了偏導(dǎo)的梯度進(jìn)行符號(hào)化(正數(shù)為1,零為0,負(fù)數(shù)為-1)sign_data_grad = data_grad.sign()# 通過(guò)epsilon生成對(duì)抗樣本perturbed_image = image + epsilon * sign_data_grad# 噪聲越來(lái)越大,機(jī)器越來(lái)越難以識(shí)別,但人眼可以看出差別# 做一個(gè)剪裁的工作,將torch.clamp內(nèi)部大于1的數(shù)值變?yōu)?,小于0的數(shù)值等于0,防止image越界perturbed_image = torch.clamp(perturbed_image, 0, 1)# 返回對(duì)抗樣本return perturbed_image# 這里的擾動(dòng)量先設(shè)定為幾個(gè)值,后面可視化展示不同的擾動(dòng)量影響以及成像效果 epsilons = [0, .05, .1, .15, .2, .25, .3, .35, .4] # epsilons = [0, .05, .1, .15, .2, ] accuracies = list() for eps in epsilons:loss_mean = 0.correct = 0.total = 0.log_interval = 10MAX_EPOCH = 3for epoch in range(MAX_EPOCH):net.train()for j, data in enumerate(valid_loader):inputs, labels = data# 圖像數(shù)據(jù)梯度可以獲取inputs.requires_grad = Trueoutputs = net(inputs)optimizer.zero_grad()loss = criterion(outputs, labels)loss.backward()# 收集datagraddata_grad = inputs.grad.data# 調(diào)用FGSM攻擊perturbed_data = fgsm_attack(inputs, eps, data_grad)# 對(duì)受擾動(dòng)的圖像進(jìn)行重新分類output = net(perturbed_data)# 統(tǒng)計(jì)分類情況_, final_pred = torch.max(output.data, 1) # 得到最大對(duì)數(shù)概率的索引total += labels.size(0)correct += (final_pred == labels).squeeze().sum().numpy()# 打印訓(xùn)練信息loss_mean += loss.item()valid_curve.append(loss.item())if (j + 1) % log_interval == 0:loss_mean = loss_mean / log_intervalprint("Validing:Epsilon: {:} Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(eps, epoch, MAX_EPOCH, j + 1, len(valid_loader), loss_mean, correct / total))loss_mean = 0.accuracies.append(correct / total * 100)valid_x = epsilons valid_y = accuraciesplt.plot(valid_x, valid_y, label='Valid')plt.legend(loc='upper right') plt.ylabel('Acc') plt.xlabel('Epsilon') plt.show()總結(jié)
本周學(xué)習(xí)了fgsm攻擊的基本原理,并將之與之前學(xué)習(xí)的RMB識(shí)別模型進(jìn)行結(jié)合(使用了原先選擇的loss函數(shù)及訓(xùn)練好的模型),學(xué)有所獲并詳細(xì)記錄了其中的思路流程。之后,會(huì)學(xué)習(xí)如何使用cifar-10和? imagenet數(shù)據(jù)集進(jìn)行FGSM攻擊,以及其他評(píng)價(jià)模型的指標(biāo)等等。
總結(jié)
以上是生活随笔為你收集整理的FGSM实例:利用fgsm攻击RMB识别模型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高级Bash脚本编程入门
- 下一篇: 2060显卡驱动最新版本_教程:怎么安装