1. 程式人生 > >CNN卷積神經網路原理的直觀理解

CNN卷積神經網路原理的直觀理解

哈哈?偶然在知乎上翻到了我旭神對CNN原理的通俗易懂的解釋,看完以後簡直醍醐灌頂呢。 下面上頭像!! 旭神標誌性的薛定諤貓 哼,趕緊記錄一下加強一下理解! 轉自知乎我旭神

如果學過數字影象處理,對於卷積核的作用應該不陌生,比如你做一個最簡單的方向濾波器,那就是一個二維卷積核,這個核其實就是一個模板,利用這個模板再通過卷積計算的定義就可以計算出一幅新的影象,新的影象會把這個卷積核所體現的特徵突出顯示出來。比如這個卷積核可以偵測水平紋理,那捲積出來的圖就是原圖水平紋理的影象。現在假設要做一個影象的分類問題,比如辨別一個影象裡是否有一隻貓,我們可以先判斷是否有貓的頭,貓的尾巴,貓的身子等等,如果這些特徵都具備,那麼我就判定這應該是一隻貓(如果用心的話你就會發現這就是CNN最後的分類層,這一部分是我們傳統的神經網路的範疇)。關鍵在於這些特徵是高階的語義特徵,這種特徵怎麼用卷積核提取呢?原來的卷積核都是人工事先定義好的,是經過演算法設計人員精心設計的,他們發現這樣或那樣的設計卷積核通過卷積運算可以突出一個什麼樣的特徵,於是就高高興興的拿去卷積了。但是現在我們所需要的這種特徵太高階了,而且隨任務的不同而不同,人工設計這樣的卷積核非常困難。於是,利用機器學習的思想,我們可以讓他自己去學習出卷積核來!也就是學習出特徵!如前所述,判斷是否是一隻貓,只有一個特徵不夠,比如僅僅有貓頭是不足的,因此需要多個高階語義特徵的組合,所以應該需要多個卷積核,這就是為什麼需要學習多個卷積核的原因。還有一個問題,那就是為什麼CNN要設計這麼多層呢?首先,應該要明白,貓的頭是一個特徵,但是對於充斥著畫素點的影象來說,用幾個卷積核直接判斷存在一個貓頭的還是太困難,怎麼辦?簡單,把貓頭也作為一個識別目標,比如貓頭應該具有更底層的一些語義特徵,比如應該有貓的眼睛、貓的耳朵、貓的鼻子等等。這些特徵有的還是太高階了,沒關係,繼續向下尋找低階特徵,一直到最低階的畫素點,這樣就構成了多層的神經網路。最好,CNN最不好理解的就要放大招了。雖然我們之前一直用一些我們人常見的語義特徵做例子,但是實際上CNN會學習出貓頭、貓尾巴、貓身然後經判定這是貓嗎?顯然我們的CNN完全不知道什麼叫貓頭、貓尾巴,也就是說,CNN不知道什麼是貓頭貓尾巴,它學習到的只是一種抽象特徵,甚至可能有些特徵在現實世界並沒有對應的名詞,但是這些特徵組合在一起計算機就會判定這是一隻貓!關於這一點,確實有些難以理解,比如一個人判斷貓是看看有沒有貓頭、貓身子、貓尾巴,但是另一個選取的特徵就是有沒有貓的毛,貓的爪子,還有的人更加奇怪,他會去通過這張影象裡是不是有老鼠去判斷,而我們的CNN,則是用它自己學習到的特徵去判斷。 —————————————————分割線————————————————————— 最近又看了一些資料,在此糾正和闡明一些問題。目前CNN的視覺化是一個很火的方向了,有些論文中已經提到了中間的卷積層特徵其實也是具有現實的語義意義的,但是隻是不那麼清晰。CNN稱之為深度學習,要義就在這個深字上,對於CNN而言,這個深其實就是意味著層層的特徵表示。比如淺層的特徵,例如點、線、面之類的簡單幾何形狀,都是在底層訓練出來的,對於這些底層的特徵繼續進行組合表示,就是後面的若干層的任務。最後把從低階特徵組合而來的高階特徵在進一步變成語義特徵,就可以使用全連線層進行分類了。也就是說,最後一次分類並不一定要用神經網路,如果已經拿到了足夠好的特徵資訊,使用其餘的分類器也未嘗不可。這就是為什麼CNN可以fine-tune的原因,例如你要完成一個分類貓和狗的任務,你需要從頭訓練一個CNN網路嗎?假設你的貓狗圖片樣本量並不是很大,這並不是一個好主意。好的辦法是,拿一個經過大型影象資料集,你如ImageNet,訓練過的大規模CNN(比如VGG NET)直接載入訓練,這個過程稱之為fine-tuning。因為這個CNN底層已經訓練到了豐富的細節資訊,你所需要訓練的其實是上層對這些特徵的組合資訊,以及最後全連線層的分類資訊,所以完全不需要從頭再來。這也證明了CNN確實可以有遷移學習的能力。 ——————————————————分割線———————————————————— 之前有一點沒有說,今天沒啥事補充一下,也算是做個記錄。CNN的部件其實大致分為三個,卷積層、池化層、全連線層,這也是LeNet-5的經典結構,之後大部分CNN網路其實都是在這三個基本部件上做各種組合和改進。卷積層之前已經介紹過了,全連線層就是連在最後的分類器,是一個普通的bp網路,實際上如果訓練得到的特徵足夠好,這裡也可以選擇其他的分類器,比如SVM等。那麼池化層是幹什麼的呢?池化,英文是pooling,字面上看挺難懂,但其實這可能是CNN裡最簡單的一步了。我們可以不按字面理解,把它理解成下采樣(subsampling)。池化分為最大值池化和平均值池化,和卷積差不多,也是取一小塊區域,比如一個55的方塊,如果是最大值池化,那就選這25個畫素點最大的那個輸出,如果是平均值池化,就把25個畫素點取平均輸出。這樣做有什麼好處呢?1、應該很明顯可以看出,影象經過了下采樣尺寸縮小了,按上面的例子,原來5

