久久ER99热精品一区二区-久久精品99国产精品日本-久久精品免费一区二区三区-久久综合九色综合欧美狠狠

博客專(zhuān)欄

EEPW首頁(yè) > 博客 > 獨(dú)家 | 對(duì)抗圖像和攻擊在Keras和TensorFlow上的實(shí)現(xiàn)(1)

獨(dú)家 | 對(duì)抗圖像和攻擊在Keras和TensorFlow上的實(shí)現(xiàn)(1)

發(fā)布人:數(shù)據(jù)派THU 時(shí)間:2020-12-21 來(lái)源:工程師 發(fā)布文章

[ 摘要 ]在這篇教程中,你將會(huì)學(xué)到如何用基于圖像的對(duì)抗攻擊來(lái)破壞深度學(xué)習(xí)模型。我們將會(huì)利用Keras和TensorFlow深度學(xué)習(xí)庫(kù)來(lái)實(shí)現(xiàn)自己的對(duì)抗攻擊。

5.png

試想下從現(xiàn)在起的二十年后。現(xiàn)在路上所有的車(chē)輛都是利用人工智能、深度學(xué)習(xí)和計(jì)算機(jī)視覺(jué)來(lái)驅(qū)動(dòng)的無(wú)人駕駛交通工具。每一次轉(zhuǎn)彎、車(chē)道轉(zhuǎn)換、加速和剎車(chē)都是由深度神經(jīng)網(wǎng)絡(luò)來(lái)提供技術(shù)支持。現(xiàn)在,想象自己在高速路上,你正坐在“駕駛室(當(dāng)車(chē)自主行駛時(shí),駕駛室還能被稱(chēng)為‘駕駛室’嗎?)”里,你的妻子坐在副駕上,你的孩子們坐在后座。

朝前看,你看到一張巨大的貼紙正在車(chē)輛所行駛的車(chē)道上,這看上去對(duì)車(chē)的前進(jìn)毫無(wú)影響。看上去這像是一張受歡迎的大幅涂鴉藝術(shù)版畫(huà),可能是幾個(gè)高中生開(kāi)玩笑把它放在這里,或者他們只是為了完成某個(gè)大冒險(xiǎn)游戲。

4.png

圖一:執(zhí)行一次對(duì)抗攻擊需要一張輸入圖像(左),故意用一個(gè)噪聲向量來(lái)擾亂它(中),迫使神經(jīng)網(wǎng)絡(luò)對(duì)輸入圖像進(jìn)行錯(cuò)誤分類(lèi),最后得到一個(gè)錯(cuò)誤的分類(lèi)結(jié)果,很可能會(huì)出現(xiàn)一次嚴(yán)重的后果(右)。

一瞬間,你的汽車(chē)突然急剎車(chē),然后立即變道,因?yàn)榉旁诼飞系哪菑堎N畫(huà)可能印的是行人、動(dòng)物或者另一輛汽車(chē)。你在車(chē)?yán)锉幻屯屏艘幌拢械筋i部似乎受了傷。你的妻子尖叫著,孩子們的零食在后座上蹦了起來(lái),彈在擋風(fēng)玻璃上后灑在中控臺(tái)上。你和你的家人都很安全,但所經(jīng)歷的這一切看上去不能再糟糕了。

發(fā)生了什么?為什么你的自動(dòng)駕駛車(chē)輛會(huì)做出這樣的反應(yīng)?是不是車(chē)內(nèi)的某段代碼或者某個(gè)軟件存在奇怪的“bug”?

答案就是,為車(chē)輛視覺(jué)組件提供技術(shù)支持的深度神經(jīng)網(wǎng)絡(luò)看到了一張對(duì)抗圖像。

對(duì)抗圖像是指:含有蓄意或故意干擾像素來(lái)混淆或欺騙模型的圖像。

但與此同時(shí),這張圖像對(duì)于人類(lèi)來(lái)說(shuō)看上去是無(wú)害且無(wú)惡意的。

這些圖像導(dǎo)致深度神經(jīng)網(wǎng)絡(luò)故意做出錯(cuò)誤的預(yù)測(cè)。對(duì)抗圖像在某種方式上去干擾模型,導(dǎo)致它們無(wú)法做出正確的分類(lèi)。

事實(shí)上,人類(lèi)通過(guò)視覺(jué)可能無(wú)法區(qū)分正常圖片和對(duì)抗攻擊的圖片——本質(zhì)上,這兩張圖片對(duì)于肉眼來(lái)說(shuō)是相同的。

