8.1.1 图像旋转对鲁棒性的影响
    下面我们结合实际的例子来介绍旋转对鲁棒性的影响,对应的代码路径为:
    https://github.com/duoergun0729/adversarial_examples/blob/master/code/8-
    case1.ipynb
    #图像加载以及预处理
    image_path="../picture/left.jpg"
    img = cv2.imread(image_path)[..., ::-1]
    img = cv2.resize(img, (rows,cols))
    matrix = cv2.getrotationmatrix2d((cols/2,rows/2),90,1)
    img1 = cv2.warpaffine(img,matrix,(cols,rows))
    matrix = cv2.getrotationmatrix2d((cols/2,rows/2),180,1)
    img2 = cv2.warpaffine(img,matrix,(cols,rows))
    matrix = cv2.getrotationmatrix2d((cols/2,rows/2),270,1)
    img3 = cv2.warpaffine(img,matrix,(cols,rows))
    如图8-1所示,直观的感觉,当图像发生旋转时,大多数情况下不会影响人对物体分类的结果。除了少数的角度/方向敏感的情况,如图8-2所示,原始图像为向左,图像分别逆时针旋转90度、180度、270度后,人对该图像会分别识别为向下、向右和向上。
    图8-1 图像发生旋转不影响分类
    图8-2 图像发生旋转影响分类
    我们以经典的熊猫图像来验证我们的想法。首先我们定义一个工具函数infer_img,使用的预测模型是pytorch框架下基于imagenet2012数据集训练的alexnet模型。infer_img的输入为图像数据img以及标签t。t默认为0,表示返回预测结果中概率最大的分类标签的概率,当t不为0时,返回指定的分类标签的概率。需要指出的是,pytorch框架下的imagenet2012数据集,图像数据的标准化比较特殊,需要使用特定的均值mean和标准差std:
    def infer_img(img,t=0):
    #标准化
    img=img.astype(np.float32)
    mean = [0.485, 0.456, 0.406]
    std = [0.229, 0.224, 0.225]
    img /= 255.0
    img = (img - mean) / std
    img = img.transpose(2, 0, 1)
    img=np.expand_dims(img, axis=0)
    img = variable(torch.from_numpy(img).to(device).float())
    #使用预测模式主要影响dropout和bn层的行为
    model = models.alexnet(pretrained=true).to(device).eval()
    output=f.softmax(model(img),dim=1)
    label=np.argmax(output.data.cpu().numpy())
    pro=output.data.cpu().numpy()[0][label]
    #当t不为0时返回指定类别的概率
    if t != 0:
    pro=output.data.cpu().numpy()[0][t]
    return pro
    我们对原始的熊猫图片进行预测。
    print(infer_img(orig))
    print(infer_img(orig,t=288))
    print(infer_img(orig,t=388))
    预测结果为,分类为标签388(熊猫对应的分类标签)的概率为92.71%,分类为标签288的概率非常低。
    0.9270878
    3.1756701e-06
    0.9270878
    下面我们把原始图像逐渐旋转至180度,每次旋转的角度增加10度,并记录下旋转角度和预测为熊猫对应标签的概率。旋转的方法使用了4.2.1节的仿射变化。
    #验证原始图片的旋转不变性
    rotate_range = range(0,180,10)
    original_pro = []
    for i in rotate_range:
    #构造仿射变换矩阵
    matrix = cv2.getrotationmatrix2d((cols/2,rows/2),i,1)
    #进行仿射变化
    rotate_img = cv2.warpaffine(orig.copy(),matrix,(cols,rows))
    #获得预测为熊猫的概率值
    pro=infer_img(rotate_img.copy(),388)
    print("rotate={} pro[388]={}".format(i,pro))
    original_pro += [pro]
    #绘图,横轴代表旋转的角度,纵轴代表预测为熊猫对应标签的概率
    fig, ax = plt.subplots()
    ax.plot(np.array(rotate_range), np.array(original_pro), 'b--',
    label='probability of class 388')
    legend = ax.legend(loc='upper center', shadow=true, fontsize='large')
    legend.get_frame().set_facecolor('#ffffff')
    plt.xlabel('rotate range')
    plt.ylabel('probability')
    plt.show()
    如图8-3所示,横轴代表旋转的角度,纵轴代表预测为熊猫对应标签的概率。我们假设分类概率大于50%表示不影响分类结果,可见当旋转角度小于60度或者在90度和110度之间时不影响分类结果。如果以更加严格的要求,认为分类概率大于80%表示不影响分类结果,那么可以认为旋转30度以内不影响分类结果。通过本例可以看出,图像分类模型对于图像旋转具有一定的鲁棒性,当旋转角度较小时对分类结果影响不大。事实上在进行模型训练时,为了增加训练数据量,会人为地把训练数据随机旋转一定的角度,这一过程也叫作数据增强。大量的实验证明,图像预测阶段旋转的角度如果在数据增强的范围内,不会影响分类结果。
    图8-3 图像分类模型对图像旋转的鲁棒性示例
    我们针对熊猫图像,使用fgsm算法生成定向攻击的对抗样本,定向攻击的目标标签为288,并且概率大于一定的阈值才认为攻击成功。
    epochs=100
    e=0.007
    target=288
    target=variable(torch.tensor([float(target)]).to(device).long())
    for epoch in range(epochs):
    # forward + backward
    output = f.softmax(model(img),dim=1)
    loss = loss_func(output, target)
    label=np.argmax(output.data.cpu().numpy())
    pro=output.data.cpu().numpy()[0][label]
    print("epoch={} loss={} label={} pro={}".format(epoch,loss,label,pro))
    #如果定向攻击成功并且概率大于阈值
    if (label == target) and ( pro > 0.80):
    print("")
    break
    #梯度清零
    optimizer.zero_grad()
    #反向传递,计算梯度
    loss.backward()
    img.data=img.data-e*torch.sign(img.grad.data)
    为了后继图像旋转处理方便,需要把归一化的对抗样本还原成正常图片格式。对抗样本的形状为[3,224,224],需要转换为[224,224,3]:
    #把对抗样本转换成正常图片格式
    adv=img.data.cpu().numpy()[0]
    print(adv.shape)
    adv = adv.transpose(1, 2, 0)
    adv = (adv * std) + mean
    adv = adv * 255.0
    adv = np.clip(adv, 0, 255).astype(np.uint8)
    print(adv.shape)
    下面我们把对抗样本逐渐旋转至180度,每次旋转的角度增加10度,并记录下旋转角度和预测为熊猫和定向攻击目标对应标签的概率。
    #验证旋转对于对抗样本的影响
    rotate_range = range(0,180,10)
    adv_288_pro = []
    adv_388_pro = []
    for i in rotate_range:
    matrix = cv2.getrotationmatrix2d((cols/2,rows/2),i,1)
    rotate_img = cv2.warpaffine(adv.copy(),matrix,(cols,rows))
    #记录熊猫的概率
    pro_388=infer_img(rotate_img.copy(),388)
    #记录定向攻击目标的概率
    pro_288=infer_img(rotate_img.copy(),288)
    print("rotate={} pro[388]={} pro[288]={}".format(i,pro_388,pro_288))
    adv_288_pro += [pro_288]
    adv_388_pro += [pro_388]
    fig, ax = plt.subplots()
    ax.plot(np.array(rotate_range), np.array(adv_288_pro), 'b--',
    label='probability of class 288')
    ax.plot(np.array(rotate_range), np.array(adv_388_pro), 'r',
    label='probability of class 388')
    legend = ax.legend(loc='upper center', shadow=true, fontsize='large')
    legend.get_frame().set_facecolor('#ffffff')
    plt.xlabel('rotate range')
    plt.ylabel('probability')
    plt.show()
    如图8-4所示,横轴代表旋转的角度,纵轴代表预测概率,实线代表预测为熊猫的概率,虚线代表预测为定向攻击目标的概率。我们假设分类概率大于50%的预测结果可信,那么可以认为当旋转角度小于5度时,该定向攻击的对抗样本有效,当角度大于10度时,定向攻击失效。如果以更加严格的要求,认为分类概率大于80%的结果可信,那么可以认为当旋转角度在30度到60度之间时,原有模型可以有效抵御定向攻击样本。
    图8-4 对抗样本对图像旋转的鲁棒性示例
    那么是否存在一种方式,把图像旋转一定角度后,既不影响对原始图像的分类,又可以抵御对抗样本的影响呢?下面我们把对抗样本和原始图片逐渐旋转至180度,每次旋转的角度增加10度,并记录下旋转角度和预测为熊猫的概率。
    #综合分析验证旋转对于对抗样本和正常图片分类的影响
    rotate_range = range(0,180,10)
    original_pro = []
    adv_pro = []
    for i in rotate_range:
    matrix = cv2.getrotationmatrix2d((cols/2,rows/2),i,1)
    rotate_adv_img = cv2.warpaffine(adv.copy(),matrix,(cols,rows))
    pro_388=infer_img(rotate_adv_img.copy(),388)
    adv_pro+= [pro_388]
    rotate_img = cv2.warpaffine(orig.copy(),matrix,(cols,rows))
    pro=infer_img(rotate_img.copy(),388)
    original_pro += [pro]
    print("rotate={} adv_pro[388]={}
    original_pro[388]={}".format(i,pro_388,pro))
    fig, ax = plt.subplots()
    ax.plot(np.array(rotate_range), np.array(adv_pro), 'b--',
    label='probability of adversarial')
    ax.plot(np.array(rotate_range), np.array(original_pro), 'r',
    label='probability of original')
    legend = ax.legend(loc='upper center', shadow=true, fontsize='large')
    legend.get_frame().set_facecolor('#ffffff')
    plt.xlabel('rotate range')
    plt.ylabel('probability')
    plt.show()
    如图8-5所示,横轴代表旋转的角度,纵轴代表预测概率,实线代表原始图像预测为熊猫的概率,虚线代表对抗样本预测为熊猫的概率。我们假设分类概率大于80%的结果可信,那么可以认为当旋转角度在30度到60度之间时,原有模型可以有效抵御定向攻击样本,同时不影响正常图片分类。
    图8-5 图像旋转对原始图像和对抗样本的鲁棒性示例

章节目录

智能系统与技术丛书·AI安全之对抗样本入门所有内容均来自互联网,一曲书屋只为原作者兜哥的小说进行宣传。欢迎各位书友支持兜哥并收藏智能系统与技术丛书·AI安全之对抗样本入门最新章节