pytorch制作CNN的类印象图 class impression(类别生成图)及生成对抗攻击样本

  本文给出完整代码实现CNN模型的类别可视化输入图像——类印象图,并基于此生成对抗样本图像。

1,完整代码

  在上一篇文章中,我给出了CNN特征可视化的代码,在此基础上稍加修改就可以得到根据各类别反馈生成的输入图像。还是先给出完整代码:

import torch
import torchvision.models as models
import cv2
import time
t0 = time.time()

mu = torch.Tensor([0.485, 0.456, 0.406]).unsqueeze(-1).unsqueeze(-1).cuda()
std = torch.Tensor([0.229, 0.224, 0.225]).unsqueeze(-1).unsqueeze(-1).cuda()
unnormalize = lambda x: x*std + mu
normalize = lambda x: (x-mu)/std

batch_size = 1
num_classes = 1000

model = models.resnet18(pretrained=True).cuda()
for params in model.parameters():
    params.requires_grad = False
model.eval()
'''
mask = torch.zeros((batch_size,3,224,224), dtype=torch.bool).cuda()
mask[:,:,100:-100,100:-100] = True
'''
for clas in range(num_classes):
    data = torch.rand(batch_size,3,224,224).cuda()
    data.requires_grad = True
    #optimizer = torch.optim.SGD([data], lr=6)#, momentum=0.99)
    optimizer = torch.optim.Adam([data], lr=0.1, weight_decay=1e-6)
    label = torch.tensor([clas]).cuda()
    one_hot= torch.zeros((batch_size,num_classes), dtype=torch.bool).cuda()
    label = label.reshape(-1,1)
    one_hot.scatter_(1, label, 1)

    for i in range(4001):
        data1 = (data - data.min()) / (data.max() - data.min())
        #data1 = data1 * mask
        data1 = normalize(data1)
        optimizer.zero_grad()
        outputs = model(data1)
        loss =  - outputs[one_hot].sum()
        loss.backward()
        optimizer.step()
    print('class:',outputs.max(1)[1].item())
    print('time: %.2f'%(time.time()-t0))

    data_i = data.clone()
    data_i = (data_i - data_i.min()) / (data_i.max() - data_i.min())
    #data_i = (data_i*mask)
    data_i = data_i[0].permute(1,2,0).data.cpu().numpy()*255
    data_i = data_i[...,::-1].astype('uint8')  #注意cv2使用BGR顺序
    cv2.imwrite('./class_impress/class_%d.png'%clas,data_i)

注意:这里损失函数使用的目标类别的输出值最大,按说像常规分类网络那样使用交叉熵CE也是可以的,但是画出来的可视化效果不好,没有使用这个损失的效果好。

2,效果图

图1.几种ImageNet预训练网络的类印象图

  这些生成的图片看起来仅仅似乎有一些该类别对应图像的影子,AlexNet的生成图还能看出点东西,其他几个网络的生成图人眼很难辨认。但使用原模型进行验证,可以发现这种生成图目标类别的识别概率都接近100%。
  也有一些技术能够使生成的图片效果更好,甚至达到非常清晰悦目的程度,但这不是本文的目的,感兴趣的可以看我另一篇文章,生成的图片效果更好。

3,小区域生成图

  我们还可以对输入施加约束,比如只在图像的某个小区域内产生图像,见代码中的mask部分。这样生成的图片虽然只有极小的部分,但仍然可以使识别网络产生接近100%的目标类别识别概率。下图给出用预训练ResNet18产生的100x100和24x24两种尺寸的类别生成图例子。
pytorch制作CNN的类印象图 class impression(类别生成图)及生成对抗攻击样本_第1张图片

图2.仅在小范围内生成的类印象图

4,生成攻击性对抗样本

  为什么要在小区域内生成类印象图呢,想必大家已经猜到了,这会是一种对抗攻击方案。既然这样的小图片可以产生很强的网络识别概率,那么我们把这个小图片加入到其他自然图片中,我们不就得到了一种对抗样本攻击方法吗?我们把class0对应的100x100生成图和class8对应的24x24生成图添加到原始图片中,得到的部分对抗样本示例如下图。

图3.添加小区域类印象图构成的对抗样本

  使用100x100补丁图攻击时,我在5000张ImageNet图像像测试,达到了100%的攻击率,使用24x24补丁图攻击时,也达到了30%的攻击率。
  但需要指出的是,这只是一种白盒攻击手段,我上述试验中的小区域补丁图是在ResNet18中生成的,它的攻击图片也只对ResNet18模型有效,如果换成其他模型攻击失效。这也说明,我们用这种方法生成的类印象图是一种非常过拟合的与模型强相关的结果,并不是一种普适的只与类别相关的类印象图。所以,类印象图这个词很准确,它只是特定模型对某个类别的“印象”。找到一种广大神经网络共同的类印象,才能找到一种黑盒攻击方法,这作为我以后思考的问题吧。

你可能感兴趣的:(随笔·各种知识点整理,深度学习)