圖解CNN:通過100張圖一步步理解CNN

v_JULY_v發表於2018-03-06

圖解CNN:通過100張圖一步步理解CNN


作者:@Brandon Rohrer,連結:http://brohrer.github.io/how_convolutional_neural_networks_work.html
譯者:@zhwhong,連結:https://www.jianshu.com/p/fe428f0b32c1

說明:本文被收錄於七月線上APP 大題檢視 深度學習第35題。本質上來講,我那篇CNN筆記,基本做到非CS專業生也能秒懂CNN。但本文更厲害,可能看過CNN無數資料,皆不如此文好懂。



當你聽到說深度學習打破了某項新技術障礙,那麼十有八九就會涉及到卷積神經網路。它們也被稱作CNNs或著ConvNets,是深層神經網路領域的主力。它們已經學會對影象進行分類,在某些情況下甚至超過了人類。如果有一個方法證明了這種假設,那就是CNN。

特別酷的一點就是,當你將它們分解為基本模組時,它們很容易被理解。這裡有一個視訊,很詳細地討論了關於這些影象問題。



LeNet-5


Classfication

先驗工作
【icml09 - Convolutional Deep Belief Networks.pdf】



【Playing Atari with Deep Reinforcement Learning】



【Robot Learning Manipulation Action Plans】




A toy ConvNet:X’s and O’s
首先,提出這樣一個問題:識別一幅圖片是包含有字母"X"還是字母"O"?

為了幫助指導你理解卷積神經網路,我們講採用一個非常簡化的例子:確定一幅影象是包含有"X"還是"O"?

這個例子足夠說明CNN背後的原理,同時它足夠簡單,能夠避免陷入不必要的細節。

在CNN中有這樣一個問題,就是每次給你一張圖,你需要判斷它是否含有"X"或者"O"。並且假設必須兩者選其一,不是"X"就是"O"。理想的情況就像下面這個樣子:

標準的"X"和"O",字母位於影象的正中央,並且比例合適,無變形

對於計算機來說,只要影象稍稍有一點變化,不是標準的,那麼要解決這個問題還是不是那麼容易的:


計算機要解決上面這個問題,一個比較天真的做法就是先儲存一張"X"和"O"的標準影象(就像前面給出的例子),然後將其他的新給出的影象來和這兩張標準影象進行對比,看看到底和哪一張圖更匹配,就判斷為哪個字母。

但是這麼做的話,其實是非常不可靠的,因為計算機還是比較死板的。在計算機的“視覺”中,一幅圖看起來就像是一個二維的畫素陣列(可以想象成一個棋盤),每一個位置對應一個數字。在我們這個例子當中,畫素值"1"代表白色,畫素值"-1"代表黑色。


當比較兩幅圖的時候,如果有任何一個畫素值不匹配,那麼這兩幅圖就不匹配,至少對於計算機來說是這樣的。

對於這個例子,計算機認為上述兩幅圖中的白色畫素除了中間的3*3的小方格里面是相同的,其他四個角上都不同:


因此,從表面上看,計算機判別右邊那幅圖不是"X",兩幅圖不同,得出結論:


但是這麼做,顯得太不合理了。理想的情況下,我們希望,對於那些僅僅只是做了一些像平移,縮放,旋轉,微變形等簡單變換的影象,計算機仍然能夠識別出圖中的"X"和"O"。就像下面這些情況,我們希望計算機依然能夠很快並且很準的識別出來:


這也就是CNN出現所要解決的問題。

Features


對於CNN來說,它是一塊一塊地來進行比對。它拿來比對的這個“小塊”我們稱之為Features(特徵)。在兩幅圖中大致相同的位置找到一些粗糙的特徵進行匹配,CNN能夠更好的看到兩幅圖的相似性,相比起傳統的整幅圖逐一比對的方法。

每一個feature就像是一個小圖(就是一個比較小的有值的二維陣列)。不同的Feature匹配影象中不同的特徵。在字母"X"的例子中,那些由對角線和交叉線組成的features基本上能夠識別出大多數"X"所具有的重要特徵。


這些features很有可能就是匹配任何含有字母"X"的圖中字母X的四個角和它的中心。那麼具體到底是怎麼匹配的呢?如下:




看到這裡是不是有了一點頭目呢。但其實這只是第一步,你知道了這些Features是怎麼在原圖上面進行匹配的。但是你還不知道在這裡面究竟進行的是怎樣的數學計算,比如這個下面3*3的小塊到底幹了什麼?

接下來就跟進介紹裡面的數學操作,也就是我們常說的“卷積”操作。

卷積(Convolution)

Convolution


當給你一張新的圖時,CNN並不能準確地知道這些features到底要匹配原圖的哪些部分,所以它會在原圖中每一個可能的位置進行嘗試。這樣在原始整幅圖上每一個位置進行匹配計算,我們相當於把這個feature變成了一個過濾器。這個我們用來匹配的過程就被稱為卷積操作,這也就是卷積神經網路名字的由來。

這個卷積操作背後的數學知識其實非常的簡單。要計算一個feature和其在原圖上對應的某一小塊的結果,只需要簡單地將兩個小塊內對應位置的畫素值進行乘法運算,然後將整個小塊內乘法運算的結果累加起來,最後再除以小塊內畫素點總個數即可。

如果兩個畫素點都是白色(也就是值均為1),那麼1*1 = 1,如果均為黑色,那麼(-1)*(-1) = 1。不管哪種情況,每一對能夠匹配上的畫素,其相乘結果為1。類似地,任何不匹配的畫素相乘結果為-1。如果一個feature(比如n*n)內部所有的畫素都和原圖中對應一小塊(n*n)匹配上了,那麼它們對應畫素值相乘再累加就等於n2,然後除以畫素點總個數n2,結果就是1。同理,如果每一個畫素都不匹配,那麼結果就是-1。

