【AI安全】对抗样本之FGSM的代码实现(TF2)

1. 简介

FGSM(Fast Gradient Sign Method)由Ian J. Goodfellow等人于2015年提出,论文地址【https://arxiv.org/abs/1412.6572】,是最早也是最受欢迎的欺骗神经网络的攻击之一。

对抗样本是创建的专门输入,目的是使神经网络分类器混淆,从而导致对给定输入错误地分类。

如图所示,攻击者对原始熊猫图像添加了小的扰动,导致了模型将这张图像标记为长臂猿。请添加图片描述
FGSM利用神经网络的梯度来创建一个对抗样本。对于输入的图像,该方法使用损失相对于输入图像的梯度来创建一个新的图像,使损失最大化。
【AI安全】对抗样本之FGSM的代码实现(TF2)

  • adv_x:生成的对抗样本图片
  • x:原始图片
  • y:原始图片的真实标签
  • 【AI安全】对抗样本之FGSM的代码实现(TF2):可以理解为学习率,用来控制添加扰动的大小
  • 【AI安全】对抗样本之FGSM的代码实现(TF2):模型参数
  • J:损失

2. 使用TensorFlow2实现FGSM

数据集为MNIST手写数字,使用FGSM对手写数字图片进行修改,实现对神经网络分类模型的攻击。

2.1 导包

import tensorflow as tf # 2.3
import matplotlib.pyplot as plt
import numpy as np
import tensorflow.keras.datasets.mnist as mnist 

2.2 数据准备

# 数据导入,获取训练集和测试集
(train_image, train_labels), (test_image, test_labels) = tf.keras.datasets.mnist.load_data()
# train_image.shape,train_labels.shape为(60000, 28, 28), (60000,)

train_image = (train_image - 127.5)/127.5 # 把0-255的数据范围变为-1到1之间
test_image = (test_image - 127.5)/127.5 # 把0-255的数据范围变为-1到1之间

# 增加通道维度
train_image = tf.expand_dims(train_image, -1)
test_image = tf.expand_dims(test_image, -1)
# TensorShape([60000, 28, 28, 1]), (60000,)

# 类型转换
train_image = tf.cast(train_image, tf.float32)
test_image = tf.cast(test_image, tf.float32)
train_labels = tf.cast(train_labels, tf.int64)
test_labels = tf.cast(test_labels, tf.int64)

# 创建Dataset
dataset = tf.data.Dataset.from_tensor_slices((train_image, train_labels)).shuffle(60000).batch(256)
test_dataset = tf.data.Dataset.from_tensor_slices((test_image, test_labels)).batch(256)

2.3搭建MLP模型并训练

# 模型搭建
model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28, 1)), 
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(10,activation='softmax') 
])
optimizer = tf.keras.optimizers.Adam()
loss_func = tf.keras.losses.SparseCategoricalCrossentropy()
model.compile(optimizer=optimizer,loss=loss_func,metrics=['acc'])
history = model.fit(dataset,validation_data=test_dataset,epochs=10) # 返回字典类型的数据 其中记录了准确率和损失的信息

【AI安全】对抗样本之FGSM的代码实现(TF2)

2.4 实现Fast Gradient Sign Method

loss_object = tf.keras.losses.SparseCategoricalCrossentropy()
def create_adversarial_pattern(input_image, input_label):
  with tf.GradientTape() as tape:
    tape.watch(input_image)
    prediction = model(input_image)
    loss = loss_object(input_label, prediction)
  gradient = tape.gradient(loss, input_image)
  # 对梯度使用sign函数,创建扰动
  signed_grad = tf.sign(gradient)
  return signed_grad

测试上述函数,查看扰动:

# test_image:测试集图片(1万张)
# test_labels:测试集标签
perturbations = create_adversarial_pattern(test_image, test_labels)
# 查看第一个扰动
plt.imshow(perturbations[0] * 0.5 + 0.5);  # [-1, 1] -> [0,1]

【AI安全】对抗样本之FGSM的代码实现(TF2)

2.5 定义绘图函数

用于查看原图片模型预测的结果和扰动之后的结果对比

# image:原始图片集合
# label:原始图片模型预测的标签
# adv_label:添加扰动后模型预测的标签
# num:每次绘图的数量
def display_images(image, label,adv_label,num=10):
    fig = plt.figure(figsize=(2*num,3)) # figsize:指定figure的宽和高,单位为英寸
    for i in range(num):   # pre_image的shape的第一个维度就是个数,这里是num
        plt.subplot(1,num,i+1) # 几行几列的 第i+1个图片(从1开始)
        plt.imshow((image[i,:,:,:] + 1)/2) # 加1除2: 将生成的-1~1的图片弄到0-1之间,
        plt.title('{} -> {}'.format(label[i],adv_label[i]))
        plt.axis('off') # 不要坐标
    plt.show()

2.6 在测试集上添加扰动查看效果

# 在不同的epsilons进行测试
epsilons = [0,0.05,0.10,0.15,0.20,0.25,0.30]
adv_acc_list = []
for i, eps in enumerate(epsilons):
  print("epsilons = {}:".format(eps))
  # 获取原始图片的预测结果
  test_image = tf.clip_by_value(test_image, -1, 1)
  predict_label = model.predict(test_image)
  predict_label = np.array([np.argmax(i) for i in predict_label])
  # 生成对抗样本,并获取预测结果
  adv_image = test_image + eps*perturbations
  adv_image = tf.clip_by_value(adv_image, -1, 1)
  adv_predict_label = model.predict(adv_image)
  adv_predict_label = np.array([np.argmax(i) for i in adv_predict_label])
  # 在对抗样本集合中评估模型
  score = model.evaluate(adv_image,test_labels,verbose=0)
  adv_acc_list.append(score[1])
  # 绘图
  display_images(adv_image,predict_label,adv_predict_label)

【AI安全】对抗样本之FGSM的代码实现(TF2)

2.7 查看准确率变化

plt.title("The Accuracy of Adversarial Samples")
plt.xlabel("epsilons")
plt.ylabel("acc")
plt.plot(epsilons,adv_acc_list)

【AI安全】对抗样本之FGSM的代码实现(TF2)
参考资料:
https://tensorflow.google.cn/tutorials/generative/adversarial_fgsm?hl=zh-cn

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2022年6月1日 上午11:31
下一篇 2022年6月1日

相关推荐