這或許不是一個(gè)準(zhǔn)確(或者說(shuō)正確)的類(lèi)比,但我喜歡在圖像密碼學(xué)的背景下來(lái)解釋對(duì)抗進(jìn)攻。利用密碼學(xué)算法,我們可以把數(shù)據(jù)(例如純文本信息)嵌入到圖像中,且不改變圖像本身的表象。這幅圖像可以純粹地傳送到接收者那里,然后接收者再去提取圖像中所隱藏的信息。

同樣的,對(duì)抗攻擊在輸入圖像中嵌入一條信息,但是這條信息并非是人們可以理解的純文本信息,因?yàn)閷?duì)抗攻擊所嵌入到輸入圖像的是一個(gè)噪聲向量。這個(gè)噪聲向量是用于戲弄或混淆深度學(xué)習(xí)模型而故意構(gòu)建的。

對(duì)抗攻擊是如何起作用的?我們應(yīng)該如何去進(jìn)行防御呢?

在這篇教程中,以及這個(gè)系列的其他推文中,我們將會(huì)準(zhǔn)確地去回答這些問(wèn)題。

想要了解如何用Keras/TensorFlow在對(duì)抗攻擊和圖像中來(lái)破壞深度學(xué)習(xí)模型,請(qǐng)繼續(xù)往下讀。

利用Keras和TensorFlow來(lái)實(shí)現(xiàn)對(duì)抗圖像和攻擊

在這篇教程中的第一部分,會(huì)討論下對(duì)抗攻擊是什么以及它們是如何影響深度學(xué)習(xí)模型的。

在那之后,我們會(huì)實(shí)現(xiàn)三段獨(dú)立的Python腳本:

1、第一段Python腳本是加載ImageNet數(shù)據(jù)集并解析類(lèi)別標(biāo)簽的使用助手。

2、第二段Python腳本是利用在ImageNet數(shù)據(jù)集上預(yù)訓(xùn)練好的ResNet模型來(lái)實(shí)現(xiàn)基本的圖像分類(lèi)(由此來(lái)演示“標(biāo)準(zhǔn)”的圖像分類(lèi))。

3、最后一段Python腳本用于執(zhí)行一次對(duì)抗攻擊,并且組成一張故意混淆我們的ResNet模型的對(duì)抗圖像,而這兩張圖像對(duì)于肉眼來(lái)說(shuō)看上去是一樣的。

讓我們開(kāi)始吧!

什么是對(duì)抗對(duì)象和對(duì)抗攻擊呢?它們是如何影響深度學(xué)習(xí)模型的呢?

3.png

圖二:當(dāng)執(zhí)行對(duì)抗攻擊時(shí),給予神經(jīng)網(wǎng)絡(luò)一張圖像(左),然后利用梯度下降來(lái)構(gòu)建一個(gè)噪聲向量(中)。這個(gè)噪聲向量被加入到輸入圖像中,生成一個(gè)誤分類(lèi)(右)。

在2014年,古德費(fèi)洛等人發(fā)表了一篇名為《Explaining and HarnessingAdversarial Examples(解釋并馴服對(duì)抗樣本)》的論文,展示了深度神經(jīng)網(wǎng)絡(luò)吸引人的屬性——有可能故意擾亂一張輸入圖像,導(dǎo)致神經(jīng)網(wǎng)絡(luò)對(duì)其進(jìn)行錯(cuò)誤的分類(lèi)。這種擾亂就被稱(chēng)為對(duì)抗攻擊。

經(jīng)典的對(duì)抗攻擊示例就像上面圖二所展示的一樣。在左邊,我們的輸入圖像在神經(jīng)網(wǎng)絡(luò)中被分在“熊貓”類(lèi)別,置信度為57.7%。

在中間有一個(gè)噪音向量,在人類(lèi)眼中看上去是隨機(jī)的,但事實(shí)上絕非如此。

恰恰相反,這一噪聲向量中的像素“等于輸入圖像的損失函數(shù)的梯度元素符號(hào)”(Goodfellow et al.)。

把這個(gè)噪聲向量嵌入到輸入圖像中,產(chǎn)出了圖二中的輸出(右)。對(duì)于我們來(lái)說(shuō),這副新圖像看起來(lái)與輸入圖像完全一樣,但我們的神經(jīng)網(wǎng)絡(luò)卻會(huì)將這站圖像分到“長(zhǎng)臂猿”類(lèi)別,置信度高達(dá)99.7%。很奇怪吧?

一段對(duì)抗攻擊和對(duì)抗圖像的簡(jiǎn)短歷史

2.png

