基于AlexNet的对抗样本攻击

目录

一、背景介绍

二、代码实现

1.代码的基本结构

第一部分:数据集的导入

第二部分:模型与优化器的选定,各类参数的设定

第三部分:cw攻击效果的训练

第四部分:攻击结果的可视化

2.cw攻击部分的代码呈现(注释很详细)

三、运行结果

        1.先让模型针对mnist数据集进行识别训练,以得到相应权值

        2.cw攻击效果展现

四、目前存在的问题


一、背景介绍

CW算法是一种基于优化的算法,它同时兼顾高攻击准确率和低对抗扰动的两个方面,达到真正意义上对抗样本的效果,即在模型分类出错的情况下,人眼不可查觉。

如果样本攻击成功就要满足两个条件:(1)对抗样本和对应的干净样本应该差距越小越好;(2)对抗样本应该使得模型分类错,且错的那一类的概率越高越好。由这两部分对应两个loss函数。

第一部分,rn对应着干净样本和对抗样本的差,把对抗样本映射到了tanh空间里面,使x可以在-inf到+inf做变换,有利于优化。也可以认为这种方法是一种平滑的梯度下降的方法,消除了在极端区域中陷入平缓而梯度消失的问题。

第二部分,公式中的Z(x)表示的是样本x通过模型未经过softmax的输出向量,对于干净的样本来说,这个向量的最大值对应的就是正确的类别(如果分类正确的话),现在我们将类别t(也就是我们最后想要攻击成的类别)所对应的逻辑值记为Z(An)t,将最大的值(对应类别不同于t)记为max{Z(An)i : i!=t },如果通过优化使得max{Z(An)i : i!=t } - Z(An)t变小,攻击就离成功更近了。k是置信度,可以理解为,k越大,那么模型分错,且错成的那一类的概率越大。最后就是常数c,这是一个超参数,用来权衡两个loss之间的关系,在这个代码中通过二分查找来确定c值。

 CW是一个基于优化的攻击,主要调节的参数是c和k。它的优点在于,可以调节置信度,生成的扰动小,可以破解很多的防御方法,缺点是很慢。

二、代码实现

1.代码的基本结构

第一部分:数据集的导入

1. 选定的mnist数据集,每次导入一种图片进行cw攻击

2. 图片大小 :28x28 标签 : 0~9

3. 初始图片信息为ndarry格式(28,28,3),经过各种操作(如转换为浮点型,resize高宽大小,transpose等),最终转换为可供模型读取的信息格式

第二部分:模型与优化器的选定,各类参数的设定

1. 我们使用的是alexnet模型和Adam优化器

2. 在进行攻击训练前,已经让alexnet模型针对mnist数据集进行识别的训练,得到了针对mnist数据集的权值

3. 各类参数的设定包括了最大迭代次数,学习率,二分查找最大迭代次数,c的初始值(c为超参数,可以简单理解为两个loss函数在最终loss值中所占比例),k值(置信度),均值,标准差等等

第三部分:cw攻击效果的训练

1. 最外层的循环为每次从数据集中导入一种图片,针对于每次导入的那张图片进行cw攻击

2. 紧接着的循环用于尝试不同的c值,通过二分法查找使得攻击效果最好的c值

3. 再内层的循环为针对一张图片的攻击效果的不断优化

        (1)将当前噪声与原始样本叠加,形成攻击样本

        (2)将攻击样本导入模型,得到梯度和结果

        (3)根据模型检测的结果,计算两个loss函数值

                loss1:用于挑选指定分类标签和剩下其他分类中概率最大者,计算两者之间的概率差

                loss2:用于计算对抗样本和原始数据之间的距离

                loss=c*loss1+loss2

        (4)进行backward,并调用优化器进行优化。(每次循环前进行梯度清零操作)

第四部分:攻击结果的可视化

1. 设定了show函数,在每张图片完成cw攻击后,同时展示其原始样本,生成的对抗样本,及对应噪声。结果图已在后文展现。

2.cw攻击部分的代码呈现(注释很详细)

import cv2
import torch
import torchvision
import numpy as np
import matplotlib.pyplot as plt
from torch.autograd import Variable
from torchvision import models
import os
import PIL as Image
# import Image
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"


def show_images_diff(original_img,original_label,adversarial_img,adversarial_label):
    plt.figure()
    # 归一化
    if original_img.any()>1.0:
        original_img=original_img/255.0
    if adversarial_img.any()>1.0:
        adversarial_img=adversarial_img/255.0
    plt.subplot(131)
    plt.title('Original')
    plt.imshow(original_img)
    plt.axis('off')
    plt.subplot(132)
    plt.title(adversarial_img)
    plt.title('Adversarial')
    plt.imshow(adversarial_img)
    plt.axis('off')
    plt.subplot(133)
    plt.title('Adversarial-Original')
    difference=adversarial_img-original_img
    # (-1,1)->(1,0)
    difference=difference/abs(difference).max()/2.0 +0.5
    plt.imshow(difference,cmap=plt.cm.gray)
    plt.axis('off')
    plt.tight_layout()
    plt.show()

def show_images(original_img):
    plt.figure()
    # 归一化
    if original_img.any()>1.0:
        original_img=original_img/255.0
    plt.subplot(131)
    plt.title('Original')
    plt.imshow(original_img)
    plt.axis('off')
    plt.tight_layout()
    plt.show()

