卷積神經網路視覺化:以Keras處理貓圖片為例
眾所周知,在過去幾年裡,深度學習領域裡的很多主要突破都來源於卷積神經網路(CNN 或者 ConvNet),但對大多數人來說卷積神經網路是一個非常不直觀的推斷過程。我一直想剖析卷積神經網路的各個部分,看看它在每個階段的影象處理結果是怎樣的,而本篇文章就是我的方法簡述。
從高層來看卷積神經網路
首先,卷積神經網路擅長幹什麼?卷積神經網路主要被用來尋找影象中的特徵。你可以通過卷積一幅影象來尋找這些特徵。卷積神經網路的前幾層能夠識別線和角,而後隨著我們把神經網路做得更深(層更多),我們能把這些特徵在神經網路裡繼續傳遞下去,並在神經網路的高層開始識別更復雜的特徵。卷積神經網路的這個特性使得它非常擅長影象中的物體識別。
什麼是卷積神經網路?
卷積神經網路是一個通常包含幾種不同型別層的神經網路,它裡面每一層是卷積層、或者池化(Pooling)層、或者啟用層,三者之一。
卷積層
為了理解卷積神經網路是什麼,你需要理解卷積是如何工作的。想象一下,你有一個由 5x5 的矩陣陣列表示的影象,而你有一個 3x3 大小的矩陣,沿著影象滑動這個 3x3 的矩形窗。在 3x3 窗所訪問的每個位置,會把當前視窗所覆蓋的影象畫素值與 3x3 矩形窗中的值進行矩陣乘。這個矩陣乘得到了一個數值,它用來代表影象中那個視窗覆蓋下的所有值。為了明晰這個過程,這裡有一個非常好的 gif 圖:
正如你所看到的,特徵矩陣中的每一項對應影象中的一個區域。(注意:核矩陣的值是 gif 圖角落裡的紅色數字。)
那個「訪問」完整張影象的「視窗」被稱為核(kernel)。核通常是正方形的,而且對於小型影象來說,3x3 是一個相當常見的核尺寸。視窗每次滑動的距離被稱為步長(stride)。需要額外說明的是,在做卷積時有時需要在影象的邊界外附上一圈零值,用來抑制影象邊緣的卷積值(其基本想法是一般情況下的影象中間部分更為重要)。
卷積層的目的是用來濾波。當我們遍歷影象時,我們能有效的檢視相應影象區域的特徵。之所以能做到這一點是因為濾波器,以及許多組成向量的權重值,這些權重值是由卷積的輸出結果相乘而來的。當訓練一幅影象時,這些權重值會發生變化,所以當到了真實場景中去評估一幅影象時,如果神經網路認為它「看」到了一個以前「看」到過的特徵,那麼這些權重將會被賦予高值。從各種濾波器得到的這些高權值的組合會使網路能夠預測影象的內容。這就是為什麼在卷積神經網路結構圖中,卷積這步是用一個盒子表示的而不是一個矩形;第三維代表的是濾波器。
AlexNet 的架構
需要注意:
-
卷積的輸出(長和寬)小於原始影象
-
核與核下面的影象視窗之間做的是一種線性函式運算
-
濾波器的權值可以通過「看」很多影象來學習得到
池化(pooling)層
池化的操作很像卷積,它們都是採用一個核來遍歷整個影象,唯一的不同是用於計算核和影象視窗值的函式不是線性的。
最大池化和平均池化是兩種最常用的池化函式。最大池化取當前核覆蓋視窗下的影象最大值,而平均池化取核覆蓋視窗下對應所有影象值的平均值。
啟用層
卷積神經網路中啟用層的工作方式與啟用層在其他神經網路中的工作過程是完全一致的,即一個值通過函式處理後都被「壓縮」到一個特定範圍內。這裡是一些常用的啟用函式:
在卷積神經網路中最常用的啟用函式是 ReLU(修正線性單元)。人們喜歡用 ReLU 出於很多種原因,其中最大原因是因為執行起來開銷很小,如果當前的數為負:輸出值 0;其他情況:輸出值為這個數本身。開銷低使得它能更快的訓練網路。
扼要重述
-
卷積神經網路三種主要層的型別:卷積(Convolutional)、池化(Pooling)、啟用(Activation)
-
卷積層將影象視窗與核值相乘,隨著時間的推移使用梯度下降來優化核權重
-
池化層使用影象在核視窗下的最大值或平均值來描述該影象的視窗
-
啟用層將核值限定在某個範圍內,通常範圍是 [0,1] 或 [-1,1]
卷積神經網路看起來是什麼樣的?
在我們進入主題之前,先來了解一些相關背景。第一個成功的 CNN 應用由 Yann LeCun 於 90 年代實現,他創造了一種叫做 LeNet 的網路,可用於閱讀手寫數字。從那時起,計算方面的進展以及 GPU 的強大效能助長了研究人員的雄心壯志。2010 年,斯坦福視覺實驗室(Stanford Vision Lab)釋出了 ImageNet 資料集——包含有 1400 萬張帶有詳細資訊標籤的影象。這個資料集已成為研究領域中用於比較 CNN 模型的標準之一,而當前世界上最好的模型可以成功檢測資料集中 94% 以上的影象。時不時的經常有新模型出現並在檢測結果上打敗以往的高分模型而且這是一件很了不起的事。2014 年是 GoogLeNet 和 VGGNet,在這之前是 ZF Net。應用於 ImageNet 的第一個切實可行 的 CNN 例項是 2012 年的 AlexNet,在此之前,研究人員嘗試在 ImageNet 上使用傳統的計算機視覺技術,AlexNet 的表現優於之前所有出現過的技術大約 15 個百分點。
不管怎麼說,來看看 LeNet 的結構:
LeNet 架構
這張圖表並沒有顯示啟用函式,不過整體架構是這樣的:
輸入圖片→卷積層→啟用函式(ReLU)→最大池化(MaxPooling)→卷積層→啟用函式(ReLU)→最大池化→隱藏層→Softmax(啟用)→輸出層
識別貓的時候到了!
這是一張貓的圖片:
我們這張貓咪圖片有 320 畫素高、400 畫素寬,RGB 三色通道模式
卷積層
那麼它在經過一層卷積後看起來是什麼樣的?
經過一次卷積之後貓的圖片
遍歷這張貓圖片的核尺寸為 3x3,有 3 個過濾器(如果超過 3 個過濾器則我們就不能繪製貓咪的 2D 影象。高維度的貓咪處理起來異常棘手。)。
這張貓咪影象看起來非常嘈雜,因為所有權重都是隨機初始化的,而且我們還沒有訓練網路。再者它們彼此向上堆疊,因此即使每一層包含有詳細資訊我們也無法看到。不過我們可以找出影象中與貓眼睛顏色相同的區域以及背景顏色相同的區域。如果我們將核增大至 10x10 會發生什麼?
從上圖可以看出,由於核過大,我們失去了一些細節。我們還注意到,影象形狀由於更大的核而變得稍小,而這些東西是由數學計算所控制。
如果我們把它縮小一點,顏色通道會看起來好點嗎?
好多了!現在我們可以看到一些濾波器所「看到」的東西。看起來紅色似乎真的很喜歡那一點黑色的鼻子和眼睛,而藍色是在挖掘勾勒貓咪外形的淺灰色部分。我們可以開始看到層是如何捕捉照片中一些更重要細節的。
3x3 核的卷積貓
原圖
15x15 畫素的核
現在如果我們顯著增大核尺寸,我們得到的影象細節就更少,而影象尺寸也比其他兩幅更小了。
新增一個啟用層
經過 ReLU 函式之後貓的圖片
通過新增 ReLU 啟用函式,我們去掉了許多非藍色區。
新增一個池化層
我們添加了一個池化層(用最大池化是為了更易於顯示出池化後的圖片效果並去掉上一步的啟用函式 ReLU)
池大小 2x2
如所期望的那樣,貓圖片色塊化了,不過我們還能做出更色塊化的圖片!
池大小 5x5 的貓池化圖片。你的所有池化都屬於我們
注意現在的影象大小是如何變成原始大小的三分之一的。
啟用(Activation)與最大池化(MaxPooling)
LeNet 模型處理的貓圖片
如果我們將貓圖片經由 LeNet 中卷積與池化部分處理,處理後的貓圖片看起來會是怎樣的?
每個卷積層有 1 個過濾器
第一個卷積層有 3 個過濾器,第二個卷積層有 1 個過濾器
每個卷積層有 3 個過濾器
總結
鑑於卷積神經網路(ConvNet)能夠提取影象的核心特徵,並使用這些特徵來識別包含類似特徵的影象,因而十分強大。進一步通過我們後面的兩個 CNN 範例,我們也可以看到該網路對諸如貓的鬍鬚、鼻子和眼睛之類的區域關注較多。正是這些型別的特徵將使得 CNN 能夠將貓同鳥區分出來。
CNN 相當強大,儘管這些視覺化效果並不完美,但是我希望它們能更好地幫助到像我一樣仍然在學習 CNN 原理的人。
延伸資源
A guide to convolution arithmetic for deep learning by Vincent Dumoulin and Francesco Visin (https://arxiv.org/pdf/1603.07285v1.pdf)