1. 程式人生 > >CNN(卷積神經網路)是什麼?(轉)

CNN(卷積神經網路)是什麼?(轉)

卷積神經網路,聽起來像是電腦科學、生物學和數學的詭異組合,但它們已經成為計算機視覺領域中最具影響力的革新的一部分。神經網路在 2012 年嶄露頭角,Alex Krizhevsky 憑藉它們贏得了那一年的 ImageNet 挑戰賽(大體上相當於計算機視覺的年度奧林匹克),他把分類誤差記錄從 26% 降到了 15%,在當時震驚了世界。自那之後,大量公司開始將深度學習用作服務的核心。Facebook 將神經網路用於自動標註演算法、谷歌將它用於圖片搜尋、亞馬遜將它用於商品推薦、Pinterest 將它用於個性化主頁推送、Instagram 將它用於搜尋架構。

<img src="https://pic2.zhimg.com/50/v2-834043be6a015ef9d7cf04de0cf03cca_hd.jpg" data-rawwidth="640" data-rawheight="249" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic2.zhimg.com/v2-834043be6a015ef9d7cf04de0cf03cca_r.jpg">

然而,應用這些網路最經典最流行的案例是進行影象處理。在影象處理任務中,讓我們看一下如何使用卷積神經網路進行影象分類。


問題空間


影象分類是對輸入影象的操作,最終輸出一組最好地描述了影象內容的分類(如貓、狗等)或分類的概率。對人類來說,識別是打出生便開始學習的技能之一,對成人來說更是信手拈來,毫不費力。我們只需一眼便能快速識別我們所處的環境以及環繞在我們身邊的物體。當我們看到一張圖片或是環看四周的時候,無需刻意觀察,多數時候也能立即描述出場景特徵並標記出每一個物件。快速識別不同模式、根據早前知識進行歸納、以及適應不同的影象環境一直都是人類的專屬技能,機器尚未享有。

<img src="https://pic3.zhimg.com/50/v2-a4552450f9ca496886c48cdd44475cce_hd.jpg" data-rawwidth="636" data-rawheight="222" class="origin_image zh-lightbox-thumb" width="636" data-original="https://pic3.zhimg.com/v2-a4552450f9ca496886c48cdd44475cce_r.jpg">

輸入與輸出


當計算機看到一張影象(輸入一張影象)時,它看的是一大堆畫素值。根據圖片的解析度和尺寸,它將看到一個 32 x 32 x 3 的陣列(3 指代的是 RGB 值)。為了講清楚這一點,假設我們有一張 JPG 格式的 480 x 480 大小的彩色圖片,那麼它對應的陣列就有 480 x 480 x 3 個元素。其中每個數字的值從 0 到 255 不等,其描述了對應那一點的畫素灰度。當我們人類對影象進行分類時,這些數字毫無用處,可它們卻是計算機可獲得的唯一輸入。其中的思想是:當你提供給計算機這一陣列後,它將輸出描述該影象屬於某一特定分類的概率的數字(比如:80% 是貓、15% 是狗、5% 是鳥)。


我們想要計算機做什麼


現在我們知道了問題所在以及輸入與輸出,就該考慮如何處理了。我們想要計算機能夠區分開所有提供給它的圖片,以及搞清楚貓貓狗狗各自的特有特徵。這也是我們人類的大腦中不自覺進行著的過程。當我們看到一幅狗的圖片時,如果有諸如爪子或四條腿之類的明顯特徵,我們便能將它歸類為狗。同樣地,計算機也可以通過尋找諸如邊緣和曲線之類的低階特點來分類圖片,繼而通過一系列卷積層級建構出更為抽象的概念。這是 CNN(卷積神經網路)工作方式的大體概述,下面是具體細節。


生物學連線


首先介紹些背景。當你第一次聽到卷積神經網路這一術語,可能會聯想到神經科學或生物學,那就對了。可以這樣說。CNN 的確是從視覺皮層的生物學上獲得啟發的。視覺皮層有小部分細胞對特定部分的視覺區域敏感。Hubel 和 Wiesel 於 1962 年進行的一項有趣的試驗詳細說明了這一觀點,他們驗證出大腦中的一些個體神經細胞只有在特定方向的邊緣存在時才能做出反應(即放電)。例如,一些神經元只對垂直邊緣興奮,另一些對水平或對角邊緣興奮。Hubel 和 Wisesl 發現所有這些神經元都以柱狀結構的形式進行排列,而且一起工作才能產生視覺感知。這種一個系統中的特定元件有特定任務的觀點(視覺皮層的神經元細胞尋找特定特徵)在機器中同樣適用,這就是 CNN 的基礎。