5的一個區域,現在只要一個值就表示出來了!2、增強了旋轉不變性,池化操作可以看做是一種強制性的模糊策略,舉個不恰當的例子,假設一個貓的圖片,貓的耳朵應該處於左上55的一個小區域內(實際上貓的耳朵不可能這麼小),無論這個耳朵如何旋轉,經過池化之後結果都是近似的,因為就是這一塊取平均和取最大對旋轉並不care。當然和之前的卷積一樣,池化也是層層遞進的,底層的池化是在模糊底層特徵,如線條等,高層的池化模糊了高階語義特徵,如貓耳朵。所以,一般的CNN架構都是三明治一樣,卷積池化交替出現,保證提取特徵的同時也強制模糊增加特徵的旋轉不變性。 ——————————————————分割線———————————————————— 更新一下比較advantage的東西。現代CNN相比於之前的遠古CNN發生了很大變化,雖然這裡的遠古CNN大約在2014年論文中出現,距今也只有不到4年時間。這裡也可以看出深度學習的發展日新月異,一日千里的可怕速度。理解了本身CNN的基礎含義,再來看看這些先進的CNN,是很有必要的,不要指望只靠卷積層池化層就可以得到好的效果,後來加入CNN的trick不計其數,而且也都是里程碑式的成果。下面主要以影象分類的CNN來闡述。暴力加深流派:以AlexNet和VGGNet為首的模型,這一派觀點很直接,就是不斷交替使用卷積層池化層,暴力增加網路層數,最後接一下全連線層分類。這類模型在CNN早期是主流,特點是引數量大,尤其是後面的全連線層,幾乎佔了一般引數量。而且相比於後續的模型,效果也較差。因此這類模型後續慢慢銷聲匿跡了。Inception流派:谷歌流派,這一派最早起源於NIN,稱之為網路中的網路,後被谷歌發展成Inception模型(這個單詞真的不好翻譯。。。)。這個模型的特點是增加模型的寬度,使得模型不僅僅越長越高,還越長越胖。也就是說每一層不再用單一的卷積核卷積,而是用多個尺度的卷積核試試。顯然,如果你熟悉CNN,就不難發現,這樣做會使每一層的feature map數量猛增,因為一種尺寸的卷積核就能卷出一系列的feature map,何況多個!這裡google使用了1
1的卷積核專門用來降channel。谷歌的特點是一個模型不玩到爛絕不算完,所以又發展出了Inception v2、Inception v3、Inception v4等等。殘差流派:2015年ResNet橫空出世,開創了殘差網路。使用殘差直連邊跨層連線,居然得到了意想不到的好效果。最重要的是,這一改進幾乎徹底突破了層數的瓶頸,1000層的resnet不是夢!之後,最新的DenseNet喪心病狂地在各個層中間都引入了殘差連線。目前大部分模型都在嘗試引入殘差連線。注意,到此為止,大部分模型已經丟棄了全連線層,改為全域性平均池化。大大降低了引數量。混合流派:這一派不說了,就是看到哪幾類模型效果好,就把這類技術混雜起來。典型的就是Xception和ResIception,將Inception和殘差網路結合起來了。BatchNromalization:不得不提這個批量標準化技術,在此技術出現之前,CNN收斂很慢,此技術出現後,大大加快了模型收斂速度,還兼具一定的防過擬合效果。當然,這個技術不僅僅限於CNN。