圖三:一個(gè)關(guān)于對(duì)抗機(jī)器學(xué)習(xí)和深度神經(jīng)網(wǎng)絡(luò)安全性出版物的時(shí)間軸(圖片來(lái)源:CanMachine Learning Be Secure?圖8)

對(duì)抗機(jī)器學(xué)習(xí)并不是一個(gè)新興領(lǐng)域,這些攻擊也不是針對(duì)深度神經(jīng)網(wǎng)絡(luò)。在2006年,巴雷諾等人發(fā)表了一篇名為《CanMachine Learning Be Secure?》的論文。論文討論了對(duì)抗攻擊,包括提出了一些對(duì)抗攻擊的防御方式。

回到2006年,最先進(jìn)的機(jī)器學(xué)習(xí)模型包括支持向量機(jī)(SVMs)和隨機(jī)森林(RFs),這兩種類(lèi)型的模型均易受對(duì)抗攻擊的影響。

隨著2012年深度神經(jīng)網(wǎng)絡(luò)的普及度開(kāi)始升高,曾寄希望于這些非線性的模型不會(huì)輕易受到這種攻擊的影響,然而古德費(fèi)洛等人打破了這一幻想。

他們發(fā)現(xiàn)深度神經(jīng)網(wǎng)絡(luò)和“前輩們”一樣,都很容易受到對(duì)抗攻擊的影響。

想要了解更多關(guān)于對(duì)抗攻擊的歷史,我建議你們?nèi)タ聪卤雀駣W(Biggio)和羅利(Roli)在2017年發(fā)表的論文《Wild Patterns: Ten Years Afterthe Rise of Adversarial Machine Learning.》

為什么對(duì)抗攻擊和對(duì)抗圖像會(huì)成為一個(gè)麻煩呢?

1.png

圖四:為什么對(duì)抗攻擊會(huì)是一種麻煩?為什么我們應(yīng)該關(guān)注它?(圖片來(lái)源imagesource)

本篇教程頂部所談到的示例中概述了為什么對(duì)抗攻擊會(huì)給我們的健康、生活和財(cái)產(chǎn)帶來(lái)嚴(yán)重?fù)p失。

另外一些后果沒(méi)有那么嚴(yán)重的示例,例如一群黑客識(shí)別了一個(gè)谷歌用于給Gmail過(guò)濾垃圾郵件的模型,或者識(shí)別了一個(gè)Facebook自動(dòng)檢測(cè)****內(nèi)容的NSFW(不適合上班時(shí)間瀏覽)過(guò)濾器模型。

如果這些黑客想要繞過(guò)Gmail垃圾郵件過(guò)濾器來(lái)讓用戶(hù)受到資源過(guò)載攻擊,或者繞過(guò)Facebook的NSFW過(guò)濾器來(lái)上傳大量的****內(nèi)容,理論上講他們是可以做到的。

這些都是對(duì)抗攻擊中造成輕微后果的示例。

關(guān)于到對(duì)抗攻擊帶有嚴(yán)重后果的劇本可以包括黑客恐怖分子識(shí)別了全世界自動(dòng)駕駛汽車(chē)所使用的深度神經(jīng)網(wǎng)絡(luò)(試想一下如果特斯拉壟斷了市場(chǎng),成為世界唯一自動(dòng)駕駛汽車(chē)生產(chǎn)商)。