具體過程如下:









對於中間部分,也是一樣的操作:





最後整張圖算完,大概就像下面這個樣子:

然後換用其他feature進行同樣的操作,最後得到的結果就是這樣了:

為了完成我們的卷積,我們不斷地重複著上述過程,將feature和圖中每一塊進行卷積操作。最後通過每一個feature的卷積操作,我們會得到一個新的二維陣列。

這也可以理解為對原始影象進行過濾的結果,我們稱之為feature map,它是每一個feature從原始影象中提取出來的“特徵”。其中的值,越接近為1表示對應位置和feature的匹配越完整,越是接近-1,表示對應位置和feature的反面匹配越完整,而值接近0的表示對應位置沒有任何匹配或者說沒有什麼關聯。

這樣我們的原始圖,經過不同feature的卷積操作就變成了一系列的feature map。我們可以很方便,直觀地將這整個操作視為一個單獨的處理過程。在CNN中,我們稱之為卷積層(convolution layer),這樣你可能很快就會想到後面肯定還有其他的layer。沒錯,後面會提到。

我們可以將卷積層看成下面這個樣子:

因此可想而知,CNN其實做的操作也沒什麼複雜的。但是儘管我們能夠以這一點篇幅就描述了CNN的工作,其內部的加法,乘法和除法操作的次數其實會增加地很快。從數學的角度來說,它們會隨著影象的大小,每一個filter的大小和filter的數目呈線性增長。由於有這麼多因素的影響,很容易使得這個問題的計算量變得相當的龐大,這也難怪很多微處理器製造商現在都在生產製造專業的晶片來跟上CNN計算的需求。

池化(Pooling)

Pooling

CNN中使用的另一個有效的工具被稱為“池化(Pooling)”。池化可以將一幅大的影象縮小,同時又保留其中的重要資訊。池化背後的數學頂多也就是小學二年級水平。它就是將輸入影象進行縮小,減少畫素資訊,只保留重要資訊。通常情況下,池化都是2*2大小,比如對於max-pooling來說,就是取輸入影象中2*2大小的塊中的最大值,作為結果的畫素值,相當於將原始影象縮小了4倍(注:同理,對於average-pooling來說,就是取2*2大小塊的平均值作為結果的畫素值)。

對於本文的這個例子,池化操作具體如下:




不足的外面補"0":



經過最大池化操作(比如2*2大小)之後,一幅圖就縮小為原來的四分之一了:

然後對所有的feature map執行同樣的操作,得到如下結果:

因為最大池化(max-pooling)保留了每一個小塊內的最大值,所以它相當於保留了這一塊最佳的匹配結果(因為值越接近1表示匹配越好)。這也就意味著它不會具體關注視窗內到底是哪一個地方匹配了,而只關注是不是有某個地方匹配上了。這也就能夠看出,CNN能夠發現影象中是否具有某種特徵,而不用在意到底在哪裡具有這種特徵。這也就能夠幫助解決之前提到的計算機逐一畫素匹配的死板做法。

當對所有的feature map執行池化操作之後,相當於一系列輸入的大圖變成了一系列小圖。同樣地,我們可以將這整個操作看作是一個操作,這也就是CNN中的池化層(pooling layer),如下:

通過加入池化層,可以很大程度上減少計算量,降低機器負載。

Normalization
啟用函式Relu (Rectified Linear Units)
這是一個很小但是很重要的操作,叫做Relu(Rectified Linear Units),或者修正線性單元。它的數學公式也很簡單:
![][01]
[01]:http://latex.codecogs.com/png.latex?f(x) = max(0, x)

對於輸入的負值,輸出全為0,對於正值,原樣輸出。關於其功能,更多詳見這裡。

下面我們看一下本文的離例子中relu啟用函式具體操作:



最後,對整幅圖操作之後,結果如下:

同樣地,在CNN中,我們這一系列操作視為一個操作,那麼就得到Relu Layer,如下:

Deep Learning
最後,我們將上面所提到的卷積,池化,啟用放在一起,就是下面這個樣子:

然後,我們加大網路的深度,增加更多的層,就得到深度神經網路了:

然後在不同的層,我們進行視覺化,就可以看到本文開頭提到的先驗知識裡面的結果了:

全連線層(Fully connected layers)






根據結果判定為"X":


在這個過程中,我們定義這一系列操作為”全連線層“(Fully connected layers):

全連線層也能夠有很多個,如下:

【綜合上述所有結構】

這一整個過程,從前到後,被稱作”前向傳播“,得到一組輸出,然後通過反向傳播來不斷糾正錯誤,進行學習。

反向傳播 (Backpropagation)
此處數學原理可以參見:深度學習 —— 反向傳播理論推導.






Gradient Descent Optimizer


Hyperparameters

Application




Learn more

If you'd like to dig deeper into deep learning, check out my Demystifying Deep Learning post. I also recommend the notes from the Stanford CS 231 course by Justin Johnson and Andrej Karpathy that provided inspiration for this post, as well as the writings of Christopher Olah, an exceptionally clear writer on the subject of neural networks.

If you are one who loves to learn by doing, there are a number of popular deep learning tools available. Try them all! And then tell us what you think.
Caffe
CNTK
Deeplearning4j
TensorFlow
Theano
Torch
Many others

I hope you've enjoyed our walk through the neighborhood of Convolutional Neural Networks. Feel free to start up a conversation.

Brandon Rohrer
本文重點在前面的具體操作部分,所以後面的部分沒有細說,只是帶過了,如有必要,後期會逐漸完善,謝謝!

Reference:
http://brohrer.github.io/how_convolutional_neural_networks_work.html
深度學習 —— 反向傳播理論推導

相關文章