如何在pytorch中实现对抗性示例?

时间:2018-04-21 01:20:46

标签: python machine-learning neural-network conv-neural-network pytorch

我想重现:

来自论文https://arxiv.org/pdf/1312.6199.pdf。我想知道,如何在pytorch中实现这一点?我的主要困惑是loss_f我使用的是torch.nn.CrossEntropy()标准。我只需要更改我已经拥有的代码:

loss = criterion(outputs+r, labels)
loss.backward()

为:

loss = criterion(outputs+r, labels)
loss = loss + c * r.norm(2)
loss.backward()

或沿着那些行的东西(当然包括优化器中的r!)。我知道它不太对,因为我没有明确说明我是如何实现x+r或超立方体约束的,但那些是我仍需要弄清楚的部分。

我认为目前我想在没有超立方体约束的情况下首先关注。如果我们假设我没事,那么上述是正确的吗?我只是想知道:

loss = loss + c * r.norm(2)

按预期工作。

现在,如果我们确实包含超立方体约束,我的解决方案会如何变化?这是“惩罚函数方法”到位吗?

https://discuss.pytorch.org/t/how-does-one-implement-adversarial-examples-in-pytorch/15668

3 个答案:

答案 0 :(得分:7)

这就是我做到的。希望对你有帮助。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Nov 18 12:39:16 2016

@author: manojacharya
"""

import torch
import torch.nn as nn
from torch.autograd import Variable
from torchvision import models,transforms
import numpy as np
from scipy.misc import imread, imresize
import os
import matplotlib.pyplot as plt
import torch.nn.functional as F
import json



normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],
                             std=[0.229, 0.224, 0.225])

transform = transforms.Compose(
    [transforms.ToTensor(),
     normalize])


def imshow(inp, title=None):
    """Imshow for Tensor."""
    plt.figure()
    inp = inp.data[0]
    inp = inp.numpy().transpose((1, 2, 0))
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    inp = std * inp + mean
    plt.imshow(inp)
    plt.axis('off')
    if title is not None:
        plt.title(title)

with open('imagenet.json') as f:
    imagenet_labels = json.load(f)

# In[model]:

model = models.vgg16(pretrained=True)
for param in model.parameters():
    param.requires_grad = False


def predict(img):
    pred_raw = model(img)
    pred = F.softmax(pred_raw)
    _,indices = torch.topk(pred,k=1)
    for ind in indices.data.numpy().ravel():
        print ("%.2f%% , class: %s , %s" %(100*pred.data[0][ind],str(ind),imagenet_labels[ind]))


# In[image ]:

peppers = imread("dog.jpg")
img =  imresize(peppers,(224,224))
imgtensor = transform(img)
imgvar = Variable(imgtensor.unsqueeze(0),requires_grad=False)
imgvard = Variable(imgtensor.unsqueeze(0),requires_grad=True)
optimizer = torch.optim.Adam([imgvard], lr = 0.1)
loss_fn =  nn.CrossEntropyLoss() 

label  =  torch.LongTensor(1)
#classify the object as this label
label[0] = 80
label = Variable(label)
eps = 2/255.0

#%% 
Nepochs = 50
print ("Starting ...........",predict(imgvar))

for epoch in range(Nepochs):     
    optimizer.zero_grad()
    pred_raw = model(imgvard)
    loss  =  loss_fn(pred_raw,label)

    diff = imgvard.data - imgvar.data
    imgvard.data = torch.clamp(torch.abs(diff),max=eps) + imgvar.data

    loss.backward()
    optimizer.step()

    print('epoch: {}/{}, loss: {}'.format(
                epoch + 1,Nepochs, loss.data[0]))
    predict(imgvard)
print('Finished Training')

#%%
imshow(imgvard)


#%%
plt.figure()
diffimg = diff[0].numpy()
diffimg = diffimg.transpose((1,2,0))
plt.imshow(diffimg)

答案 1 :(得分:4)

我将尝试以简单的方式讨论对抗性示例。基本上,对于属于某个类C_1的给定示例,我们希望通过添加小值r来修改此输入,使得它在视觉上不会发生很大变化,但是以非常高的置信度分类到另一个类C_2。为此,您需要选择功能:enter image description here

理想情况下,我们希望r非常小,这是通过在r上进行L1正则化得到的,r是方程的第一部分。第二项损失是将输入x + r分类为新目标类C_2的损失。对于每次迭代,同时优化损失,

                        x_t = x_(t-1) + r

同时确保x + r具有某个范围的x,即允许x在一个非常小的范围内变化,即0.0001。 这将给出x_t,这是x的对抗性示例。 我知道它令人困惑,但这就是你需要实现上面的等式。希望这会有所帮助。

答案 2 :(得分:0)

我们在https://github.com/BorealisAI/advertorch开源并正在积极维护AdverTorch工具箱,它是基于PyTorch的对抗性鲁棒性工具箱

如有兴趣,请看看。

https://github.com/BorealisAI/advertorch/blob/master/advertorch/attacks/lbfgs.py在该论文中实施了LBFGS攻击。