機器學習原來如此有趣:如何故意欺騙神經網絡
只要程序員一直在編寫計算機程序,計算機黑客就會一直尋找破解這些程序的方法。惡意黑客利用程序中最小的錯誤來破解系統,竊取數據,然后會造成嚴重破壞。
但由深度學習算法驅動的系統應該能夠避免人為干擾,對嗎?一個黑客如何破解經過TB級數據訓練出的神經網絡?
事實證明,即使是最先進的深層神經網絡也容易被愚弄。有一些技巧,你可以迫使他們預測你想要的結果:
我修改了這張貓圖片,所以它被認為是烤面包機。
因此,在你啟動由深層神經網絡驅動的新系統之前,讓我們詳細了解如何破解這些系統,以及如何保護自己免受攻擊者的傷害。
將神經網絡作為安全衛士
我們假設我們經營像Ebay這樣的拍賣網站。在我們的網站上,我們想防止人們出售違禁物品 比如活的動物。
如果你有數百萬的用戶,執行這些規則是很困難的。我們可以聘請數百人手動審查每一個拍賣清單,但這顯然是不合理的。相反,我們可以使用深度學習自動檢查違禁物品的拍賣照片,并標記違反規定的拍攝照片。
這是一個典型的圖像分類問題。為了構建這個,我們將訓練一個深層卷積神經網絡來告訴機器禁止的項目和允許上傳的項目,然后我們將通過它運行我們網站上的所有照片。
首先,我們需要一個來自過去拍賣列表的成千上萬個圖像的數據集。我們需要允許和禁止的項目的圖像,以便我們可以訓練神經網絡來告訴他們:
為了訓練神經網絡,我們將使用標準的反向傳播算法。這種算法的特點是,我們輸入一個訓練圖片,輸入該圖片的預期結果,然后回到神經網絡中的每一層輕輕地調整他們的權重,使他們更好地產生該圖片的正確輸出:
我們用數千張照片重復上千次,直到模型以可接受的準確性可靠地產生正確的結果。
最終的結果是可以可靠地分類圖像的神經網絡:
但事情并不如他們看起來那么可靠。。。
卷積神經網絡是對整個圖像進行分類時考慮的強大模型。無論復雜的形狀和圖案出現在哪里,他都可以識別到。在許多圖像識別任務中,它們們與人類的表現不相上下,有時候甚至能夠擊敗人類。
有了像這樣的杰出的模型,將圖像中的幾個像素更改為更暗或更輕,對最終的預測不應該有很大的影響,對吧?當然可能會稍微改變最終的可能性,但不會將圖像從“禁止”轉換為“允許”。
我們期望的是:輸入照片的小變化只能對最終預測造成微小的變化。
但是在2013年的著名論文“神經網絡”中,發現這并不總是真的。如果你知道到底是哪個像素改變了和究竟有多少個像素被改變,你可以有意迫使神經網絡對于給定的照片做出錯誤的輸出,而不需要對圖片的外觀改變非常多的地方。
這意味著我們可以有意制作一張明顯是禁止物品的照片,但完全愚弄我們的神經網絡:![]()
為什么是這樣?機器學習分類器的工作原理是找到分開的東西之間的分界線。以下是一個簡單的二維分類器的圖形,它被要求學習將綠點(可接受)與紅點(禁止)分開:![]()
現在,分類器的精度達到100%。它發現一條線,將所有的綠點與紅點完美分開。
但是,如果我們欺騙它讓它講一個紅點當做綠點來分類呢?我們可以將紅點推到綠色領域的最低限度是多少?
如果我們在邊界旁邊的紅點的Y值加少量,那么我們幾乎可以把它推到綠色領域:![]()
所以要欺騙一個分類器,我們只需要知道向哪個方向來推動這個點,以便讓它在一行上。如果我們不想對惡意言論過于明確,理想情況下我們會盡可能的減少這一點,這樣看起來就是一個誠實的錯誤。
在具有深層神經網絡的圖像分類中,我們分類的每個“點”是由數千個像素組成的整個圖像。這給了我們數千種可能的值,讓我們去調整值來將這個點推到決定界限的另一頭。如果我們可以以不太明顯的方式調整圖像中的像素,我們就可以愚弄分類器,而不會使圖像看起來受到操縱。
換句話說,我們可以為一個對象拍一張照片,然后非常輕微地改變像素,使得圖像完全可以騙過神經網絡 - 而且我們可以精確地控制它檢測到的對象:
把一只貓變成烤面包機 來自Keras.js基于Web的演示的圖像檢測結果
如何欺騙神經網絡
我們已經討論了訓練神經網絡分類照片的基本過程:
1.飼養(Feed in)訓練照片。
2.檢查神經網絡的預測,看看距離正確答案有多遠。
3.使用反向傳播調整神經網絡中每一層的權重,使最終預測更接近正確答案。
4.重復步驟1-3幾千次與幾千個不同的訓練照片。
但是,如果不調整神經網絡的層次的權重,而是改變輸入圖像本身直到我們得到我們想要的答案為止會怎么樣呢?
所以讓我們使用已經訓練好的神經網絡,并進再次“訓練”。但是這次讓我們使用反向傳播來調整輸入圖像而不是神經網絡層:![]()
所以這里是新的算法:
1.輸入我們想要hack的圖片
2.檢查神經網絡的預測,看看我們想要獲得的答案還有多遠。
3.使用反向傳播調整我們的照片,使最終的預測更接近我們想要的答案。
4.使用相同的照片重復步驟1-3幾千次, 直到網絡給我們想要的答案。
在這個結尾,我們將有一個可以愚弄神經網絡的圖像,而不改變神經網絡本身內的任何東西。
唯一的問題是,沒有任何限制的允許調整任何單個像素,圖像的更改可能會非常大,他們會出現變色斑點或波浪區域:![]()
為了防止這些明顯的扭曲,我們可以為我們的算法添加一個簡單的約束。我們可以規定被hacked的圖像每個像素的改變范圍- 比如說不能超過0.01%。這迫使我們的算法以一種仍然愚弄神經網絡的方式來調整圖像,而不會看起來與原始圖像不同。
以下是添加該約束時生成的圖像的樣子:
下面就可以開始寫代碼了!
為了編碼,首先我們需要一個預先訓練的神經網絡來被欺騙。而不是從頭開始培訓,我們將會使用Google創建的。
受歡迎的深層學習框架Keras帶有幾個預先訓練的神經網絡。我們將使用經過預處理的Google Inception v3深層神經網絡副本來檢測1000種不同類型的對象。
這里是Keras的基本代碼,用于識別使用該神經網絡的圖片中的內容。在運行之前,請確保安裝了Python 3和Keras:
import numpy as np
from keras.preprocessing import image
from keras.applications import inception_v3
# Load pre-trained image recognition model
model = inception_v3.InceptionV3()
# Load the image file and convert it to a numpy array
img = image.load_img("cat.png", target_size=(299, 299))
input_image = image.img_to_array(img)
# Scale the image so all pixel intensities are between [-1, 1] as the model expects
input_image /= 255.
input_image -= 0.5
input_image *= 2.
# Add a 4th dimension for batch size (as Keras expects)
input_image = np.expand_dims(input_image, axis=0)
# Run the image through the neural network
predictions = model.predict(input_image)
# Convert the predictions into text and print them
predicted_classes = inception_v3.decode_predictions(predictions, top=1)
imagenet_id, name, confidence = predicted_classes[0][0]
print("This is a {} with {:.4}% confidence!".format(name, confidence * 100))
view rawpredict.py hosted with ? by GitHub
當我們運行它,它將正確地檢測我們的圖是一只波斯貓:
$ python3 predict.py
This is a Persian_cat with 85.7% confidence!
現在讓我們來想一想,通過調整圖像,直到它騙過神經網絡,這只貓才是烤面包機。
Keras沒有內置的方式來訓練輸入圖像,只能訓練神經網絡層,所以我不得不來點小技巧,手動編寫訓練步驟。
以下是代碼:
import numpy as np
from keras.preprocessing import image
from keras.applications import inception_v3
from keras import backend as K
from PIL import Image
# Load pre-trained image recognition model
model = inception_v3.InceptionV3()
# Grab a reference to the first and last layer of the neural net
model_input_layer = model.layers[0].input
model_output_layer = model.layers[-1].output
# Choose an ImageNet object to fake
# The list of classes is available here: https://gist.github.com/ageitgey/4e1342c10a71981d0b491e1b8227328b
# Class #859 is "toaster"
object_type_to_fake = 859
# Load the image to hack
img = image.load_img("cat.png", target_size=(299, 299))
original_image = image.img_to_array(img)
# Scale the image so all pixel intensities are between [-1, 1] as the model expects
original_image /= 255.
original_image -= 0.5
original_image *= 2.
# Add a 4th dimension for batch size (as Keras expects)
original_image = np.expand_dims(original_image, axis=0)
# Pre-calculate the maximum change we will allow to the image
# We'll make sure our hacked image never goes past this so it doesn't look funny.
# A larger number produces an image faster but risks more distortion.
max_change_above = original_image + 0.01
max_change_below = original_image - 0.01
# Create a copy of the input image to hack on
hacked_image = np.copy(original_image)
# How much to update the hacked image in each iteration
learning_rate = 0.1
# Define the cost function.
# Our 'cost' will be the likelihood out image is the target class according to the pre-trained model
cost_function = model_output_layer[0, object_type_to_fake]
# We'll ask Keras to calculate the gradient based on the input image and the currently predicted class
# In this case, referring to "model_input_layer" will give us back image we are hacking.
gradient_function = K.gradients(cost_function, model_input_layer)[0]
# Create a Keras function that we can call to calculate the current cost and gradient
grab_cost_and_gradients_from_model = K.function([model_input_layer, K.learning_phase()], [cost_function, gradient_function])
cost = 0.0
# In a loop, keep adjusting the hacked image slightly so that it tricks the model more and more
# until it gets to at least 80% confidence
while cost < 0.80:
# Check how close the image is to our target class and grab the gradients we
# can use to push it one more step in that direction.
# Note: It's really important to pass in '0' for the Keras learning mode here!
# Keras layers behave differently in prediction vs. train modes!
cost, gradients = grab_cost_and_gradients_from_model([hacked_image, 0])
# Move the hacked image one step further towards fooling the model
hacked_image += gradients * learning_rate
# Ensure that the image doesn't ever change too much to either look funny or to become an invalid image
hacked_image = np.clip(hacked_image, max_change_below, max_change_above)
hacked_image = np.clip(hacked_image, -1.0, 1.0)
print("Model's predicted likelihood that the image is a toaster: {:.8}%".format(cost * 100))
# De-scale the image's pixels from [-1, 1] back to the [0, 255] range
img = hacked_image[0]
img /= 2.
img += 0.5
img *= 255.
# Save the hacked image!
im = Image.fromarray(img.astype(np.uint8))
im.save("hacked-image.png")
如果我們運行這個,它最終會吐出一個會欺騙神經網絡的圖像:
$ python3 generated_hacked_image.py
Model's predicted likelihood that the image is a toaster: 0.00072%
[ .... a few thousand lines of training .... ]
Model's predicted likelihood that the image is a toaster: 99.4212%
注意:如果你沒有GPU,則可能需要幾個小時才能運行。如果你的GPU正確配置了Keras和CUDA,則運行時間不應超過兩分鐘。
現在我們來測試一下我們剛剛通過原始模型運行的黑客圖像:
$ python3 predict.py
This is a toaster with 98.09% confidence!
我們做到了!我們欺騙神經網絡讓它認為這只貓是烤面包機!
我們可以用黑客圖像做什么?
創建了一個被這樣被黑客攻擊的圖像稱為“產生對抗的例子”。我們有意制作一個數據,以便機器學習模型將錯誤分類。這是一個有趣的戲法,但為什么這在現實世界中這是一個麻煩呢?
研究表明,這些黑客圖像有一些令人驚訝的屬性:
1.即使它們打印在紙上,黑客圖像仍然可以欺騙神經網絡!因此,你可以使用這些被黑客入侵的圖像來愚弄物理攝像機或掃描儀,而不僅僅是直接上傳圖像文件的系統。
2.愚弄一個神經網絡的圖像傾向于以完全不同的設計愚弄其他神經網絡,如果他們接受類似數據的訓練。
所以我們可以用這些黑客圖片做很多事情!
但是我們如何創建這些圖像仍然有很大的限制 - 我們的攻擊需要直接訪問神經網絡本身。因為我們實際上是“訓練”神經網絡來愚弄,所以我們需要一個它的副本。在現實世界中,沒有任何公司會讓你下載他們訓練有素的神經網絡的代碼,這意味著我們不能攻擊他們...對吧?
不!研究人員最近表明,你可以訓練你自己的替代神經網絡,通過探索另一個神經網絡來觀察其行為。然后,你可以使用你的替代神經網絡來生成愚弄原始網絡的黑客圖像!這被稱為黑匣子攻擊。
黑匣子攻擊的應用是無限的。這里有一些合理的例子:
- 自駕車把紅燈視為綠燈,這樣可能會導致汽車出車禍!
- 技巧內容過濾系統讓冒犯/非法內容通過。
而這些攻擊方法并不僅限于圖像。你可以使用同樣的方法來愚弄可用于其他類型數據的分類器。例如,你可以欺騙病毒掃描程序將你的病毒識別為安全的代碼!
我們如何保護自己免受這些襲擊?
那么現在我們知道有可能欺騙神經網絡(和所有其他機器學習模型),我們如何防御這個攻擊呢?
簡單的答案是,沒有人是完全確定的。防止這種攻擊仍然是一個持續的研究領域。跟隨最新發展的最好方法是閱讀由Ian Goodfellow和Nicolas Papernot維護的這個由這個領域最有影響力的研究人員組成的cleverhans blog。
但到目前為止我們知道的一些事情:
- 如果你只是創建大量被黑客入侵的圖像,并將它們包含在你未來的培訓數據集中,那似乎使你的神經網絡更能抵御這些攻擊。這被稱為對抗訓練,現在可能是比較合理的方法。
- 還有另一種有效的方法叫做防御性蒸餾,你可以在此訓練第二個模型來模擬你的原始模型。但是這種方法是新的而且相當復雜的,所以我不會投資這個,除非你有專門的需求。
- 研究人員迄今為止嘗試過的其他所有想法幾乎都不能有助于防止這些攻擊。
由于我們還沒有任何最終答案,你需要謹慎考慮使用神經網絡的場景,以便減少這種攻擊會對你的業務造成損害的風險。



浙公網安備 33010602011771號