Keras深度學習——使用對抗攻擊生成可欺騙神經網路的影象

語言: CN / TW / HK

theme: hydrogen

持續創作,加速成長!這是我參與「掘金日新計劃 · 6 月更文挑戰」的第16天,點選檢視活動詳情

0. 前言

為了瞭解如何對影象進行對抗攻擊,我們首先回顧如何使用深度學習模型進行常規預測,然後我們將研究如何調整輸入影象,以使深度學習模型對影象輸出完全不同的類別,即使修改後的影象在人眼看來與原始影象並無差別。

1. 對抗攻擊簡介

1.1 模型識別影象流程

讓我們來看一個示例,在該示例中我們將嘗試識別影象中物件的類: - 使用訓練完成的深度學習模型預測紅狐圖片 - 對輸入影象進行預處理,以便可以將其傳遞到 Inception 網路中 - 匯入預訓練的 Inception v3 模型 - 使用 Inception 模型預測影象類別 - 影象將被預測為紅狐

1.2 對抗攻擊流程

接下來,我們的任務是修改影象,使其滿足以下兩個目標: - 使用同一網路對修改後的影象進行預測,令模型預測結果改變為山貓 - 修改後的影象在人類看來沒有區別

為了達到以上目標,我們制定以下策略: - 定義損失函式: - 損失值是紅狐影象屬於山貓類別的概率 - 損失值越大,表明我們越接近欺騙神經網路輸出錯誤結果的目標 - 因此,我們將最大化損失函式 - 計算相對於輸入變化的損失變化梯度: - 此步驟有助於瞭解將輸出移向我們目標的輸入畫素 - 根據計算出的梯度來更新輸入影象: - 確保原始影象中的畫素值與最終影象中的畫素值相差不超過 3 - 這樣可以確保生成的影象與原始影象在人眼看來幾乎沒有差別 - 重複以上步驟,直到模型以至少 0.8 的置信度將修改後的影象預測為山貓

2. 使用 Keras 實現對抗攻擊

在本節中,我們使用 Keras 實現上述策略,生成對抗樣本。 讀取紅狐圖片的影象: ```python 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() ``` 影象的視覺化結果如下所示:

紅狐圖片

預處理影象,以便可以將其傳遞到 Inception 網路: ```python 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) 匯入預訓練的模型,並使用此模型預測影象中物件的類別:python 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)) 模型對於輸入的影象,輸出的預測結果如下,看以看到模型可以以很高的置信度得到正確的結果:python This is a red_fox with 92.09% confidence 接下來,為對抗攻擊模型定義輸入和輸出:python model_input_layer = model.layers[0].input model_output_layer = model.layers[-1].output `model_input_layer` 是模型的輸入,而 `model_output_layer` (具有 `softmax` 啟用函式的最後一層)是輸入影象屬於各種類別的概率。 設定原始影象的修改限制(即圖片最大變化閾值),指定了修改原始影象應遵照的限制:python max_change_above = np.copy(original_image) + 0.01 max_change_below = np.copy(original_image) - 0.01 adversarial_sample = np.copy(original_image) 初始化損失函式,以便模型將修改後影象預測為山貓(模型輸出預測向量中的第 `283` 個索引值):python learning_rate = 0.1 prob_cat = []

山貓

object_type_to_fake = 283 cost_function = model_output_layer[0, object_type_to_fake] `model_output_layer` 的輸出是影象的各種類別的概率。在本例中,我們指定損失函式由我們要偽造物件類別的索引位置決定。 初始化損失相對於輸入的梯度函式:python gradient_function = K.gradients(cost_function, model_input_layer)[0] `` 此程式碼計算cost_function相對於model_input_layer` (輸入影象)的梯度變化。

定義輸入與損失和梯度變化的對映函式,計算 cost_function 值(即該影象屬於山貓類別的概率)和相對於輸入影象的梯度資訊: python grab_cost_and_gradients_from_model = K.function([model_input_layer], [cost_function, gradient_function]) 使用梯度資訊不斷更新輸入影象,直到模型以至少 0.8 的置信度將修改後的影象預測為山貓: ```python 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` 的概率被預測為山貓為止。shell 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% ```

預測被修改後的影象類別概率: python output = model.predict(adversarial_sample)[0] print('class: ', np.argmax(output), 'confidence: ', output[np.argmax(output)]) 預測輸出已經被修改為 283,即山貓,且概率為 0.9487python class: 283 confidence: 0.94870704