首先:DeepFool是白盒攻擊算法
概述
生成對抗樣本的基本思路,大體可以分爲白盒攻擊和黑盒攻擊,區別在於黑盒測試把模型當做黑盒,只能輸入樣本獲得預測結果,白盒在黑盒的基礎上還可以獲取模型的參數、梯度等信息。本文將介紹白盒攻擊中最有名的DeepFool算法。
DeepFool基本原理
我們做攻擊,一個很好的問題就是,我們究竟對原始圖像做了多大修改就可以欺騙AI模型呢?換個說法就是,如何儘量少的修改原始圖像就可以達到欺騙AI模型的目的呢?首先我們先看下我們對原始圖像做了哪些修改。假設我們原始圖像爲x0file,對抗樣本爲x1file,將原始圖像保存成向量。
#原始圖像數據
x0_img = image.load_img(x0_file, target_size=(299, 299))
x0 = image.img_to_array(x0_img)
同樣的方法,將對抗樣本生成的圖像保存成向量。
#對抗樣本數據
x1_img = image.load_img(x1_file, target_size=(299, 299))
x1 = image.img_to_array(x1_img)
計算原始圖像和對抗樣本之間的差值,轉換成無符號的字節類型後保存成圖像。
#計算變化量
d=x1-x0
im = Image.fromarray(d.astype(np.uint8))
im.save(out)
以我們經典的小豬圖像爲原始圖像,效果如下圖所示。
FGSM算法生成的對抗樣本圖像,效果如下圖所示。
對抗樣本相對原始圖像的變化量,效果如下圖所示。
DeepFool最早由S. Moosavi-Dezfooli, A. Fawzi,和P. Frossard在《DeepFool: a simple and accurate method to fool deep neural networks》中提出。以最簡單的二分類問題爲例,如圖所示,假設分割平面是一個直線,直線的兩側分別對應不同的分類結果。
如果想改變其中某點的分類結果,一定要跨過分割平面。顯然最短的移動距離就是垂直分割平面進行移動。在線性代數裏面,點x到直線Ax+By+C=0的距離定義爲:
向量化表示距離如下,其中w爲參數矩陣。
推而廣之,在二分類問題中,當分割平面不是線性時,我們假設當移動的距離很小時,分割平面相對該點可以認爲依然是一個線性的分割平面,每次迭代時,該點都以很小的移動距離不斷逼近分割平面。
由於移動距離很小,可以使用該點的梯度代替參數矩陣w。多分類問題時,與二分類問題類似,只不過在迭代計算時需要考慮該點向不同分類標籤移動時要選取一定距離最短的那個。
攻擊圖像識別模型
以攻擊InceptionV3模型爲例,介紹生成攻擊樣本的基本原理。Keras內置了這個模型,我們直接使用就可以了。從模型中直接獲取第一層的輸入作爲輸入層,最後一層的輸出爲輸出層。
model = inception_v3.InceptionV3()
model_input_layer = model.layers[0].input
model_output_layer = model.layers[-1].output
然後加載我們攻擊的圖片,比如我們的小豬。這裏需要特別強調的是,NumPy出於性能考慮,默認的變量賦值會引用同樣一份內存,所以我們需要使用np.copy手工強制複製一份圖像數據。
img = image.load_img("…/picture/pig.jpg", target_size=(299, 299))
original_image = image.img_to_array(img)
hacked_image = np.copy(original_image)
爲了避免圖像變化過大,超過肉眼可以接受的程度,我們需要定義閾值。
max_change_above = original_image + 0.01
max_change_below = original_image - 0.01
下面我們要定義最關鍵的三個函數了,我們定義損失函數爲識別爲烤麪包機的概率,因此我們需要使用梯度上升算法,不斷追求損失函數的最大化,變量objecttypeto_fake定義的就是烤麪包機對應的標籤,在InceptionV3中麪包機的標籤爲859。
object_type_to_fake = 859
有了損失函數以後,我們就可以通過Keras的接口獲取到對應的梯度函數。最後通過K.function獲取一個Keras函數實例,該函數的輸入列表分別爲輸入層和當前是訓練模式還是測試模式的標記learning_phase(),輸出列表是損失函數和梯度。關於K.function的使用建議閱讀Keras的在線文檔。
除了迭代環節,DeepFool與FGSM的算法完全相同。在迭代環節,我們通過NumPy的inalg.norm函數對梯度進行處理,然後迭代更新圖片內容。
這裏需要特別介紹下linalg.norm函數,其函數原型爲:
x_norm=np.linalg.norm(x, ord=None, axis=None, keepdims=False)
其中ord表示矩陣的範數。
ord=1,列和的最大值,第一範式
ord=2,求特徵值,然後求最大特徵值得算術平方根,第二範式,也是默認值
axis表示處理類型。
axis=1表示按行向量處理,求多個行向量的範數
axis=0表示按列向量處理,求多個列向量的範數
axis=None表示矩陣範數。
在我的Mac本經過2分鐘27次迭代訓練,獲得了新的家豬圖像,但是機器學習模型識別它爲烤麪包機的概率卻達到了86.086%。
batch:20 Cost: 18.707792%
batch:21 Cost: 26.560178%
batch:22 Cost: 37.765652%
batch:23 Cost: 50.175613%
batch:24 Cost: 65.024394%
batch:25 Cost: 71.812165%
batch:26 Cost: 73.846906%
batch:27 Cost: 86.086935%
基於DeepFool算法被識別爲烤麪包機的家豬的圖片效果如下。
計算相對原始圖像的修改量,如下圖所示,顯然比FGSM修改量少。