結構


回到細節上來。更為詳細的 CNN 工作概述指的是你挑一張影象,讓它歷經一系列卷積層、非線性層、池化(下采樣(downsampling))層和完全連線層,最終得到輸出。正如之前所說,輸出可以是最好地描述了影象內容的一個單獨分類或一組分類的概率。如今,難點在於理解其中每一層的工作方法。我們先來看最重要的部分。


第一層——數學部分


CNN 的第一層通常是卷積層(Convolutional Layer)。首先需要了解卷積層的輸入內容是什麼。如上所述,輸入內容為一個 32 x 32 x 3 的畫素值陣列。現在,解釋卷積層的最佳方法是想象有一束手電筒光正從影象的左上角照過。假設手電筒光可以覆蓋 5 x 5 的區域,想象一下手電筒光照過輸入影象的所有區域。在機器學習術語中,這束手電筒被叫做過濾器(filter,有時候也被稱為神經元(neuron)或核(kernel)),被照過的區域被稱為感受野(receptive field)。過濾器同樣也是一個數組(其中的數字被稱作權重或引數)。重點在於過濾器的深度必須與輸入內容的深度相同(這樣才能確保可以進行數學運算),因此過濾器大小為 5 x 5 x 3。現在,以過濾器所處在的第一個位置為例,即影象的左上角。當篩選值在影象上滑動(卷積運算)時,過濾器中的值會與影象中的原始畫素值相乘(又稱為計算點積)。這些乘積被加在一起(從數學上來說,一共會有 75 個乘積)。現在你得到了一個數字。切記,該數字只是表示過濾器位於圖片左上角的情況。我們在輸入內容上的每一位置重複該過程。(下一步將是將過濾器右移 1 單元,接著再右移 1 單元,以此類推。)輸入內容上的每一特定位置都會產生一個數字。過濾器滑過所有位置後將得到一個 28 x 28 x 1 的陣列,我們稱之為啟用對映(activation map)或特徵對映(feature map)。之所以得到一個 28 x 28 的陣列的原因在於,在一張 32 x 32 的輸入影象上,5 x 5 的過濾器能夠覆蓋到 784 個不同的位置。這 784 個位置可對映為一個 28 x 28 的陣列。


<img src="https://pic1.zhimg.com/50/v2-790a3d600c6b6208f3c7db27c393a1ea_hd.jpg" data-rawwidth="640" data-rawheight="347" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic1.zhimg.com/v2-790a3d600c6b6208f3c7db27c393a1ea_r.jpg">