對(duì)抗圖片有可能被有戰(zhàn)略性地?cái)[放在車(chē)道或公路上,造成連環(huán)車(chē)禍、財(cái)產(chǎn)損失或車(chē)內(nèi)乘客的受傷甚至死亡。

只有你的想象力,對(duì)已知模型的了解程度以及對(duì)模型的使用程度是對(duì)抗攻擊的天花板。

我們能夠抵御對(duì)抗攻擊嗎?

好消息是我們可以降低對(duì)抗攻擊所造成的影響(但無(wú)法將它們完全消除)。

這方面的話題將不會(huì)在今天的教程中展開(kāi),可能會(huì)在未來(lái)的教程中進(jìn)行討論。

配置你的開(kāi)發(fā)環(huán)境

在這篇教程中配置你的系統(tǒng),我建議你跟隨這兩篇教程:

如何在Ubuntu系統(tǒng)下配置TensorFlow2.0 ?(How to installTensorFlow 2.0 on Ubuntu)

如何在macOS系統(tǒng)下配置TensorFlow2.0 ?How to install TensorFlow 2.0 on macOS

這兩篇教程都會(huì)協(xié)助你在便捷的Python虛擬環(huán)境中利用必要的軟件來(lái)配置系統(tǒng)。

項(xiàng)目結(jié)構(gòu):

$ tree --dirsfirst

.

├── pyimagesearch

│ ├── __init__.py

│ ├── imagenet_class_index.json

│ └── utils.py

├── adversarial.png

├── generate_basic_adversary.py

├── pig.jpg

└── predict_normal.py

1 directory, 7 files

在pyimagesearch模塊中,有兩個(gè)文件:

1、imagenet_class_index.json: 一個(gè)JSON文件,將ImageNet類(lèi)別標(biāo)簽標(biāo)記為可讀的字符串。我們將會(huì)利用這個(gè)JSON文件來(lái)決定這樣一組特殊標(biāo)簽的整數(shù)值索引,在構(gòu)建對(duì)抗圖像攻擊時(shí),這個(gè)索引將會(huì)給予我們幫助。

2、utils.py: 包含簡(jiǎn)單的Python輔助函數(shù),用于載入和解析imagenet_class_index.json

這里面還有兩個(gè)我們今天需要檢驗(yàn)的Python腳本:

1、predict_normal.py: 接收一張輸入圖像(pig.jpg),載入ResNet50模型,對(duì)輸入圖像進(jìn)行分類(lèi)。這個(gè)腳本的輸出會(huì)是預(yù)測(cè)類(lèi)別標(biāo)簽在ImageNet的類(lèi)別標(biāo)簽索引。

2、generate_basic_adversary.py:利用predict_normal.py腳本中的輸出,我們將構(gòu)建一次對(duì)抗攻擊來(lái)欺騙ResNet,這個(gè)腳本的輸出(adversarial.png)將會(huì)存儲(chǔ)在硬盤(pán)中。

做好準(zhǔn)備來(lái)實(shí)現(xiàn)你的第一個(gè)Keras和TensorFlow中的對(duì)抗攻擊了嗎?讓我們開(kāi)始吧。

ImageNet 類(lèi)別標(biāo)簽/索引幫助實(shí)用程序

在我們開(kāi)始執(zhí)行正常的圖像分類(lèi)或者對(duì)抗攻擊使用的混淆圖像分類(lèi)之前,首先需要?jiǎng)?chuàng)建一個(gè)Python輔助函數(shù)來(lái)載入和解析ImageNet數(shù)據(jù)集的類(lèi)別標(biāo)簽。

我們提供了一個(gè)JSON文件包含所有的類(lèi)別標(biāo)簽索引、標(biāo)識(shí)符和可讀的字符串,全都包含在項(xiàng)目目錄結(jié)構(gòu)中pyimagesearch模塊的imagenet_class_index.json文件里。

在這里展示JSON文件的前幾行:

{

"0": [

"n01440764",

"tench"

],

"1": [

"n01443537",

"goldfish"

],

"2": [

"n01484850",

"great_white_shark"

],

"3": [

"n01491361",

"tiger_shark"

],

...

"106": [

"n01883070",

"wombat"

],

...

在這里可以看到這個(gè)文件是一個(gè)字典格式的。字典的關(guān)鍵字是類(lèi)別標(biāo)簽的整數(shù)值索引,而值由二元元組組成:

1、ImageNet標(biāo)簽的唯一標(biāo)識(shí)符;

2、有可讀性的類(lèi)別標(biāo)簽。

我們的目標(biāo)是實(shí)現(xiàn)一個(gè)Python函數(shù)可以解析JSON文件:

接收一個(gè)輸入標(biāo)簽;

轉(zhuǎn)化成其對(duì)應(yīng)標(biāo)簽的類(lèi)別標(biāo)簽整數(shù)值索引。

實(shí)際上,我們就是轉(zhuǎn)換imagenet_class_index.json文件中的鍵與值(key/value)的關(guān)系。

讓我們來(lái)實(shí)現(xiàn)這個(gè)輔助函數(shù)吧。

打開(kāi)pyimagesearch模塊的utils.py文件,插入下列代碼:

# importnecessary packages

import json

import os

defget_class_idx(label):

# build the path to theImageNet class label mappings file

labelPath = os.path.join(os.path.dirname(__file__),

"imagenet_class_index.json")

第2行和第3行引入我們所需要的Python包。我們要用到j(luò)son Python模塊來(lái)載入JSON文件,而os包用于構(gòu)建文件路徑,這與你使用的是什么操作系統(tǒng)并無(wú)關(guān)系。

接下來(lái)我們?nèi)ザxget_class_idx輔助函數(shù)。這個(gè)函數(shù)的目標(biāo)是接收一個(gè)輸入類(lèi)別標(biāo)簽,然后獲得預(yù)測(cè)(即在ImageNet上所訓(xùn)練出的模型在1000個(gè)標(biāo)簽類(lèi)別中做出的預(yù)測(cè))的標(biāo)簽類(lèi)別的整數(shù)值索引。

