Press "Enter" to skip to content

Keras深度学习实战(19)——使用对抗攻击生成可欺骗神经网络的图像

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

Keras深度学习实战(19)——使用对抗攻击生成可欺骗神经网络的图像

 

0. 前言

 

近年来,深度学习在图像分类、 目标检测图像分割 、音频识别等诸多领域取得了突破性进展,深度学习模型已经能够以接近甚至超越人类水平的完成某些特定任务。

 

但最近的研究表明,深度学习模型容易受到输入数据中细微扰动的影响,从而导致模型输出错误的预测。在图像领域,此类扰动通常很小对于人眼而言甚至无法察觉,但它们却能够愚弄深度学习模型。针对深度学习模型的这种对抗攻击,限制了深度学习的成功在更广泛领域的应用。

 

本节中,我们将介绍对抗攻击 ( Adversarial Attack ) 的基本概念,并使用 Keras 实现对抗攻击生成可欺骗神经网络的图像。

 

1. 对抗攻击简介

 

深度学习在执行各种计算机视觉任务方面都有着优异的准确性,但尽管深度学习模型的精确度很高,现代深度网络却容易被微小扰动形式的对抗攻击所干扰,这些扰动对虽然对人类视觉系统而言几乎无法感知,但却可能导致神经网络分类器完全改变其对图像的预测。甚至,被攻击的模型对错误的预测结果具有很高的置信度。此外,相同的图像扰动可能使多个深度网络分类器得到错误输出,这引发了研究人员对对抗攻击的广泛兴趣。

 

包含恶意扰动的数据通常称为对抗样本 ( Adversarial Example ),而对抗攻击 ( Adversarial Attack ) 则是构建对抗样本的并对目标模型实施攻击的过程。例如,如下图所示,通过在图像中添加不明显的扰动,并不会影响人类对其内容的判断,但深度神经网络却对扰动后的图像输出了完全错误的分类结果。

 

2. 对抗攻击模型分析

 

为了了解如何对图像进行对抗攻击,我们首先回顾如何使用深度学习模型进行常规预测,然后我们将研究如何调整输入图像,以使深度学习模型对图像输出完全不同的类别,即使修改后的图像在人眼看来与原始图像并无差别。

 

2.1 模型识别图像流程

 

本小节,我们首先通过一个示例回顾深度学习模型识别图像流程,在该示例中我们尝试使用训练完成的深度学习模型预测红狐图片:

 

Inception
Inception v3
Inception

 

2.2 对抗攻击流程

 

接下来,我们的介绍如何通过在图中添加微小扰动修改图像,使其满足以下两个目标:

使用同一网络对修改后的图像进行预测,令模型预测结果改变为山猫
修改后的图像在人类看来没有区别

为了使生成的对抗样本完成以上目标,我们制定以下对抗攻击策略:

定义损失函数:

损失值是红狐图像属于山猫类别的概率
损失值越大,表明我们越接近欺骗神经网络输出错误结果的目标
因此,我们将最大化损失函数

计算相对于输入变化的损失变化梯度:

此步骤有助于了解将输出移向我们目标的输入像素

重复以上步骤,直到模型以至少 0.8 的置信度将修改后的图像预测为山猫

3. 使用 Keras 实现对抗攻击

 

在本节中,我们使用 Keras 实现上述对抗攻击策略,以生成对抗样本。

 

(1)导入所需库,读取红狐图片的图像,并查看图片:

 

