【AI安全】对抗样本之FGSM的代码实现(TensorFlow2)
文章目錄
- 1. 簡介
- 2. 使用TensorFlow2實現FGSM
- 2.1 導包
- 2.2 數據準備
- 2.3搭建MLP模型并訓練
- 2.4 實現Fast Gradient Sign Method
- 2.5 定義繪圖函數
- 2.6 在測試集上添加擾動查看效果
- 2.7 查看準確率變化
1. 簡介
FGSM(Fast Gradient Sign Method)由Ian J. Goodfellow等人于2015年提出,論文地址【https://arxiv.org/abs/1412.6572】,是最早也是最受歡迎的欺騙神經網絡的攻擊之一。
對抗樣本是創(chuàng)建的專門輸入,目的是使神經網絡分類器混淆,從而導致對給定輸入錯誤地分類。
如圖所示,攻擊者對原始熊貓圖像添加了小的擾動,導致了模型將這張圖像標記為長臂猿。
FGSM利用神經網絡的梯度來創(chuàng)建一個對抗樣本。對于輸入的圖像,該方法使用損失相對于輸入圖像的梯度來創(chuàng)建一個新的圖像,使損失最大化。
adv_x=x+??sign(?xJ(θ,x,y))adv\_x = x + \epsilon * sign(\nabla_xJ(\theta,x,y)) adv_x=x+??sign(?x?J(θ,x,y))
- adv_x:生成的對抗樣本圖片
- x:原始圖片
- y:原始圖片的真實標簽
- ?\epsilon?:可以理解為學習率,用來控制添加擾動的大小
- θ\thetaθ:模型參數
- 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 mnist2.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的數據范圍變?yōu)?1到1之間 test_image = (test_image - 127.5)/127.5 # 把0-255的數據范圍變?yōu)?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)# 創(chuàng)建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) # 返回字典類型的數據 其中記錄了準確率和損失的信息
測試集上的準確率可達到97.6%
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函數,創(chuàng)建擾動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]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的第一個維度就是個數,這里是numplt.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*perturbationsadv_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)2.7 查看準確率變化
plt.title("The Accuracy of Adversarial Samples") plt.xlabel("epsilons") plt.ylabel("acc") plt.plot(epsilons,adv_acc_list)GitHub地址:FGSM_TensorFlow2_mnist
參考資料:
https://tensorflow.google.cn/tutorials/generative/adversarial_fgsm?hl=zh-cn
總結
以上是生活随笔為你收集整理的【AI安全】对抗样本之FGSM的代码实现(TensorFlow2)的全部內容,希望文章能夠幫你解決所遇到的問題。