<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          對(duì)抗圖像和攻擊在Keras和TensorFlow上的實(shí)現(xiàn)

          共 19802字,需瀏覽 40分鐘

           ·

          2021-04-02 10:20

          點(diǎn)擊上方小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂

          重磅干貨,第一時(shí)間送達(dá)

          本文轉(zhuǎn)自:計(jì)算機(jī)視覺聯(lián)盟

          AI博士筆記系列推薦
          周志華《機(jī)器學(xué)習(xí)》手推筆記正式開源!可打印版本附pdf下載鏈接
          [ 摘要 ]在這篇教程中,你將會(huì)學(xué)到如何用基于圖像的對(duì)抗攻擊來破壞深度學(xué)習(xí)模型。我們將會(huì)利用Keras和TensorFlow深度學(xué)習(xí)庫(kù)來實(shí)現(xiàn)自己的對(duì)抗攻擊。

                        
          試想下從現(xiàn)在起的二十年后?,F(xiàn)在路上所有的車輛都是利用人工智能、深度學(xué)習(xí)和計(jì)算機(jī)視覺來驅(qū)動(dòng)的無人駕駛交通工具。每一次轉(zhuǎn)彎、車道轉(zhuǎn)換、加速和剎車都是由深度神經(jīng)網(wǎng)絡(luò)來提供技術(shù)支持?,F(xiàn)在,想象自己在高速路上,你正坐在“駕駛室(當(dāng)車自主行駛時(shí),駕駛室還能被稱為‘駕駛室’嗎?)”里,你的妻子坐在副駕上,你的孩子們坐在后座。
           
          朝前看,你看到一張巨大的貼紙正在車輛所行駛的車道上,這看上去對(duì)車的前進(jìn)毫無影響??瓷先ミ@像是一張受歡迎的大幅涂鴉藝術(shù)版畫,可能是幾個(gè)高中生開玩笑把它放在這里,或者他們只是為了完成某個(gè)大冒險(xiǎn)游戲。

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


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

          發(fā)生了什么?為什么你的自動(dòng)駕駛車輛會(huì)做出這樣的反應(yīng)?是不是車內(nèi)的某段代碼或者某個(gè)軟件存在奇怪的“bug”?
           
          答案就是,為車輛視覺組件提供技術(shù)支持的深度神經(jīng)網(wǎng)絡(luò)看到了一張對(duì)抗圖像。
           
          對(duì)抗圖像是指:含有蓄意或故意干擾像素來混淆或欺騙模型的圖像。
           
          但與此同時(shí),這張圖像對(duì)于人類來說看上去是無害且無惡意的。
           
          這些圖像導(dǎo)致深度神經(jīng)網(wǎng)絡(luò)故意做出錯(cuò)誤的預(yù)測(cè)。對(duì)抗圖像在某種方式上去干擾模型,導(dǎo)致它們無法做出正確的分類。
           
          事實(shí)上,人類通過視覺可能無法區(qū)分正常圖片和對(duì)抗攻擊的圖片——本質(zhì)上,這兩張圖片對(duì)于肉眼來說是相同的。
           
          這或許不是一個(gè)準(zhǔn)確(或者說正確)的類比,但我喜歡在圖像密碼學(xué)的背景下來解釋對(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)確地去回答這些問題。
           
          想要了解如何用Keras/TensorFlow在對(duì)抗攻擊和圖像中來破壞深度學(xué)習(xí)模型,請(qǐng)繼續(xù)往下讀。

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


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

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

          1. 第一段Python腳本是加載ImageNet數(shù)據(jù)集并解析類別標(biāo)簽的使用助手。
          2. 第二段Python腳本是利用在ImageNet數(shù)據(jù)集上預(yù)訓(xùn)練好的ResNet模型來實(shí)現(xiàn)基本的圖像分類(由此來演示“標(biāo)準(zhǔn)”的圖像分類)。
          3. 最后一段Python腳本用于執(zhí)行一次對(duì)抗攻擊,并且組成一張故意混淆我們的ResNet模型的對(duì)抗圖像,而這兩張圖像對(duì)于肉眼來說看上去是一樣的。

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

          圖二:當(dāng)執(zhí)行對(duì)抗攻擊時(shí),給予神經(jīng)網(wǎng)絡(luò)一張圖像(左),然后利用梯度下降來構(gòu)建一個(gè)噪聲向量(中)。這個(gè)噪聲向量被加入到輸入圖像中,生成一個(gè)誤分類(右)。
           
          在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ò)誤的分類。這種擾亂就被稱為對(duì)抗攻擊。
           
          經(jīng)典的對(duì)抗攻擊示例就像上面圖二所展示的一樣。在左邊,我們的輸入圖像在神經(jīng)網(wǎng)絡(luò)中被分在“熊貓”類別,置信度為57.7%。
           
          在中間有一個(gè)噪音向量,在人類眼中看上去是隨機(jī)的,但事實(shí)上絕非如此。
           
          恰恰相反,這一噪聲向量中的像素“等于輸入圖像的損失函數(shù)的梯度元素符號(hào)”(Goodfellow et al.)。
           
          把這個(gè)噪聲向量嵌入到輸入圖像中,產(chǎn)出了圖二中的輸出(右)。對(duì)于我們來說,這副新圖像看起來與輸入圖像完全一樣,但我們的神經(jīng)網(wǎng)絡(luò)卻會(huì)將這站圖像分到“長(zhǎng)臂猿”類別,置信度高達(dá)99.7%。很奇怪吧!



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

          圖三:一個(gè)關(guān)于對(duì)抗機(jī)器學(xué)習(xí)和深度神經(jīng)網(wǎng)絡(luò)安全性出版物的時(shí)間軸(圖片來源: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),這兩種類型的模型均易受對(duì)抗攻擊的影響。
           
          隨著2012年深度神經(jīng)網(wǎng)絡(luò)的普及度開始升高,曾寄希望于這些非線性的模型不會(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è)麻煩呢?


          圖四:為什么對(duì)抗攻擊會(huì)是一種麻煩?為什么我們應(yīng)該關(guān)注它?(圖片來源imagesource)
           
          本篇教程頂部所談到的示例中概述了為什么對(duì)抗攻擊會(huì)給我們的健康、生活和財(cái)產(chǎn)帶來嚴(yán)重?fù)p失。
           
          另外一些后果沒有那么嚴(yán)重的示例,例如一群黑客識(shí)別了一個(gè)谷歌用于給Gmail過濾垃圾郵件的模型,或者識(shí)別了一個(gè)Facebook自動(dòng)檢測(cè)色情內(nèi)容的NSFW(不適合上班時(shí)間瀏覽)過濾器模型。
           
          如果這些黑客想要繞過Gmail垃圾郵件過濾器來讓用戶受到資源過載攻擊,或者繞過Facebook的NSFW過濾器來上傳大量的色情內(nèi)容,理論上講他們是可以做到的。
           
          這些都是對(duì)抗攻擊中造成輕微后果的示例。
           
          關(guān)于到對(duì)抗攻擊帶有嚴(yán)重后果的劇本可以包括黑客恐怖分子識(shí)別了全世界自動(dòng)駕駛汽車所使用的深度神經(jīng)網(wǎng)絡(luò)(試想一下如果特斯拉壟斷了市場(chǎng),成為世界唯一自動(dòng)駕駛汽車生產(chǎn)商)。
           
          對(duì)抗圖片有可能被有戰(zhàn)略性地?cái)[放在車道或公路上,造成連環(huán)車禍、財(cái)產(chǎn)損失或車內(nèi)乘客的受傷甚至死亡。
           
          只有你的想象力,對(duì)已知模型的了解程度以及對(duì)模型的使用程度是對(duì)抗攻擊的天花板。 

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

          好消息是我們可以降低對(duì)抗攻擊所造成的影響(但無法將它們完全消除)。
           
          這方面的話題將不會(huì)在今天的教程中展開,可能會(huì)在未來的教程中進(jìn)行討論。

          配置你的開發(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)境中利用必要的軟件來配置系統(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.py1 directory, 7 files
           
          在pyimagesearch模塊中,有兩個(gè)文件:

          1. imagenet_class_index.json: 一個(gè)JSON文件,將ImageNet類別標(biāo)簽標(biāo)記為可讀的字符串。我們將會(huì)利用這個(gè)JSON文件來決定這樣一組特殊標(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)行分類。這個(gè)腳本的輸出會(huì)是預(yù)測(cè)類別標(biāo)簽在ImageNet的類別標(biāo)簽索引。
          2. generate_basic_adversary.py:利用predict_normal.py腳本中的輸出,我們將構(gòu)建一次對(duì)抗攻擊來欺騙ResNet,這個(gè)腳本的輸出(adversarial.png)將會(huì)存儲(chǔ)在硬盤中。
           
          做好準(zhǔn)備來實(shí)現(xiàn)你的第一個(gè)Keras和TensorFlow中的對(duì)抗攻擊了嗎?讓我們開始吧。

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


          在我們開始執(zhí)行正常的圖像分類或者對(duì)抗攻擊使用的混淆圖像分類之前,首先需要?jiǎng)?chuàng)建一個(gè)Python輔助函數(shù)來載入和解析ImageNet數(shù)據(jù)集的類別標(biāo)簽。
           
          我們提供了一個(gè)JSON文件包含所有的類別標(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)鍵字是類別標(biāo)簽的整數(shù)值索引,而值由二元元組組成:

          1. ImageNet標(biāo)簽的唯一標(biāo)識(shí)符;
          2. 有可讀性的類別標(biāo)簽。
           
          我們的目標(biāo)是實(shí)現(xiàn)一個(gè)Python函數(shù)可以解析JSON文件:

          1. 接收一個(gè)輸入標(biāo)簽;
          2. 轉(zhuǎn)化成其對(duì)應(yīng)標(biāo)簽的類別標(biāo)簽整數(shù)值索引。
           
          實(shí)際上,我們就是轉(zhuǎn)換imagenet_class_index.json文件中的鍵與值(key/value)的關(guān)系。
           
          讓我們來實(shí)現(xiàn)這個(gè)輔助函數(shù)吧。
           
          打開pyimagesearch模塊的utils.py文件,插入下列代碼:

          # importnecessary packagesimport jsonimport osdefget_class_idx(label):# build the path to theImageNet class label mappings filelabelPath = os.path.join(os.path.dirname(__file__),"imagenet_class_index.json")
           
          第2行和第3行引入我們所需要的Python包。我們要用到j(luò)son Python模塊來載入JSON文件,而os包用于構(gòu)建文件路徑,這與你使用的是什么操作系統(tǒng)并無關(guān)系。
           
          接下來我們?nèi)ザxget_class_idx輔助函數(shù)。這個(gè)函數(shù)的目標(biāo)是接收一個(gè)輸入類別標(biāo)簽,然后獲得預(yù)測(cè)(即在ImageNet上所訓(xùn)練出的模型在1000個(gè)標(biāo)簽類別中做出的預(yù)測(cè))的標(biāo)簽類別的整數(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 valuewithopen(labelPath)as f:imageNetClasses = {labels[1]: int(idx)for(idx, labels)injson.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 valuereturn imageNetClasses.get(label, None)
           
          第4-6行,打開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é)來構(gòu)建get_class_idx輔助函數(shù)。
           

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

          在實(shí)現(xiàn)了ImageNet 類標(biāo)簽/索引輔助函數(shù)后,讓我們構(gòu)造一個(gè)圖像分類腳本,在沒有對(duì)抗攻擊的情況下實(shí)現(xiàn)基本分類的圖像分類腳本。
           
          這個(gè)腳本可以證明我們的ResNet模型表現(xiàn)正常(做出正確地預(yù)測(cè))。在這篇教程的后半部分,你們將會(huì)發(fā)現(xiàn)如何構(gòu)建一張對(duì)抗圖像用于混淆ResNet。
           
          讓我們開始基本的圖像分類腳本——在你的工程文件結(jié)構(gòu)中打開predict_normal.py文件,并插入以下代碼:

          # import necessarypackagesfrom pyimagesearch.utils import get_class_idxfrom tensorflow.keras.applications import ResNet50from tensorflow.keras.applications.resnet50 import decode_predictionsfrom tensorflow.keras.applications.resnet50 import preprocess_inputimport numpy as npimport argparseimport imutilsimport cv2
           
          在第2-9行,我們引入了所需的Python包。如果你之前使用過Keras,TensorFlow和OpenCV的話,這些對(duì)你來說都是常規(guī)操作。
           
          如果你是Keras和TensorFlow的新手,我強(qiáng)烈建議你去看一下我的這篇《KerasTutorial: How to get started with Keras, Deep Learning, and Python》教程。另外,你或許想要讀一讀我的書《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# dimensionimage = 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 imagereturn image
           
          preprocess_image 方法接收一個(gè)單一的必需參數(shù),那就是我們想要預(yù)處理的圖片。
           
          對(duì)這張圖片進(jìn)行預(yù)處理有以下幾步:

          1. 將圖片的BGR通道組合轉(zhuǎn)化為RGB;
          2. 執(zhí)行preprocess_input函數(shù),用于完成ResNet50中特別的預(yù)處理和比例縮放過程;
          3. 將圖片大小調(diào)整為224×224;
          4. 增加一個(gè)批次維度。
           
          這張預(yù)處理好的圖像會(huì)被返回到調(diào)用函數(shù)中。
           
          接下來,讓我們解析下指令參數(shù):

          # construct the argument parser and parsethe argumentsap = argparse.ArgumentParser()ap.add_argument("-i", "--image",required=True,help="pathto input image")args = vars(ap.parse_args())
           
          我們?cè)谶@里只需要一個(gè)命令行參數(shù),--image,即輸入圖像存放在硬盤上的路徑。
           
          如果你從來沒有處理過命令行參數(shù)和argparse ,我建議你看一下這篇教程。
           
          接下來讓載入輸入圖像并進(jìn)行預(yù)處理:

          # load image fromdisk and make a clone for annotationprint("[INFO] loadingimage...")image = cv2.imread(args["image"])output = image.copy()# preprocess the input imageoutput = imutils.resize(output, width=400)preprocessedImage = preprocess_image(image)
           
          通過調(diào)用cv2.imread來載入輸入圖片。在第4行對(duì)這張圖片進(jìn)行了復(fù)制,以便后期在輸出結(jié)果上面畫框并標(biāo)注上預(yù)測(cè)結(jié)果類別標(biāo)簽。
           
          我們調(diào)整下輸出圖片的尺寸,讓它的寬變?yōu)?00像素,這樣可以適配我們的電腦屏幕。在這里同樣使用preprocess_image函數(shù)將其處理為可用于ResNet進(jìn)行分類的輸入圖片。
           
          加上我們預(yù)處理好的圖片,接著載入ResNet并對(duì)圖片進(jìn)行分類:

          # load thepre-trained ResNet50 modelprint("[INFO] loadingpre-trained ResNet50 model...")model = ResNet50(weights="imagenet")# makepredictions on the input image and parse the top-3 predictionsprint("[INFO] makingpredictions...")predictions =model.predict(preprocessedImage)predictions = decode_predictions(predictions, top=3)[0]
           
          第3行,載入ResNet和該模型用ImageNet數(shù)據(jù)集預(yù)訓(xùn)練好的權(quán)重。
           
          第6和7行,針對(duì)預(yù)處理好的圖片進(jìn)行預(yù)測(cè),然后再用 Keras/TensorFlow 中的decode_predictions輔助函數(shù)對(duì)圖片進(jìn)行解碼。
           
          現(xiàn)在讓我們看看神經(jīng)網(wǎng)絡(luò)預(yù)測(cè)的Top 3 (置信度前三)類別以及所展示的類別標(biāo)簽:

          # loop over thetop three predictionsfor(i, (imagenetID, label,prob))inenumerate(predictions):# print the ImageNet class label ID of the top prediction to our# terminal (we'll need thislabel for our next script which will# perform the actual adversarial attack)if i == 0:print("[INFO] {} => {}".format(label, get_class_idx(label)))# display the prediction to our screenprint("[INFO] {}.{}: {:.2f}%".format(i + 1, label, prob * 100))
           
          第2行開始循環(huán)Top-3預(yù)測(cè)結(jié)果。
           
          如果這是第一個(gè)預(yù)測(cè)結(jié)果(即Top-1預(yù)測(cè)結(jié)果),在輸出終端顯示可讀的標(biāo)簽,然后利用 get_class_idx函數(shù)找出該標(biāo)簽對(duì)應(yīng)的ImageNet的整數(shù)值索引。
           
          還可以在終端上展示Top-3的標(biāo)簽和對(duì)應(yīng)的概率值。
           
          最終一步就是將Top-1預(yù)測(cè)結(jié)果標(biāo)注在輸出圖片中:

          # draw thetop-most predicted label on the image along with the# confidence scoretext = "{}:{:.2f}%".format(predictions[0][1],predictions[0][2] * 100)cv2.putText(output, text, (3, 20),cv2.FONT_HERSHEY_SIMPLEX, 0.8,(0, 255, 0), 2)# show the output imagecv2.imshow("Output", output)cv2.waitKey(0)
           
          輸出圖像在終端顯示,如果你單擊OpenCV窗口或按下任意鍵,輸出圖像將會(huì)關(guān)閉。
           
          非對(duì)抗圖像的分類結(jié)果

          現(xiàn)在可以用ResNet來執(zhí)行基本的圖像分類(非對(duì)抗攻擊)了。
           
          首先在“下載“頁(yè)獲取源代碼和圖像范例。
           
          從這開始,打開一個(gè)終端并執(zhí)行以下命令:

          $ pythonpredict_normal.py --image pig.jpg[INFO] loading image...[INFO] loadingpre-trained ResNet50 model...[INFO] making predictions...[INFO] hog => 341[INFO] 1. hog: 99.97%[INFO] 2.wild_boar: 0.03%[INFO] 3. piggy_bank: 0.00%

          圖五:預(yù)訓(xùn)練好的ResNet模型可以正確地將這張圖片分類為“豬(hog)”。
           
          在這里你可以看到我們將一張豬的圖片進(jìn)行了分類,置信度為99.97%。
           
          另外,這里還加上了hog標(biāo)簽的ID(341)。我們將會(huì)在下一章用到這個(gè)標(biāo)簽ID,我們會(huì)針對(duì)這張豬的輸入圖片進(jìn)行一次對(duì)抗攻擊。

          在Keras和TensorFlow上實(shí)現(xiàn)對(duì)抗圖像和對(duì)抗攻擊


          接下來就要學(xué)習(xí)如何在Keras和TensorFlow上實(shí)現(xiàn)對(duì)抗圖像和對(duì)抗攻擊。
           
          打開generate_basic_adversary.py文件,插入以下代碼:

          # import necessary packagesfrom tensorflow.keras.optimizers import Adamfrom tensorflow.keras.applications import ResNet50from tensorflow.keras.losses importSparseCategoricalCrossentropyfrom tensorflow.keras.applications.resnet50 import decode_predictionsfrom tensorflow.keras.applications.resnet50 import preprocess_inputimport tensorflow as tfimport numpy as npimport argparseimport cv2
           
          在第2-10行中引入我們所需的Python包。你會(huì)注意到我們?cè)俅斡玫搅薘esNet50 架構(gòu),以及對(duì)應(yīng)的preprocess_input函數(shù)(用于預(yù)處理/縮放輸入圖像)和 decode_predictions用于解碼預(yù)測(cè)輸出和顯示可讀的ImageNet標(biāo)簽。
           
          SparseCategoricalCrossentropy 用于計(jì)算標(biāo)簽和預(yù)測(cè)值之間的分類交叉熵?fù)p失。利用稀疏版本的分類交叉熵,我們不需要像使用scikit-learn的LabelBinarizer或者Keras/TensorFlow的to_categorical功能一樣用one-hot對(duì)類標(biāo)簽編碼。
           
          例如在predict_normal.py腳本中有preprocess_image 功能,我們?cè)谶@個(gè)腳本上同樣需要:

          defpreprocess_image(image):# swap color channels, resizethe input image, and add a batch# dimensionimage = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)image = cv2.resize(image, (224, 224))image = np.expand_dims(image, axis=0)# return the preprocessedimagereturn image
           
          除了省略了調(diào)用preprocess_input函數(shù),這一段代碼與上一段代碼相同,當(dāng)我們開始創(chuàng)建對(duì)抗圖像時(shí),你們馬上就會(huì)明白為什么省去調(diào)用這一函數(shù)。
           
          接下來,我們有一個(gè)簡(jiǎn)單的輔助程序,clip_eps:

          defclip_eps(tensor, eps):# clip the values of thetensor to a given range and return itreturn tf.clip_by_value(tensor,clip_value_min=-eps,clip_value_max=eps)
           
          這個(gè)函數(shù)的目的就是接受一個(gè)輸入張量tensor,然后在范圍值 [-eps, eps]內(nèi)對(duì)輸入進(jìn)行截取。
           
          被截取后的tensor會(huì)被返回到調(diào)用函數(shù)。
           
          接下來看看generate_adversaries 函數(shù),這是對(duì)抗攻擊的靈魂:

          defgenerate_adversaries(model, baseImage,delta, classIdx, steps=50):# iterate over the number ofstepsfor step inrange(0, steps):# record our gradientswith tf.GradientTape()as tape:# explicitly indicate thatour perturbation vector should# be tracked for gradient updatestape.watch(delta)
           
          generate_adversaries 方法是整個(gè)腳本的核心。這個(gè)函數(shù)接收四個(gè)必需的參數(shù),以及第五個(gè)可選參數(shù):

          1. model:ResNet50模型(如果你愿意,你可以換成其他預(yù)訓(xùn)練好的模型,例如VGG16,MobileNet等等);
          2. baseImage:原本沒有被干擾的輸入圖像,我們有意針對(duì)這張圖像創(chuàng)建對(duì)抗攻擊,導(dǎo)致model參數(shù)對(duì)它進(jìn)行錯(cuò)誤的分類。
          3. delta:噪聲向量,將會(huì)被加入到baseImage中,最終導(dǎo)致錯(cuò)誤分類。我們將會(huì)用梯度下降均值來更新這個(gè)delta 向量。
          4. classIdx:通過predict_normal.py腳本所獲得的類別標(biāo)簽整數(shù)值索引。
          5. steps:梯度下降執(zhí)行的步數(shù)(默認(rèn)為50步)。
           
          第3行開始循環(huán)設(shè)定好的步數(shù)。
           
          接下來用GradientTape來記錄梯度。在tape上調(diào)用 .watch方法指出擾動(dòng)向量是可以用來追蹤更新的。
           
          現(xiàn)在可以建造對(duì)抗圖像了:

          # add our perturbation vector to the base image and# preprocess the resulting imageadversary = preprocess_input(baseImage + delta)# run this newly constructed image tensor through our# model and calculate theloss with respect to the# *original* class indexpredictions = model(adversary,training=False)loss = -sccLoss(tf.convert_to_tensor([classIdx]),predictions)# check to see if we arelogging the loss value, and if# so, display it to our terminalif step % 5 == 0:print("step: {},loss: {}...".format(step,loss.numpy()))# calculate the gradients ofloss with respect to the# perturbation vectorgradients = tape.gradient(loss, delta)# update the weights, clipthe perturbation vector, and# update its valueoptimizer.apply_gradients([(gradients, delta)])delta.assign_add(clip_eps(delta, eps=EPS))# return the perturbationvectorreturn delta
           
          第3行將delta擾動(dòng)向量加入至baseImage的方式來組建對(duì)抗圖片,所得到的結(jié)果將放入ResNet50的preprocess_input函數(shù)中來進(jìn)行比例縮放和結(jié)果對(duì)抗圖像進(jìn)行歸一化。
           
          接下來幾行的意義是:

          • 第7行用model參數(shù)導(dǎo)入的模型對(duì)新創(chuàng)建的對(duì)抗圖像進(jìn)行預(yù)測(cè)。
          • 第8和9行針對(duì)原有的classIdx(通過運(yùn)行predict_normal.py得到的top-1 ImageNet類別標(biāo)簽整數(shù)值索引)計(jì)算損失。
          • 第12-14行表示每5步就顯示一次損失值。
           
          第17行,在with聲明外根據(jù)擾動(dòng)向量計(jì)算梯度損失。
           
          接著,可以更新delta向量,截取掉超出 [-EPS,EPS] 范圍外的值。
           
          最終,把得到的擾動(dòng)向量返回至調(diào)用函數(shù)——即最終的delta值,該值能讓我們建立用來欺騙模型的對(duì)抗攻擊。
           
          在對(duì)抗腳本的核心實(shí)現(xiàn)后,接下來就是解析命令行參數(shù):

          # construct the argumentparser and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", "--input", required=True,help="path tooriginal input image")ap.add_argument("-o", "--output", required=True,help="path tooutput adversarial image")ap.add_argument("-c", "--class-idx", type=int,required=True,help="ImageNetclass ID of the predicted label")args = vars(ap.parse_args())
           
          我們的對(duì)抗攻擊Python腳本需要三個(gè)指令行參數(shù):

          1. --input: 輸入圖像的磁盤路徑(例如pig.jpg);
          2. --output: 在構(gòu)建進(jìn)攻后的對(duì)抗圖像輸出(例如adversarial.png);
          3. --class-idex:ImageNet數(shù)據(jù)集中的類別標(biāo)簽整數(shù)值索引。我們可以通過執(zhí)行在“非對(duì)抗圖像的分類結(jié)果”章節(jié)中提到的predict_normal.py來獲得這一索引。
           
          接下來是幾個(gè)變量的初始化,以及加載/預(yù)處理--input圖像:

          # define theepsilon and learning rate constantsEPS = 2 / 255.0LR = 0.1# load the inputimage from disk and preprocess itprint("[INFO] loadingimage...")image = cv2.imread(args["input"])image = preprocess_image(image)
           
          第2行定義了用于在構(gòu)建對(duì)抗圖像時(shí)來裁剪tensor的epsilon值(EPS)。2 / 255.0 是EPS的一個(gè)用于對(duì)抗類刊物或教程的標(biāo)準(zhǔn)值和指導(dǎo)值(如果你想要了解更多的默認(rèn)值,你可以參考這份指導(dǎo))。
           
          在第3行定義了學(xué)習(xí)速率。經(jīng)驗(yàn)之談,LR的初始值一般設(shè)為0.1,在創(chuàng)建你自己的對(duì)抗圖像時(shí)可能需要調(diào)整這個(gè)值。
           
          最后兩行載入輸入圖像,利用preprocess_image輔助函數(shù)來對(duì)其進(jìn)行預(yù)處理。
           
          接下來,可以載入ResNet模型:

          # load thepre-trained  ResNet50 model for running inferenceprint("[INFO] loadingpre-trained ResNet50 model...")model = ResNet50(weights="imagenet")# initializeoptimizer and loss functionoptimizer = Adam(learning_rate=LR)sccLoss = SparseCategoricalCrossentropy()
           
          第3行載入在ImageNet數(shù)據(jù)集上訓(xùn)練好的ResNet50模型。
           
          我們將會(huì)用到Adam優(yōu)化器,以及稀疏的分類損失用于更新我們的擾動(dòng)向量。
           
          讓我們來構(gòu)建對(duì)抗圖像:

          # create a tensorbased off the input image and initialize the# perturbation vector (we will update this vector via training)baseImage = tf.constant(image,dtype=tf.float32)delta = tf.Variable(tf.zeros_like(baseImage), trainable=True)# generate the perturbation vector to create an adversarialexampleprint("[INFO]generating perturbation...")deltaUpdated = generate_adversaries(model, baseImage,delta,args["class_idx"])# create theadversarial example, swap color channels, and save the# output image to diskprint("[INFO]creating adversarial example...")adverImage = (baseImage +deltaUpdated).numpy().squeeze()adverImage = np.clip(adverImage, 0, 255).astype("uint8")adverImage = cv2.cvtColor(adverImage,cv2.COLOR_RGB2BGR)cv2.imwrite(args["output"], adverImage)
           
          第3行根據(jù)輸入圖像構(gòu)建了一個(gè)tensor,第4行初始化擾動(dòng)向量delta。
           
          我們可以把ResNet50、輸入圖像、初始化后的擾動(dòng)向量、及類標(biāo)簽整數(shù)值索引作為參數(shù),用來調(diào)用generate_adversaries并更新delta向量。
           
          在 generate_adversaries函數(shù)執(zhí)行時(shí),會(huì)一直更新delta擾動(dòng)向量,生成最終的噪聲向量deltaUpdated。
           
          在倒數(shù)第4行,在baseImage上加入deltaUpdated 向量,就生成了最終的對(duì)抗圖像(adverImage)。
           
          然后,對(duì)生成的對(duì)抗圖像進(jìn)行以下三步后處理:

          1. 將超出[0,255] 范圍的值裁剪掉;
          2. 將圖片轉(zhuǎn)化成一個(gè)無符號(hào)8-bit(unsigned 8-bit)整數(shù)(這樣OpenCV才能對(duì)圖片進(jìn)行處理);
          3. 將通道順序從RGB轉(zhuǎn)換成BGR。
           
          在經(jīng)過這些處理步驟后,就可以把對(duì)抗圖像寫入到硬盤里了。
           
          真正的問題來了,我們新創(chuàng)建的對(duì)抗圖像能夠欺騙我們的ResNet模型嗎?
           
          下一段代碼就可以回答這一問題:

          # run inferencewith this adversarial example, parse the results,# and display the top-1 predicted resultprint("[INFO]running inference on the adversarial example...")preprocessedImage = preprocess_input(baseImage +deltaUpdated)predictions =model.predict(preprocessedImage)predictions = decode_predictions(predictions, top=3)[0]label = predictions[0][1]confidence = predictions[0][2] * 100print("[INFO] label:{} confidence: {:.2f}%".format(label,confidence))# draw the top-most predicted label on the adversarial imagealong# with theconfidence scoretext = "{}: {:.2f}%".format(label, confidence)cv2.putText(adverImage, text, (3, 20),cv2.FONT_HERSHEY_SIMPLEX, 0.5,(0, 255, 0), 2)# show the output imagecv2.imshow("Output", adverImage)cv2.waitKey(0)
           
          在第4行又一次創(chuàng)建了一個(gè)對(duì)抗圖像,方式還是在原始輸入圖像中加入delta噪聲向量,但這次我們利用ResNet的preprocess_input功能來處理。
           
          生成的預(yù)處理圖像進(jìn)入到ResNet,然后會(huì)得到top-3預(yù)測(cè)結(jié)果并對(duì)他們進(jìn)行解碼(第5和6行)。
           
          接著我們獲取到top-1標(biāo)簽和對(duì)應(yīng)的概率/置信度,并將這些值顯示在終端上(第7-10行)。
           
          最后一步就是把最高的預(yù)測(cè)值標(biāo)在輸出的對(duì)抗圖像上,并展示在屏幕上。

          對(duì)抗圖像和攻擊的結(jié)果

          準(zhǔn)備好見證一次對(duì)抗攻擊了嗎?
           
          從這里開始,你就可以打開終端并執(zhí)行下列代碼了:

          $ python generate_basic_adversary.py --inputpig.jpg --output adversarial.png --class-idx 341[INFO] loading image...[INFO] loading pre-trained ResNet50 model...[INFO] generatingperturbation...step: 0, loss:-0.0004124982515349984...step: 5, loss:-0.0010656398953869939...step: 10, loss:-0.005332294851541519...step: 15, loss: -0.06327803432941437...step: 20, loss: -0.7707189321517944...step: 25, loss: -3.4659299850463867...step: 30, loss: -7.515471935272217...step: 35, loss: -13.503922462463379...step: 40, loss: -16.118188858032227...step: 45, loss: -16.118192672729492...[INFO] creating adversarial example...[INFO] running inference on theadversarial example...[INFO] label: wombat confidence: 100.00%

          圖六:之前,這張輸入圖片被正確地分在了“豬(hog)”類別中,但現(xiàn)在因?yàn)閷?duì)抗攻擊而被分在了“袋熊(wombat)”類別里!

           
          我們的輸入圖片 pig.jpg 之前被正確地分在了“豬(hog)”類別中,但現(xiàn)在它的標(biāo)簽卻成為了“袋熊(wombat)”!
           
          將原始圖片和用generate_basic_adversary.py腳本生成的對(duì)抗圖片放在一起進(jìn)行對(duì)比:

          圖七:在左邊是原始圖片,分類結(jié)果正確。右邊將是對(duì)抗圖片,被錯(cuò)誤地分在了“袋熊(wombat)”類別中。而對(duì)于人類的眼睛來看完全分辨不出兩張圖片的有什么區(qū)別。
           
          左邊是最初豬的圖像,在右邊是輸出的對(duì)抗圖像,這張圖像被錯(cuò)誤的分在了“袋熊(wombat)”類別。
           
          就像你看到的一樣,這兩張圖片沒有任何可感知的差別,我們?nèi)祟惖难劬床怀鋈魏螀^(qū)別,但對(duì)于ResNet來說確實(shí)完全不同的。
           
          這很好,但我們無法清晰地掌控對(duì)抗圖像被最終識(shí)別的類別標(biāo)簽。這會(huì)引起以下問題:
          我們有可能掌控輸入圖片的最終類別標(biāo)簽嗎?答案是肯定的,這會(huì)成為我下一篇教程的主題。
           
          總結(jié)來說,對(duì)抗圖像和對(duì)抗攻擊真的是令人細(xì)思極恐。但如果等我們看到下一篇教程,就可以提前防御這種類型的進(jìn)攻。稍后再詳細(xì)說明下。

          致謝

          如果沒有Goodfellow, Szegedy和其他深度學(xué)習(xí)的研究者的工作,這篇教程就無法完成。
           
          另外,這篇教程所用到的實(shí)現(xiàn)代碼靈感來自于TensorFlow官方實(shí)現(xiàn)的《Fast Gradient Signed Method》。我強(qiáng)烈建議你去看看其他的示例,每一段代碼都比這篇教程中的在理論和數(shù)學(xué)上更加明確。
           
          總結(jié)


          在這篇教程中,你學(xué)到關(guān)于對(duì)抗攻擊的知識(shí),關(guān)于他們是怎樣工作的,以及隨著人工智能和深度神經(jīng)網(wǎng)絡(luò)與這個(gè)世界的關(guān)聯(lián)越來越高,對(duì)抗攻擊就會(huì)構(gòu)成更大的威脅。

          接著我們利用深度學(xué)習(xí)庫(kù)Keras 和TensorFlow實(shí)現(xiàn)了基本的對(duì)抗攻擊算法。
          利用對(duì)抗攻擊,我們可以蓄意擾亂一張輸入圖片,例如:

          1. 這張輸入圖片會(huì)被錯(cuò)誤分類。
          2. 然而,肉眼看上去被擾亂的圖片還是和之前一樣。

          利用這篇教程所使用的方法,我們并不能控制圖片最終被判別的類別標(biāo)簽——我們所做的只是創(chuàng)造一個(gè)噪聲向量,并將其嵌入到輸入圖像中,導(dǎo)致深度神經(jīng)網(wǎng)絡(luò)對(duì)其錯(cuò)誤分類。

          如果我們能夠控制最終的類別標(biāo)簽會(huì)怎樣呢?比如說,我們拿一張“狗”的圖片,然后制造一次對(duì)抗攻擊,讓卷積神經(jīng)網(wǎng)絡(luò)認(rèn)為這是一張“貓”的圖片,這有沒有可能呢?

          答案是肯定的——我們會(huì)在下一篇教程中來談?wù)撨@一話題。

          原文鏈接:
          https://www.pyimagesearch.com/2020/10/19/adversarial-images-and-attacks-with-keras-and-tensorflow/
          原文標(biāo)題:
          Adversarial images andattacks with Keras and TensorFlow


          下載1:OpenCV-Contrib擴(kuò)展模塊中文版教程
          在「小白學(xué)視覺」公眾號(hào)后臺(tái)回復(fù):擴(kuò)展模塊中文教程,即可下載全網(wǎng)第一份OpenCV擴(kuò)展模塊教程中文版,涵蓋擴(kuò)展模塊安裝、SFM算法、立體視覺、目標(biāo)跟蹤、生物視覺、超分辨率處理等二十多章內(nèi)容。

          下載2:Python視覺實(shí)戰(zhàn)項(xiàng)目52講
          小白學(xué)視覺公眾號(hào)后臺(tái)回復(fù):Python視覺實(shí)戰(zhàn)項(xiàng)目,即可下載包括圖像分割、口罩檢測(cè)、車道線檢測(cè)、車輛計(jì)數(shù)、添加眼線、車牌識(shí)別、字符識(shí)別、情緒檢測(cè)、文本內(nèi)容提取、面部識(shí)別等31個(gè)視覺實(shí)戰(zhàn)項(xiàng)目,助力快速學(xué)校計(jì)算機(jī)視覺。

          下載3:OpenCV實(shí)戰(zhàn)項(xiàng)目20講
          小白學(xué)視覺公眾號(hào)后臺(tái)回復(fù):OpenCV實(shí)戰(zhàn)項(xiàng)目20講,即可下載含有20個(gè)基于OpenCV實(shí)現(xiàn)20個(gè)實(shí)戰(zhàn)項(xiàng)目,實(shí)現(xiàn)OpenCV學(xué)習(xí)進(jìn)階。

          交流群


          歡迎加入公眾號(hào)讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測(cè)、分割、識(shí)別、醫(yī)學(xué)影像、GAN、算法競(jìng)賽等微信群(以后會(huì)逐漸細(xì)分),請(qǐng)掃描下面微信號(hào)加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請(qǐng)按照格式備注,否則不予通過。添加成功后會(huì)根據(jù)研究方向邀請(qǐng)進(jìn)入相關(guān)微信群。請(qǐng)勿在群內(nèi)發(fā)送廣告,否則會(huì)請(qǐng)出群,謝謝理解~


          瀏覽 30
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人色情五月天 | 日韩性爱网 | 成人天堂AV | 四虎影院a | 成人毛片18岁女人 |