import matplotlib.pyplot as plt
import cv2
import numpy as np
from keras import backend as K
img = cv2.imread('5.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()

 

 

(2)预处理图像,以便可以将其传递到 Inception 网络:

 

img = cv2.resize(img, (299,299))
# 将图像像素值归一化至[-1,1]
original_image = img.astype('float')/255
original_image -= 0.5
original_image *= 2.
# 维度扩展
original_image = np.expand_dims(original_image, axis=0)

 

(3)导入预训练的模型,并使用此模型预测图像中对象的类别:

 

from keras.preprocessing import image
from keras.applications import inception_v3
model = inception_v3.InceptionV3()
predictions = model.predict(original_image)
predicted_classes = inception_v3.decode_predictions(predictions, top=1)
imagnet_id, name, confidence = predicted_classes[0][0]
print("This is a {} with {:.4}% confidence".format(name, confidence * 100))

 

模型对于输入的图像,输出的预测结果如下,看以看到模型可以以很高的置信度得到正确的结果:

 

This is a red_fox with 92.09% confidence

 

(4)接下来,为对抗攻击模型定义输入和输出:

 

model_input_layer = model.layers[0].input
model_output_layer = model.layers[-1].output

 

model_input_layer 是模型的输入,而 model_output_layer (具有 softmax 激活函数的最后一层)是输入图像属于各种类别的概率。

 

(5)设置原始图像的修改限制(即图片最大变化阈值),指定了修改原始图像应遵照的限制:

 

max_change_above = np.copy(original_image) + 0.01
max_change_below = np.copy(original_image) - 0.01
adversarial_sample = np.copy(original_image)

 

(6)初始化损失函数,以便模型将修改后图像预测为山猫(模型输出预测向量中的第 283 个索引值):

 

learning_rate = 0.1
prob_cat = []
# 山猫
object_type_to_fake = 283
cost_function = model_output_layer[0, object_type_to_fake]

 

model_output_layer 的输出是图像的各种类别的概率,我们指定损失函数由我们要伪造对象类别的索引位置决定。

 

(7)初始化损失相对于输入的梯度函数:

 

gradient_function = K.gradients(cost_function, model_input_layer)[0]

 

此代码计算 cost_function 相对于 model_input_layer (输入图像)的梯度变化。需要注意的是,如果使用 TensorFlow2 作为 Keras 的后端,会报如下错误:

 

Traceback (most recent call last):
  File "adversarial_attack.py", line 45, in <module>
    gradient_function = K.gradients(cost_function, model_input_layer)[0]
  File "/python3.7/lib/python3.7/site-packages/tensorflow/python/keras/backend.py", line 3969, in gradients
    loss, variables, colocate_gradients_with_ops=True)
  File "/python3.7/lib/python3.7/site-packages/tensorflow/python/ops/gradients_impl.py", line 172, in gradients
    unconnected_gradients)
  File "/python3.7/lib/python3.7/site-packages/tensorflow/python/ops/gradients_util.py", line 491, in _GradientsHelper
    raise RuntimeError("tf.gradients is not supported when eager execution "
RuntimeError: tf.gradients is not supported when eager execution is enabled. Use tf.GradientTape instead.

 

为了解决上述问题,需要在代码开头加上以下代码,切换梯度求解的执行模型:

 

import tensorflow as tf
tf.compat.v1.disable_eager_execution()

 

(8)定义输入与损失和梯度变化的映射函数,计算 cost_function 值(即该图像属于山猫类别的概率)和相对于输入图像的梯度信息:

 

grab_cost_and_gradients_from_model = K.function([model_input_layer], [cost_function, gradient_function])

 

(9)使用梯度信息不断更新输入图像,直到模型以至少 0.8 的置信度将修改后的图像预测为山猫:

 

cost = 0.0
while cost < 0.80:
    cost, gradients = grab_cost_and_gradients_from_model([adversarial_sample, 0])
    adversarial_sample += gradients * learning_rate
    adversarial_sample = np.clip(adversarial_sample, max_change_below, max_change_above)
    prob_cat.append(cost)
    print("Model's predicted likelihood that the image is an tiger cat: {:.8}%".format(cost * 100))

 

在以上代码中,我们获得了与输入图像 ( adversarial_sample ) 相对应的损失和梯度信息。另外,我们利用梯度(乘以学习率)更新输入图像。最后,如果被修改的图片超过了预定义的图片最大变化阈值,我们会对其进行裁剪,以确保图像修改前后的变化并不明显。不断循环执行这些步骤,直到获得输入图像至少有 0.8 的概率被预测为山猫为止。

 

Model's predicted likelihood that the image is an tiger cat: 0.0043381504%
Model's predicted likelihood that the image is an tiger cat: 0.0043390162%
...
Model's predicted likelihood that the image is an tiger cat: 74.044788%
Model's predicted likelihood that the image is an tiger cat: 89.34136%

 

(10)绘制随着 epoch 的改变,红狐图像被检测为山猫图像的概率的变化:

 

epochs = range(1, len(prob_cat) + 1)
plt.plot(epochs, prob_cat, 'b')
plt.title('Probability of African elephant class')
plt.xlabel('Epochs')
plt.ylabel('Probability')
plt.show()

 

得到的图像被预测为山猫的概率变化如下:

 

 

(11)预测被修改后的图像类别概率:

 

output = model.predict(adversarial_sample)[0]
print('class: ', np.argmax(output), 'confidence: ', output[np.argmax(output)])

 

预测输出已经被修改为 283 ,即山猫,且概率为 0.9487

 

class:  283 confidence:  0.94870704

 

(12)由于在输入图像时对其进行了预处理,为了将其可视化,需要对修改后的输入图像进行逆预处理过程。原始图像、对抗样本(即被修改后图像)以及两个图像之间的差异(即添加的对抗性扰动)可视化如下:

 

adversarial_sample = adversarial_sample / 2
adversarial_sample = adversarial_sample + 0.5
adversarial_sample = adversarial_sample * 255
adversarial_sample = np.clip(adversarial_sample, 0, 255).astype('uint8')
plt.subplot(131)
plt.imshow(img)
plt.title('Original image')
plt.subplot(132)
plt.imshow(adversarial_sample[0,:,:,:])
plt.title('Adversarial sample')
plt.subplot(133)
plt.imshow(img - adversarial_sample[0,:,:,:])
plt.title('Difference')
plt.show()

 

 

尽管深度神经网络在各种计算机视觉任务上具有很高的准确性,但研究表明它们容易受到微小扰动的影响,从而导致它们输出完全错误的预测结果。由于深度学习是当前机器学习和人工智能的核心技术,这一缺陷引起了研究人员广泛的兴趣。本文首先介绍了对抗攻击的基本概念,然后利用 Keras 实现了一种经典的对抗攻击算法,通过在图中添加微小扰动令红狐图像被错误的预测为山猫图像,我们也可以通过改变攻击的目标索引,来使图像被错误分类为其它类别。

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。