(注意:包括上圖在內的一些圖片來自於 Micheal Nielsen 的 「神經網路與深度學習( Neural Networks and Deep Learning)」一書。我強烈推薦這本書。這本書可免費線上瀏覽:Neural networks and deep learning


當我們使用兩個而不是一個 5 x 5 x 3 的過濾器時,輸出總量將會變成 28 x 28 x 2。採用的過濾器越多,空間維度( spatial dimensions)保留得也就越好。數學上而言,這就是卷積層上發生的事情。


第一層——高層次角度


不過,從高層次角度而言卷積是如何工作的?每個過濾器可以被看成是特徵識別符號( feature identifiers)。這裡的特徵指的是例如直邊緣、原色、曲線之類的東西。想一想所有影象都共有的一些最簡單的特徵。假設第一組過濾器是 7 x 7 x 3 的曲線檢測器。(在這一節,為了易於分析,暫且忽略該過濾器的深度為 3 個單元,只考慮過濾器和影象的頂層層面。)作為曲線過濾器,它將有一個畫素結構,在曲線形狀旁時會產生更高的數值(切記,我們所討論的過濾器不過是一組數值!)

<img src="https://pic2.zhimg.com/50/v2-4e15bce4b402176ce8c6dca1538836d7_hd.jpg" data-rawwidth="624" data-rawheight="278" class="origin_image zh-lightbox-thumb" width="624" data-original="https://pic2.zhimg.com/v2-4e15bce4b402176ce8c6dca1538836d7_r.jpg">

左圖:過濾器的畫素表示;右圖:曲線檢測器過濾器的視覺化;對比兩圖可以看到數值和形狀的對應


回到數學角度來看這一過程。當我們將過濾器置於輸入內容的左上角時,它將計算過濾器和這一區域畫素值之間的點積。拿一張需要分類的照片為例,將過濾器放在它的左上角。

<img src="https://pic1.zhimg.com/50/v2-a7a8f5b74d66f7b5389f9c17a1417c09_hd.jpg" data-rawwidth="640" data-rawheight="227" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic1.zhimg.com/v2-a7a8f5b74d66f7b5389f9c17a1417c09_r.jpg">切記,我們要做的是將過濾器與影象的原始畫素值相乘。

<img src="https://pic2.zhimg.com/50/v2-f1c852e5da0df5407565aa5b0f78fe43_hd.jpg" data-rawwidth="640" data-rawheight="241" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic2.zhimg.com/v2-f1c852e5da0df5407565aa5b0f78fe43_r.jpg">

左圖:感受野的視覺化;右圖:感受野的畫素表示 * 過濾器的畫素表示


簡單來說,如果輸入影象上某個形狀看起來很像過濾器表示的曲線,那麼所有點積加在一起將會得出一個很大的值!讓我們看看移動過濾器時會發生什麼。

<img src="https://pic3.zhimg.com/50/v2-4c637624f3f01ba910736784547c37db_hd.jpg" data-rawwidth="640" data-rawheight="224" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic3.zhimg.com/v2-4c637624f3f01ba910736784547c37db_r.jpg">

這個值小了很多!這是因為影象的這一部分和曲線檢測器過濾器不存在對應。記住,這個卷積層的輸出是一個啟用對映(activation map)。因此,在這個帶有一個過濾器卷積的例子裡(當篩選值為曲線檢測器),啟用對映將會顯示出影象裡最像曲線的區域。在該例子中,28 x 28 x 1 的啟用對映的左上角的值為 6600。高數值意味著很有可能是輸入內容中的曲線激活了過濾器。啟用地圖右上角的值將會是 0,因為輸入內容中沒有任何東西能啟用過濾器(更簡單地說,原始圖片中的這一區域沒有任何曲線)。這僅僅是一組檢測右彎曲線的過濾器。還有其它檢測左彎曲線或直線邊緣的過濾器。過濾器越多,啟用對映的深度越大,我們對輸入內容的瞭解也就越多。


宣告:我在本小節中描繪的過濾器(filter)只是為了描述卷積中的數學過程。在下圖中你可以看到訓練後的網路中第一個卷積層的過濾器的實際視覺化。儘管如此,主要觀點仍舊不變。當在輸入內容中尋找特定特徵時,第一層上的過濾器在輸入影象上進行卷積運算和「啟用」(即計算高數值)。


<img src="https://pic3.zhimg.com/50/v2-2743f8ad8c349c6bcc1806fcefaa8e5e_hd.jpg" data-rawwidth="270" data-rawheight="277" class="content_image" width="270">

網路中的更深處


在傳統卷積神經網路架構中,卷積層之間還有其它型別的層。我強烈建議有興趣的人閱讀和它們有關的材料,並理解相應的功能和作用;但總的來說,它們提供的非線性和維度保留有助於提高網路的穩健性(robustness)並控制過擬合。一個典型的 CNN 結構看起來是這樣的:


<img src="https://pic3.zhimg.com/50/v2-afa8132cdb9958051f102657335ac68f_hd.jpg" data-rawwidth="639" data-rawheight="46" class="origin_image zh-lightbox-thumb" width="639" data-original="https://pic3.zhimg.com/v2-afa8132cdb9958051f102657335ac68f_r.jpg">

輸入→卷積→ReLU→卷積→ReLU→池化→ReLU→卷積→ReLU→池化→全連線


我們稍後再來討論關鍵的最後一層,先回顧一下學到了哪些。我們討論了過濾器是如何在第一個卷積層檢測特徵的。它們檢測邊緣和曲線一類的低階特徵。正如想象的那樣,為了預測出圖片內容的分類,網路需要識別更高階的特徵,例如手、爪子與耳朵的區別。第一個卷積層的輸出將會是一個 28 x 28 x 3 的陣列(假設我們採用三個 5 x 5 x 3 的過濾器)。當我們進入另一卷積層時,第一個卷積層的輸出便是第二個卷積層的輸入。解釋這一點有些困難。第一層的輸入是原始影象,而第二卷積層的輸入正是第一層輸出的啟用對映。也就是說,這一層的輸入大體描繪了低階特徵在原始圖片中的位置。在此基礎上再採用一組過濾器(讓它通過第 2 個卷積層),輸出將是表示了更高階的特徵的啟用對映。這類特徵可以是半圓(曲線和直線的組合)或四邊形(幾條直線的組合)。隨著進入網路越深和經過更多卷積層後,你將得到更為複雜特徵的啟用對映。在網路的最後,可能會有一些過濾器會在看到手寫筆跡或粉紅物體等時啟用。如果你想知道更多關於視覺化卷積網路中過濾器的內容,可以檢視 Matt Zeiler 和 Rob Fergus 的一篇討論該問題的頗為傑出的研究論文。在 YouTube 上,Jason Yosinski 有一段視訊十分視覺化地呈現了這一過程(如下)。有趣的是,越深入網路,過濾器的感受野越大,意味著它們能夠處理更大範圍的原始輸入內容(或者說它們可以對更大區域的畫素空間產生反應)。


完全連線層


檢測高階特徵之後,網路最後的完全連線層就更是錦上添花了。簡單地說,這一層處理輸入內容(該輸入可能是卷積層、ReLU 層或是池化層的輸出)後會輸出一個 N 維向量,N 是該程式必須選擇的分類數量。例如,如果你想得到一個數字分類程式,如果有 10 個數字,N 就等於 10。這個 N 維向量中的每一數字都代表某一特定類別的概率。例如,如果某一數字分類程式的結果向量是 [0 .1 .1 .75 0 0 0 0 0 .05],則代表該圖片有 10% 的概率是 1、10% 的概率是 2、75% 的概率是 3、還有 5% 的概率是 9(注:還有其他表現輸出的方式,這裡只展示了 softmax 的方法)。完全連線層觀察上一層的輸出(其表示了更高階特徵的啟用對映)並確定這些特徵與哪一分類最為吻合。例如,如果該程式預測某一影象的內容為狗,那麼啟用對映中的高數值便會代表一些爪子或四條腿之類的高階特徵。同樣地,如果程式測定某一圖片的內容為鳥,啟用對映中的高數值便會代表諸如翅膀或鳥喙之類的高階特徵。大體上來說,完全連線層觀察高階特徵和哪一分類最為吻合和擁有怎樣的特定權重,因此當計算出權重與先前層之間的點積後,你將得到不同分類的正確概率。

<img src="https://pic4.zhimg.com/50/v2-0d4e7aabbd235461330da8904cd20bb5_hd.jpg" data-rawwidth="640" data-rawheight="206" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic4.zhimg.com/v2-0d4e7aabbd235461330da8904cd20bb5_r.jpg">

訓練(也就是:什麼能讓其有效)


下面是神經網路中的一個我尚未提及但卻最為重要的部分。閱讀過程中你可能會提出許多問題。第一卷積層中的濾波器是如何知道尋找邊緣與曲線的?完全連線層怎麼知道觀察哪些啟用圖?每一層級的濾波器如何知道需要哪些值?計算機通過一個名為反向傳播的訓練過程來調整過濾器值(或權重)。


在探討反向傳播之前,我們首先必須回顧一下神經網路工作起來需要什麼。在我們剛出生的時候,大腦一無所知。我們不曉得貓啊狗啊鳥啊都是些什麼東西。與之類似的是 CNN 剛開始的時候,權重或過濾器值都是隨機的。濾波器不知道要去尋找邊緣和曲線。更高層的過濾器值也不知道要去尋找爪子和鳥喙。不過隨著年歲的增長,父母和老師向我們介紹各式各樣的圖片並且一一作出標記。CNN 經歷的便是一個介紹圖片與分類標記的訓練過程。在深入探討之前,先設定一個訓練集,在這裡有上千張狗、貓、鳥的圖片,每一張都依照內容被標記。下面回到反向傳播的問題上來。


反向傳播可分為四部分,分別是前向傳導、損失函式、後向傳導,以及權重更新。在前向傳導中,選擇一張 32×32×3 的陣列訓練影象並讓它通過整個網路。在第一個訓練樣例上,由於所有的權重或者過濾器值都是隨機初始化的,輸出可能會是 [.1 .1 .1 .1 .1 .1 .1 .1 .1 .1],即一個不偏向任何數字的輸出。一個有著這樣權重的網路無法尋找低階特徵,或者說是不能做出任何合理的分類。接下來是反向傳播的損失函式部分。切記我們現在使用的是既有影象又有標記的訓練資料。假設輸入的第一張訓練圖片為 3,標籤將會是 [0 0 0 1 0 0 0 0 0 0]。損失函式有許多種定義方法,常見的一種是 MSE (均方誤差)。

<img src="https://pic4.zhimg.com/50/v2-1d99155e7d28ecc87c9207e1ec845e5d_hd.jpg" data-rawwidth="472" data-rawheight="63" class="origin_image zh-lightbox-thumb" width="472" data-original="https://pic4.zhimg.com/v2-1d99155e7d28ecc87c9207e1ec845e5d_r.jpg">假設變數 L 等同該數值。正如所料,前兩張訓練圖片的損失將會極高。現在,我們直觀地想一下。我們想要預測標記(卷積網路的輸出)與訓練標記相同(意味著網路預測正確)。為了做到這一點,我們想要將損失數量最小化。將其視為微積分優化問題的話,也就是說我們想要找出是哪部分輸入(例子中的權重)直接導致了網路的損失(或錯誤)。

<img src="https://pic1.zhimg.com/50/v2-8920aa91f987f9b43c61d6755331e006_hd.jpg" data-rawwidth="640" data-rawheight="222" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic1.zhimg.com/v2-8920aa91f987f9b43c61d6755331e006_r.jpg">

這是一個 dL/dW 的數學等式,W 是特定層級的權重。我們接下來要做的是在網路中進行後向傳導,測定出是哪部分權重導致了最大的損失,尋找調整方法並減少損失。一旦計算出該導數,將進行最後一步也就是權重更新。所有的過濾器的權重將會更新,以便它們順著梯度方向改變。


<img src="https://pic1.zhimg.com/50/v2-277722f38cdc66537c2bffbda47a3617_hd.jpg" data-rawwidth="606" data-rawheight="99" class="origin_image zh-lightbox-thumb" width="606" data-original="https://pic1.zhimg.com/v2-277722f38cdc66537c2bffbda47a3617_r.jpg">學習速率是一個由程式設計師決定的引數。高學習速率意味著權重更新的動作更大,因此可能該模式將花費更少的時間收斂到最優權重。然而,學習速率過高會導致跳動過大,不夠準確以致於達不到最優點。
<img src="https://pic2.zhimg.com/50/v2-112ee3cfba309c85245c3a2fd6d42a04_hd.jpg" data-rawwidth="640" data-rawheight="198" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic2.zhimg.com/v2-112ee3cfba309c85245c3a2fd6d42a04_r.jpg">

總的來說,前向傳導、損失函式、後向傳導、以及引數更新被稱為一個學習週期。對每一訓練圖片,程式將重複固定數目的週期過程。一旦完成了最後訓練樣本上的引數更新,網路有望得到足夠好的訓練,以便層級中的權重得到正確調整。


測試


最後,為了檢驗 CNN 能否工作,我們準備不同的另一組圖片與標記集(不能在訓練和測試中使用相同的!)並讓它們通過這個 CNN。我們將輸出與實際情況(ground truth )相比較,看看網路是否有效!


企業如何使用 CNN


資料、資料、資料。資料越多的企業在競爭中越發彰顯優勢。你提供給網路的訓練資料越多,你能進行的訓練迭代也越多,緊接著權重更新也多,那麼當用於產品時調整出的網路自然就好。Facebook (和 Instagram)可以使用它如今擁有的十幾億使用者的圖片,Pinterest 可以使用它站點上 500 億花瓣的資訊,谷歌可以使用搜索資料,亞馬遜可以使用每天銷售的數以百萬計的商品資料。而你現在也知道它們使用資料背後的神奇之處了。


Part 2:卷積神經網路中的部分問題



引言


在這篇文章中,我們將更深入地介紹有關卷積神經網路(ConvNet)的詳細情況。宣告:我確實知道本文中一部分內容相當複雜,可以用一整篇文章進行介紹。但為了在保持全面性的同時保證簡潔,我會在文章中相關位置提供一些更詳細解釋該相關主題的論文連結。


步幅和填充


好了,現在來看一下我們的卷積神經網路。還記得過濾器、感受野和卷積嗎?很好。現在,要改變每一層的行為,有兩個主要引數是我們可以調整的。選擇了過濾器的尺寸以後,我們還需要選擇步幅(stride)和填充(padding)。


步幅控制著過濾器圍繞輸入內容進行卷積計算的方式。在第一部分我們舉的例子中,過濾器通過每次移動一個單元的方式對輸入內容進行卷積。過濾器移動的距離就是步幅。在那個例子中,步幅被預設設定為1。步幅的設定通常要確保輸出內容是一個整數而非分數。讓我們看一個例子。想象一個 7 x 7 的輸入影象,一個 3 x 3 過濾器(簡單起見不考慮第三個維度),步幅為 1。這是一種慣常的情況。

<img src="https://pic3.zhimg.com/50/v2-504ba01c8af8e2d7d41957ddaa4fe6d3_hd.jpg" data-rawwidth="594" data-rawheight="236" class="origin_image zh-lightbox-thumb" width="594" data-original="https://pic3.zhimg.com/v2-504ba01c8af8e2d7d41957ddaa4fe6d3_r.jpg">還是老一套,對吧?看你能不能試著猜出如果步幅增加到 2,輸出內容會怎麼樣。

<img src="https://pic3.zhimg.com/50/v2-c4a7b49deda73e2b26232d12db7e77c6_hd.jpg" data-rawwidth="627" data-rawheight="247" class="origin_image zh-lightbox-thumb" width="627" data-original="https://pic3.zhimg.com/v2-c4a7b49deda73e2b26232d12db7e77c6_r.jpg">

所以,正如你能想到的,感受野移動了兩個單元,輸出內容同樣也會減小。注意,如果試圖把我們的步幅設定成 3,那我們就會難以調節間距並確保感受野與輸入影象匹配。正常情況下,程式設計師如果想讓接受域重疊得更少並且想要更小的空間維度(spatial dimensions)時,他們會增加步幅。


現在讓我們看一下填充(padding)。在此之前,想象一個場景:當你把 5 x 5 x 3 的過濾器用在 32 x 32 x 3 的輸入上時,會發生什麼?輸出的大小會是 28 x 28 x 3。注意,這裡空間維度減小了。如果我們繼續用卷積層,尺寸減小的速度就會超過我們的期望。在網路的早期層中,我們想要儘可能多地保留原始輸入內容的資訊,這樣我們就能提取出那些低層的特徵。比如說我們想要應用同樣的卷積層,但又想讓輸出量維持為 32 x 32 x 3 。為做到這點,我們可以對這個層應用大小為 2 的零填充(zero padding)。零填充在輸入內容的邊界周圍補充零。如果我們用兩個零填充,就會得到一個 36 x 36 x 3 的輸入卷。

<img src="https://pic1.zhimg.com/50/v2-16ad975f95ef7a45ab836fa563e73736_hd.jpg" data-rawwidth="640" data-rawheight="248" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic1.zhimg.com/v2-16ad975f95ef7a45ab836fa563e73736_r.jpg">

如果我們在輸入內容的周圍應用兩次零填充,那麼輸入量就為 32×32×3。然後,當我們應用帶有 3 個 5×5×3 的過濾器,以 1 的步幅進行處理時,我們也可以得到一個 32×32×3 的輸出


如果你的步幅為 1,而且把零填充設定為

<img src="https://pic3.zhimg.com/50/v2-151ea0d356f24533867c018bec7c3127_hd.jpg" data-rawwidth="425" data-rawheight="52" class="origin_image zh-lightbox-thumb" width="425" data-original="https://pic3.zhimg.com/v2-151ea0d356f24533867c018bec7c3127_r.jpg">

K 是過濾器尺寸,那麼輸入和輸出內容就總能保持一致的空間維度。


計算任意給定卷積層的輸出的大小的公式是

<img src="https://pic4.zhimg.com/50/v2-47d83d1bb16072a57d5c1fbb49991d68_hd.jpg" data-rawwidth="302" data-rawheight="53" class="content_image" width="302">

其中 O 是輸出尺寸,K 是過濾器尺寸,P 是填充,S 是步幅。


選擇超引數


我們怎麼知道要用多少層、多少卷積層、過濾器尺寸是多少、以及步幅和填充值多大呢?這些問題很重要,但又沒有一個所有研究人員都在使用的固定標準。這是因為神經網路很大程度上取決於你的資料型別。影象的大小、複雜度、影象處理任務的型別以及其他更多特徵的不同都會造成資料的不同。對於你的資料集,想出如何選擇超引數的一個方法是找到能創造出影象在合適尺度上抽象的正確組合。


ReLU(修正線性單元)層


在每個卷積層之後,通常會立即應用一個非線性層(或啟用層)。其目的是給一個在卷積層中剛經過線性計算操作(只是陣列元素依次(element wise)相乘與求和)的系統引入非線性特徵。過去,人們用的是像雙曲正切和 S 型函式這樣的非線性方程,但研究者發現 ReLU 層效果好得多,因為神經網路能夠在準確度不發生明顯改變的情況下把訓練速度提高很多(由於計算效率增加)。它同樣能幫助減輕梯度消失的問題——由於梯度以指數方式在層中消失,導致網路較底層的訓練速度非常慢。ReLU 層對輸入內容的所有值都應用了函式 f(x) = max(0, x)。用基本術語來說,這一層把所有的負啟用(negative activation)都變為零。這一層會增加模型乃至整個神經網路的非線性特徵,而且不會影響卷積層的感受野。


  • 參見 Geoffrey Hinton(即深度學習之父)的論文:Rectified Linear Units Improve Restricted Boltzmann Machines


池化層


在幾個 ReLU 層之後,程式設計師也許會選擇用一個池化層(pooling layer)。它同時也被叫做下采樣(downsampling)層。在這個類別中,也有幾種可供選擇的層,最受歡迎的就是最大池化( max-pooling)。它基本上採用了一個過濾器(通常是 2x2 的)和一個同樣長度的步幅。然後把它應用到輸入內容上,輸出過濾器卷積計算的每個子區域中的最大數字。

<img src="https://pic2.zhimg.com/50/v2-a944f0f847266c28ad93f2b6b9986e65_hd.jpg" data-rawwidth="640" data-rawheight="333" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic2.zhimg.com/v2-a944f0f847266c28ad93f2b6b9986e65_r.jpg">

帶有 2×2 和過濾器的且步幅為 2 的最大池化的例子


池化層還有其他選擇,比如平均池化(average pooling)和 L2-norm 池化 。這一層背後的直觀推理是:一旦我們知道了原始輸入(這裡會有一個高啟用值)中一個特定的特徵,它與其它特徵的相對位置就比它的絕對位置更重要。可想而知,這一層大幅減小了輸入卷的空間維度(長度和寬度改變了,但深度沒變)。這到達了兩個主要目的。第一個是權重引數的數目減少到了75%,因此降低了計算成本。第二是它可以控制過擬合(overfitting)。這個術語是指一個模型與訓練樣本太過匹配了,以至於用於驗證和檢測組時無法產生出好的結果。出現過擬合的表現是一個模型在訓練集能達到 100% 或 99% 的準確度,而在測試資料上卻只有50%。


Dropout 層


如今,Dropout 層在神經網路有了非常明確的功能。上一節,我們討論了經過訓練後的過擬合問題:訓練之後,神經網路的權重與訓練樣本太過匹配以至於在處理新樣本的時候表現平平。Dropout 的概念在本質上非常簡單。Dropout 層將「丟棄(drop out)」該層中一個隨機的啟用引數集,即在前向通過(forward pass)中將這些啟用引數集設定為 0。簡單如斯。既然如此,這些簡單而且似乎不必要且有些反常的過程的好處是什麼?在某種程度上,這種機制強制網路變得更加冗餘。這裡的意思是:該網路將能夠為特定的樣本提供合適的分類或輸出,即使一些啟用引數被丟棄。此機制將保證神經網路不會對訓練樣本「過於匹配」,這將幫助緩解過擬合問題。另外,Dropout 層只能在訓練中使用,而不能用於測試過程,這是很重要的一點。


  • 參考 Geoffrey Hinton 的論文:Dropout: A Simple Way to Prevent Neural Networks from Overfitting


網路層中的網路


網路層中的網路指的是一個使用了 1 x 1 尺寸的過濾器的卷積層。現在,匆匆一瞥,你或許會好奇為何這種感受野大於它們所對映空間的網路層竟然會有幫助。然而,我們必須謹記 1x1 的卷積層跨越了特定深度,所以我們可以設想一個1 x 1 x N 的卷積層,此處 N 代表該層應用的過濾器數量。該層有效地使用 N 維陣列元素依次相乘的乘法,此時 N 代表的是該層的輸入的深度。


  • 參閱 Min Lin 的論文:Network In Network


分類、定位、檢測、分割


本系列第一部分使用的案例中,我們觀察了影象分類任務。這個過程是:獲取輸入圖片,輸出一套分類的類數(class number)。然而當我們執行類似目標定位的任務時,我們要做的不只是生成一個類標籤,而是生成一個描述圖片中物體suo所在位置的邊界框。

<img src="https://pic2.zhimg.com/50/v2-53c1e0def4fdc2119fd13f2656234ef7_hd.jpg" data-rawwidth="640" data-rawheight="257" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic2.zhimg.com/v2-53c1e0def4fdc2119fd13f2656234ef7_r.jpg">

我們也有目標檢測的任務,這需要圖片上所有目標的定位任務都已完成。


因此,你將獲得多個邊界框和多個類標籤。


最終,我們將執行目標分割的任務:我們需要輸出類標籤的同時輸出圖片中每個目標的輪廓。


<img src="https://pic4.zhimg.com/50/v2-24822a554ee977795e0d0ab22eaa0ff2_hd.jpg" data-rawwidth="640" data-rawheight="250" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic4.zhimg.com/v2-24822a554ee977795e0d0ab22eaa0ff2_r.jpg">

關於目標檢測、定位、分割的論文有很多,這裡就不一一列出了。


遷移學習


如今,深度學習領域一個常見的誤解在於沒有谷歌那樣的巨量資料,你將沒有希望建立一個有效的深度學習模型。儘管資料是建立網路中至關重要的部分,遷移學習的思路將幫助我們降低資料需求。遷移學習指的是利用預訓練模型(神經網路的權重和引數都已經被其他人利用更大規模的資料集訓練好了)並用自己的資料集將模型「微調」的過程。這種思路中預訓練模型扮演著特徵提取器的角色。你將移除網路的最後一層並用你自有的分類器置換(取決於你的問題空間)。然後凍結其他所有層的權重並正常訓練該網路(凍結這些層意味著在梯度下降/最優化過程中保持權值不變)。


讓我們探討一下為什麼做這項工作。比如說我們正在討論的這個預訓練模型是在 ImageNet (一個包含一千多個分類,一千四百萬張影象的資料集)上訓練的 。當我們思考神經網路的較低層時,我們知道它們將檢測類似曲線和邊緣這樣的特徵。現在,除非你有一個極為獨特的問題空間和資料集,你的神經網路也會檢測曲線和邊緣這些特徵。相比通過隨機初始化權重訓練整個網路,我們可以利用預訓練模型的權重(並凍結)聚焦於更重要的層(更高層)進行訓練。如果你的資料集不同於 ImageNet 這樣的資料集,你必須訓練更多的層級而只凍結一些低層的網路。


  • Yoshua Bengio (另外一個深度學習先驅 )論文:How transferable are features in deep neural networks?

  • Ali Sharif Razavian 論文:CNN Features off-the-shelf: an Astounding Baseline for Recognition

  • Jeff Donahue 論文:DeCAF: A Deep Convolutional Activation Feature for Generic Visual Recognition


資料增強技術


現在我們對卷積網路中資料的重要性可能已經感到有些麻木了,所以我們來談下如何利用一些簡單的轉換方法將你現有的資料集變得更大。正如我們之前所提及的,當計算機將圖片當作輸入時,它將用一個包含一列畫素值的陣列描述(這幅圖)。若是圖片左移一個畫素。對你和我來說,這種變化是微不可察的。然而對計算機而已,這種變化非常顯著:這幅圖的類別和標籤保持不變,陣列卻變化了。這種改變訓練資料的陣列表徵而保持標籤不變的方法被稱作資料增強技術。這是一種人工擴充套件資料集的方法。人們經常使用的增強方法包括灰度變化、水平翻轉、垂直翻轉、隨機編組、色值跳變、翻譯、旋轉等其他多種方法。通過利用這些訓練資料的轉換方法,你將獲得兩倍甚至三倍於原資料的訓練樣本。