《Intriguing properties of neural networks》代码实现——Pytorch

《Intriguing properties of neural networks》代码实现——Pytorch

一、代码实现

#导入库
import torch 
import torch.nn as nn
import torch.optim as optim
import torchvision
import numpy as np
import matplotlib.pyplot as plt

# 加载mnist数据
mnist_train = torchvision.datasets.MNIST(root = 'D:\\train_datasets\\mnist\\torch_mnist',
                                        transform=torchvision.transforms.ToTensor(),
                                        train=True,
                                        download=True)
train_loader = torch.utils.data.DataLoader(dataset=mnist_train,
                                          batch_size=128,
                                          shuffle=True)
mnist_test = torchvision.datasets.MNIST(root = 'D:\\train_datasets\\mnist\\torch_mnist',
                                        transform=torchvision.transforms.ToTensor(),
                                        train=False,
                                        download=True)
test_loader = torch.utils.data.DataLoader(dataset=mnist_test,
                                         batch_size=10000, # 把所有test图像放入一个batch,后续用自然向量基好提取特征
                                         shuffle=False)

# 创建FC100模型
class FC_model(nn.Module):
    def __init__(self):
        super(FC_model,self).__init__()
        
        self.layer1 = nn.Sequential(
            nn.Linear(28*28,100),
            nn.ReLU()
        )
        self.layer2 = nn.Sequential(
            nn.Linear(100,100),
            nn.ReLU()
        )
        self.layer3 = nn.Sequential(
            nn.Linear(100,10)
        )
        
    def forward(self,x):
        x = x.view(-1,28*28)
        y_1 = self.layer1(x)
        y_2 = self.layer2(y_1)
        y_3 = self.layer3(y_2)
        return y_1,y_2,y_3 # 因为后面需要提取特征向量,所以把每一层的输出都返回

# 损失函数与优化
FC_100 = FC_model()
Loss = nn.CrossEntropyLoss()
Optimizer_1 = optim.Adam(FC_100.parameters(),lr=0.001, weight_decay=0)

# 训练模型
for epoch in range(10):
    for i,(images,labels) in enumerate(train_loader):
        X = images
        Y = labels
        
        _,_,y = FC_100(X)
        cost = Loss(y,Y)
        
        Optimizer_1.zero_grad()
        cost.backward()
        Optimizer_1.step()
        _,y_ = torch.max(y.data,1)
        correct = (y_ == Y).sum()
        Acc = correct/128.
        if (i+1)%128 == 0:
            print('Epoch [%d/%d], lter [%d], Loss: %.4f,Acc:%.4f'%(epoch+1, 10, i+1, cost.item(),Acc))
print("Train Finshed")

# 测集上的正确率
total = 0
correct = 0
for images, labels in test_loader:
    
    test_images  = images
    test_labels  = labels
    
    _,_,outputs = FC_100(test_images)
    
    _, predicted = torch.max(outputs.data, 1)
    total += len(labels)
    correct += (predicted == labels).sum()
    
print('Accuracy of test images: %.2f %%' % (100 * float(correct) / total))


# 画图函数
def img_show(imgs,title):
    imgs = torchvision.utils.make_grid(imgs) # 将多张图拼为一张图,方便图片显示
    imgs = imgs.numpy()
    font_d = {'size':28}
    fig = plt.figure(figsize = (28, 28))
    plt.imshow(imgs.transpose(1,2,0))
    plt.title(title,fontdict=font_d)
    plt.show()

测试Unit函数提取特征,可以看到提取出的图片有基本的特征

# 1.自然向量基
FC_100.eval()
for i in range(5) :
    
    unit_vector_1 = torch.eye(100)[i,:]
    
    for images, labels in test_loader:

        _, phi_x_1, _ = FC_100(images)
        values_1 = torch.mv(phi_x_1, unit_vector_1)
        
    top_idx_1 = np.argsort(values_1.data.numpy())[-8:]
    top_img_1 = images[top_idx_1]
    img_show(top_img_1,str(i+1) + "th vector")

在这里插入图片描述

# 2.随机向量
for i in range(5) :
    
    unit_vector_2 = torch.rand(100)
    
    for images, labels in test_loader:

        _, phi_x_2, _ = FC_100(images)
        values_2 = torch.mv(phi_x_2, unit_vector_2)
        
    top_idx_2 = np.argsort(values_2.data.numpy())[-8:]
    top_img_2 = images[top_idx_2]
    img_show(top_img_2,str(i+1) + "th vector")

在这里插入图片描述
看看图片索引

print(top_idx_1)
print(top_idx_2)

#output
#[8013  461 2337 9086 2170 6128 6130 6068]
#[6096  923 6333 9409 6139 6123 2080 7117]

实现对抗样本攻击

# 从测试集选取一张没有训练过的图片
attack_img = mnist_test[1][0]
plt.figure()
show_img = np.transpose(attack_img.numpy(),(1,2,0))
plt.imshow(show_img)
plt.show()

此图片为“2”
在这里插入图片描述
攻击代码

for param in FC_model.parameters():
    param.requires_grad = False
for num in range(10):
    r = torch.rand(1, 28, 28)
    r.requires_grad = True

    optimizer_adv = optim.Adam([r], lr=0.001)

    for i in range(3000):

        X = torch.clamp(attack_img + r, 0, 1)  
        Y = torch.tensor([num])

        _,_,outputs = FC_model(X)
        _, predicted = torch.max(outputs.data, 1)

        loss_adv =0.1*r.abs().sum() + Loss(outputs, Y)

        optimizer_adv.zero_grad()
        loss_adv.backward(retain_graph=True)
        optimizer_adv.step()
        if i%100 == 0:
            print("Loss_adv={}".format(loss_adv))
    if predicted.item() != 2 :
        print("Attack successed!")
        break

攻击成功后可以看到输出标签是3

增加扰动后得图片显示

plt.figure(figsize=(5,20))
show_img = np.transpose(X.data.numpy()*255,(1,2,0))
plt.imshow(show_img)
plt.show()

在这里插入图片描述
可以看到用文献中的方法生成扰动后,能顾实现模型的识别误分类。

二、结束语

代码菜鸟,而且对Pytorch框架还不够熟悉,因此代码写的乱七八糟……大神请飘过。后续需要提高代码能力,以及代码的规范化。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值