第7行是組成能夠載入 pyimagesearch模塊中的imagenet_class_index.json的路徑。

現(xiàn)在載入JSON文件中的內(nèi)容:

# open theImageNet class mappings file and load the mappings as

# a dictionary with the human-readable class label as the keyand

# the integerindex as the value

withopen(labelPath)as f:

imageNetClasses = {labels[1]: int(idx)for(idx, labels)in

json.load(f).items()}

# check to see if the inputclass label has a corresponding

# integer index value, and if so return it; otherwise return

# a None-type value

return imageNetClasses.get(label, None)

第4-6行,打開(kāi)labelPath文件,然后將鍵值對(duì)的關(guān)系進(jìn)行轉(zhuǎn)換,這樣鍵才是可讀的標(biāo)簽字符串,而值是那個(gè)標(biāo)簽的整數(shù)值索引。

為了獲得輸入標(biāo)簽的整數(shù)值索引,可以調(diào)用imageNetClasses字典中的.get方法(最后一行),會(huì)返回:

·  如果在字典中存在改標(biāo)簽的話,則返回該標(biāo)簽的整數(shù)值索引;

·  否則返回None。

這個(gè)值返回到調(diào)用函數(shù)。

讓我們?cè)谙乱徽鹿?jié)來(lái)構(gòu)建get_class_idx輔助函數(shù)。

利用Keras和TensorFlow在沒(méi)有對(duì)抗攻擊的情況下進(jìn)行圖片分類(lèi)

在實(shí)現(xiàn)了ImageNet 類(lèi)標(biāo)簽/索引輔助函數(shù)后,讓我們構(gòu)造一個(gè)圖像分類(lèi)腳本,在沒(méi)有對(duì)抗攻擊的情況下實(shí)現(xiàn)基本分類(lèi)的圖像分類(lèi)腳本。

這個(gè)腳本可以證明我們的ResNet模型表現(xiàn)正常(做出正確地預(yù)測(cè))。在這篇教程的后半部分,你們將會(huì)發(fā)現(xiàn)如何構(gòu)建一張對(duì)抗圖像用于混淆ResNet。

讓我們開(kāi)始基本的圖像分類(lèi)腳本——在你的工程文件結(jié)構(gòu)中打開(kāi)predict_normal.py文件,并插入以下代碼:

# import necessarypackages

from pyimagesearch.utils import get_class_idx

from tensorflow.keras.applications import ResNet50

from tensorflow.keras.applications.resnet50 import decode_predictions

from tensorflow.keras.applications.resnet50 import preprocess_input

import numpy as np

import argparse

import imutils

import cv2

在第2-9行,我們引入了所需的Python包。如果你之前使用過(guò)Keras,TensorFlow和OpenCV的話,這些對(duì)你來(lái)說(shuō)都是常規(guī)操作。

如果你是Keras和TensorFlow的新手,我強(qiáng)烈建議你去看一下我的這篇《KerasTutorial: How to get started with Keras, Deep Learning, and Python》教程。另外,你或許想要讀一讀我的書(shū)《DeepLearning for Computer Vision with Python》加深你對(duì)訓(xùn)練自定義神經(jīng)網(wǎng)絡(luò)的理解。

在第2行,我們引入了在上一章節(jié)中定義的get_class_idx函數(shù),這個(gè)函數(shù)可以獲得ResNet50模型中最高預(yù)測(cè)標(biāo)簽的整數(shù)索引值。

讓我們定義下 preprocess_image輔助函數(shù):

defpreprocess_image(image):

# swap color channels,preprocess the image, and add in a batch

# dimension

image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)

image = preprocess_input(image)

image = cv2.resize(image, (224, 224))

image = np.expand_dims(image, axis=0)

# return the preprocessed image

return image

preprocess_image 方法接收一個(gè)單一的必需參數(shù),那就是我們想要預(yù)處理的圖片。

對(duì)這張圖片進(jìn)行預(yù)處理有以下幾步:

1、將圖片的BGR通道組合轉(zhuǎn)化為RGB;

2、執(zhí)行preprocess_input函數(shù),用于完成ResNet50中特別的預(yù)處理和比例縮放過(guò)程;

3、將圖片大小調(diào)整為224×224;

4、增加一個(gè)批次維度。

這張預(yù)處理好的圖像會(huì)被返回到調(diào)用函數(shù)中。

*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。



關(guān)鍵詞:

相關(guān)推薦

技術(shù)專(zhuān)區(qū)

關(guān)閉