#数据集地址
images = os.listdir('D:\pycharm\CWattack\pic\MNIST/test/')
length = len(images)

#选择模型
device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model=models.alexnet(pretrained=True).to(device).eval()

#设定最大迭代次数、学习率、二分查找最大迭代次数、c的初始值、k值等参数
max_iterations=1000 # 1000次可以完成95%的优化工作
learning_rate=0.01
binary_search_steps=10
initial_const=1e2
confidence=initial_const
k=40

# 像素值区间
boxmin = -3.0
boxmax = 3.0
num_labels=1000 # 类别数

# 攻击目标标签,必须使用one hot编码
target_label = 6
tlab=Variable(torch.from_numpy(np.eye(num_labels)[target_label]).to(device).float())
# np.eye 生成对角矩阵
shape=(1,3,224,224)
#均值和标准差
mean = [0.485, 0.456, 0.406]
std = [0.229, 0.224, 0.225]


# 初始化c的边界
lower_bound=0
c=initial_const
upper_bound=1e10
# 保存最佳的l2值、预测概率值和对抗样本
o_bestl2=1e10
o_bestscore=-1
o_bestattack=[np.zeros(shape)]
# 根据像素值的边界计算标准差boxmul和均值boxplus,把对抗样本转换成新的输入newimg
boxmul=(boxmax-boxmin)/2.0
boxplus=(boxmin+boxmax)/2.0


# 每次导入一张图片进行CW攻击
for i in range(length):
    #   图片信息导入以及格式转换
    img = cv2.imread('D:\pycharm\CWattack\pic\MNIST/test/' + images[i]) #uint8(64,64,3)
    img2 = np.asarray(img, dtype='float32')  #numpy (64,64,3)BGR
    img2 = img2[..., ::-1]  #(64,64,3)RGB
    # img2 = np.asarray(img2,dtype='float32')
    img2 = cv2.resize(img2, (224, 224))
    img1 = img2.copy().astype(np.float32)
    img1 /= 255.0
    img1 = (img1 - mean) / std
    img1 = img1.transpose(2, 0, 1)
    img1 = np.expand_dims(img1, axis=0)

    # CW攻击过程
    for outer_step in range(binary_search_steps):
        print("o_bestl2={} confidence={}".format(o_bestl2,confidence))
        # 把原始图像转换成图像数据和扰动的形态
        timg=Variable(torch.from_numpy(np.arctanh((img1-boxplus)/boxmul*0.99999)).to(device).float())
        modifier=Variable(torch.zeros_like(timg).to(device).float())
        # 图像数据的扰动量梯度可以获取
        modifier.requires_grad = True
        optimizer=torch.optim.Adam([modifier],lr=learning_rate) # 优化器
        for iteration in range(1,max_iterations+1):
            optimizer.zero_grad()
            # 定义新输入
            newimg=torch.tanh(modifier+timg)*boxmul+boxplus
            output=model(newimg)
            # 定义cw中的损失函数  loss2:计算对抗样本和原始数据之间的距离
            loss2=torch.dist(newimg,(torch.tanh(timg)*boxmul+boxplus),p=2)
            # loss1:挑选指定分类标签和剩下其它分类中概率最大者,计算两者之间概率差
            real= torch.max(output*tlab)
            other=torch.max((1-tlab)*output)
            loss1=other-real+k
            loss1=torch.clamp(loss1,min=0) # 限制范围,截取功能
            loss1=confidence*loss1
            # 计算总的损失函数
            loss=loss1+loss2
            loss.backward(retain_graph=True)
            optimizer.step()
            l2=loss2
            sc=output.data.cpu().numpy()
            # 显示当前运行结果
            if(iteration%(max_iterations//10)==0):
                print("iteration={} loss={} loss1={} loss2={}".format(
                iteration,loss,loss1,loss2))
            if(l2<o_bestl2)and(np.argmax(sc)==target_label):
                print('attack success l2={} target_label={}'.format(l2,target_label))
                o_bestl2=l2
                o_bestscore=np.argmax(sc)
                o_bestattack=newimg.data.cpu().numpy()

        # 叠加噪声之后的攻击样本
        adv = o_bestattack[0]
        adv = adv.transpose(1, 2, 0)
        adv = (adv * std) + mean
        adv = adv * 255.0
        adv = np.clip(adv, 0, 255).astype(np.uint8)
        # 调用展示函数展示该图片的原始样本、攻击样本和噪声
        show_images_diff(img2, 0, adv, 0)

        # 每轮二分查找结束后,更新c值以及对应的边界
        confidence_old=-1
        if(o_bestscore==target_label)and o_bestscore!=-1:
            # 攻击成功,减小c的值
            upper_bound=min(upper_bound,confidence)
            if upper_bound<1e9:
                print()
                confidence_old=confidence
                confidence=(lower_bound+upper_bound)/2
        else:
            lower_bound=max(lower_bound,confidence)
            confidence_old=confidence
            if upper_bound<1e9:
                confidence=(lower_bound+upper_bound)/2
            else:
                confidence *=10

        print("outer_step={} confidence {}->{}".format(outer_step,
                                                  confidence_old,confidence))

三、运行结果

1.先让模型针对mnist数据集进行识别训练,以得到相应权值

运行结果如下:

2.cw攻击效果展现

四、目前存在的问题

loss1在前10轮中取值很小,有很多时候是0,我们推断与训练过程中种类的设置有关,需要解决。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值