1. 程式人生 > >你看到的最直白清晰的CNN講解(轉載)

你看到的最直白清晰的CNN講解(轉載)

0?wx_fmt=gif&wxfrom=5&wx_lazy=1

 向AI轉型的程式設計師都關注了這個號???


大資料探勘DT資料分析  公眾號: datadw


這篇部落格介紹的是深度神經網路中常用在影象處理的模型——卷積神經網路(CNN),CNN在影象分類中(如kaggle的貓狗大戰)大顯身手。這篇部落格將帶你瞭解影象在計算機中是如何儲存的,什麼是卷積,卷積神經網路的四個重要環節(區域性感知、引數共享、多卷積核、池化),不會涉及複雜的公式。


計算機是怎麼儲存圖片的


為了更好的理解計算機對圖片的儲存,我找了一個非常簡單的圖片,是一個385*385(畫素)的jpg格式的圖片,如圖1所示,這個圖片就是一個白色為底色,數字為黑色的數字“2”,也就是說,圖片中只涉及兩種顏色——黑與白(實際上並不是,因為圖片在顯示器中顯示是一個畫素一個畫素的,黑白相間的地方其實並不是純黑或者純白的,將圖片經過稍後描述的處理後也可以看出來,不過簡單起見,我們就當它是黑白兩色的)。


640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1


圖1


可以使用scipy包中的imread函式將圖片轉換為數值型矩陣


  
  1. from scipy.misc import imread import pandas as pd
  2. img = imread( '2.jpg')
  3. print(img.shape)
  4. img_df=pd.DataFrame(img)
  5. img_df.to_csv( '2.csv')


上面的程式碼不用太過研究,能實現這個過程的方法很多。其實圖片在計算機中就是數字,385*385=148225,圖片中有148225個數字,每個數字其實就是該畫素的顏色對應的數值(如白色是255),那麼我們來看一下圖片轉換成為的矩陣是什麼樣子,如圖2所示(我把csv按比例縮放了一下,看的比較清楚)。


0?wx_fmt=png


圖2


是不是驚豔到了!!!原來這個2在計算機中是這麼儲存的,好,我把區域性放大一下,如圖3所示,圖3這個區域放大了,所以你可能看不太出來這是個啥,其實就是圖4中紅色圓圈的部分。


0?wx_fmt=png


圖3



0?wx_fmt=png


圖4


現在你可能明白了,其實每個圖片都由若干畫素點構成,每個畫素點儲存了該位置的顏色,其實還隱藏儲存了另一個資訊,就是位置。每一個畫素點都有一對索引元組,例如(1,1)就是第一行第一列的畫素點,如果寫作(1,1,255),就是說第一行第一列的畫素點是黑色,以此類推,也就是這樣一個矩陣就完整的記錄著圖片的所有資訊。



好,到了這裡,聰明的你應該已經知道圖片在計算機中的儲存方式了。那麼正式開始講解CNN。


卷及神經網路

卷積

在開篇的部分,先簡單給大家介紹一下什麼叫做卷積,學過概率論的同學一定不陌生,那麼白話解釋一下啥叫卷積,很形象,就是“卷”,你假象一下,你把擦臉毛巾捲起來,成為一個圓柱體的卷,就是這個意思,抽象的說,就是將原來的物件變小一些,但又能保證原來影象中的資訊儘量多的保留下來,可以看看下面這個卷積過程圖。後面會有針對CNN卷積過程的詳細解釋,看看這個圖,大概理解卷積是一個什麼樣子的過程就可以了,用對映兩個字我認為是比較恰當的。

0?wx_fmt=gif


卷積過程圖


影象到神經網路

這裡的全部講解基於大家瞭解了最簡單的感知機,單層神經網路,多隱藏層神經網路的結構和引數估計方法(反向傳播演算法,具體可參見我部落格中轉載的文章《一文弄懂神經網路中的反向傳播法——BackPropagation》)


為了更簡單的理解CNN,我們先關注多隱藏層的輸入層和第一個隱藏層(其實後面層數有多少都無所謂,一模一樣的模式,大家假裝CNN就是個單隱藏層的神經網路就好,不然多隱藏層畫起來也麻煩,講起來也麻煩)。網路結構如圖6所示。


0?wx_fmt=png


圖5


這裡,選取了兩張比較直觀和經典的圖來展示個大家,如圖6所示。
0?wx_fmt=jpeg

圖6


現實中的圖片可沒有我例子這麼簡單,將它存成矩陣恐怕各位也看不出來他是個什麼鬼,除非你能把每個位置的數字在腦海中腦部成顏色,然後將數萬甚至數百萬的畫素粒按照矩陣在腦海中拼湊在一起。


好,我們關注圖6的左圖。假設我們輸入的圖片是1000*1000維的影象,在影象處理中,通常不使用這樣的二維形式儲存,而是將後一行拼接到前一行的最後,構成一個向量,對於這個1000*1000的影象,就構成了一個1×1000000,即長度一百萬的一個數組,換句話說,神經網路的輸入層(圖5最左側)有1000000個元素,假設(第一個)隱藏層,即圖5中間的層的神經元個數與輸入層相同,也是1000000,且輸入層與第一隱藏層是全連線的,如圖6中左圖所示,那麼我們就需要訓練一個 個引數,及圖5的輸入層和隱藏層之間有1萬億個連線線,這樣去進行訓練,哪怕對計算機而言,都無疑是個災難。


第一法寶:區域性感知

現在我們優化一下,假設圖5的隱藏層中的每個神經元只與輸入層的10*10個輸入(即10*10個畫素點)相連,(也就意味著每個隱藏層神經元不是和圖片的全部畫素都連線,而只是和圖片的某一個區域的全部畫素連線),那麼兩層之間連線線的個數,即引數的個數就變成了 個,比起原來的個引數,已經縮小了10000倍,但引數還是太多了,需要進一步的優化。


第二法寶:引數共享(以及卷積過程講解)

既然引數太多了,每個神經元對應了100個引數,每個神經元對應的100個引數我們姑且叫它 引數組,我們就會有 這些引數組,假設,也就是說每個神經元對應的引數組是相同的,那麼我們其實就只有一個含有100個未知引數的引數組,瞬間,引數數量就成為了100,是一個可以輕易進行訓練的數量級。


你可能要問,這樣的假設合理麼,答案是:從理論和思想上來說,是合理的,從實踐結果的證明來看,是非常好的。這個假設意味著什麼呢?這100個引數(就是卷積操作)是一種特徵提取,該方式與位置無關。這其中隱含的原理則是:影象的一部分的統計特性與其他部分是一樣的。這也意味著我們在這一部分學習的特徵也能用在另一部分上,所以對於這個影象上的所有位置,我們都能使用同樣的學習特徵。再說白一點兒,一張圖片,左半邊和右半邊的特點,風格一般情況下是一樣的,哪怕畢加索這種抽象派大師,喜歡畫左右臉不一樣的抽象人物,其左右臉的風格也是相同的,找一個畢加索的畫作,讓你看,你可能一眼就看出來作者十有八九是畢加索,遮住圖片的左側,你可能也比較確認是畢加索的畫作,遮住右邊也是一樣的,這個說法不太嚴謹,這個“風格”其實就是影象中的各種統計特徵(影象程式設計了數值,那麼任何位置都會有一些統計指標,比如極值,均值等)。


這個10*10的引數矩陣,就是所謂的卷積核!!!


卷積的過程可以參考圖7所示(動圖來源於http://www.cnblogs.com/nsnow/p/4562308.html ,不要怪我懶,我是真的不太擅長搞一些特別清楚明白的動圖,所以只能看到好的就拿過來借鑑一下)。


0?wx_fmt=gif


圖7


我來詳細解釋一下,圖7的左圖是一個5*5的圖片,轉換為了其對應的畫素矩陣。圖7右側是一個使用3*3的卷積核進行卷積後得到的結果,卷積核心作用在影象上的過程是這樣的:用一個3*3的視窗去挨個遍歷左圖的5*5的矩陣,可以得到9個3*3的矩陣(這個理解吧,小學生應該也能算出來),用這9個矩陣分別與圖7右側的卷積核做對應相乘再求和,就是卷積。打個比方,左圖第一個3*3矩陣應當為


假設我們的卷積核就是圖7左圖中給出的卷積核(圖7每個小方塊右下角的元素構成的軍鎮就是卷積核),即:


矩陣(1)與卷積核進行對應元素相乘再求和,即:,因此圖7右側左上角的元素即為4,依次類推,得到了一個3*3的對映結果。也就是說,假設我的影象是M*M維的,而卷積核是N維的,那麼卷積操作後會得到一個(M-N+1)*(M-N+1)的矩陣。


有人又要問了,這個卷積核怎麼定呢?
CNN的目的就是通過反向傳播演算法,訓練出最好的卷積核,這個卷積核就是我們的引數。 


初始的卷積核可以使用平均矩陣,對於一個3*3的卷積核而言,大可使用(3)中的矩陣:


好了,引數已經優化到了很成功的量級,接下來,還有什麼可以優化的麼?


第三法寶:多核卷積

上面所述只有一個10*10的卷積核,有100個引數,顯然,特徵提取是不充分的,我們可以新增多個卷積核,比如32個卷積核,可以學習32種特徵。在有多個卷積核時,如圖8右側所示:

0?wx_fmt=jpeg


圖8


每一個區域性感知野不止像圖8左側那樣,只由一個卷積核進行卷積操作,而是對應多個。這個過對應到網路可能比較難想想,我也想了很久怎麼能把這個過程展示清楚,所以想引用LeCun的LeNet-5網路結構,即圖9所示的網路結構來給大家看看。看圖9左起第二個層,裡面有很多個正方形(即矩陣,每個矩陣都是通過不同卷積核進行卷積後得到的結果),也就是說這個隱藏層是有“厚度”的,一個卷積核就可以得到一個正方形,6個卷積和就得到6個正方形,構成了一個有厚度的層,這裡的結構大家把它想成3D立體的,有厚度這個概念,就可能好理解一些了。


這樣,通過多個卷積核的操作,對影象的特徵提取就更加充分了。


0?wx_fmt=jpeg


圖9


第四法寶:池化-Down-pooling(下采樣)

有時影象太大,即使我們引數不太多,但影象的畫素實在太多,導致卷積操作後,我們得到的結果(圖9中左起第二個層中的每一個正方形中的元素數量太多)仍然過大。我們需要減少訓練引數的數量,它被要求在隨後的卷積層之間週期性地引進池化層。池化的一個目的是減少影象的空間大小。池化在每一個縱深維度上獨自完成,因此影象的縱深保持不變。池化層的最常見形式是最大池化。


還有一個目的是保持平移不變性。 卷積對輸入有平移不變性,池化對特徵有平移不變性。平移不變性是什麼呢?因為卷積核是在輸入圖或者feature maps上滑動,或者說平移,每次平移時,因此假設使用max pooling,會過濾掉那些不明顯、未被啟用的特徵。


深度學習,自然有多個隱藏層,對應到CNN中,就是有多個卷積層,且有多個卷積核,那麼原始影象的過大會導致卷積後的結果過大。其實我們可以對卷積後的結果進行一個縮小的過程,使下一次卷積更加輕鬆。這個縮小過程就是池化。


為了解決這個問題,首先回憶一下,我們之所以決定使用卷積後的特徵是因為影象具有一種“靜態性”的屬性,這也就意味著在一個影象區域有用的特徵極有可能在另一個區域同樣適用。因此,為了描述大的影象,一個很自然的想法就是對不同位置的特徵進行聚合統計,例如,人們可以計算影象一個區域上的某個特定特徵的平均值 (或最大值)。這些概要統計特徵不僅具有低得多的維度 (相比使用所有提取得到的特徵),同時還會改善結果(不容易過擬合)。這種聚合的操作就叫做池化 (pooling),有時也稱為平均池化或者最大池化 (取決於計算池化的方法)。


池化的過程如圖10所示。


0?wx_fmt=png


圖10


在這裡,我們把步幅定為 2,池化尺寸也為 2。也就是對圖10左側4*4的矩陣,用一個2*2的視窗去以2為步長去遍歷,再直觀的說,我們按照橫向和縱向兩條中軸線將他切成4個2*2的矩陣,然後取每個矩陣的最大值,作為池化後的結果,就得到了圖10右側的池化結果。最大化執行也應用在每個卷機輸出的深度尺寸中。正如你所看到的,最大池化操作後,4*4 卷積的輸出變成了 2*2。

除去最大池化,有平均池化,L2池化等等。


輸出

其實深層的CNN和上述過程一樣,首先有輸入層A,初始化一個卷積核,然後進行卷積,得到了第一個卷積層B(如果有i個卷積核,就會在同一層中得到),然後進行池化,得到一個池化層C(),然後進行下一次卷積。。。一個卷積層,一個池化層,重複下去,假如是做分類任務,那麼當層數到達了我們指定的層數,然後到達了輸出層,CNN

中的輸出層是全連線層,其中來自其他層的輸入在這裡被平化和傳送,以便將輸出轉換為網路所需的引數。通過前向傳播過程到達label,然後進行反向傳播,進行引數的計算。


再多說一些

之前說的多個卷積核,必然得到多個輸出,這些輸出就是一個個的矩陣,而這個矩陣本身其實也是圖片(就像原始影象一樣),這些圖片叫做feature
maps,由於feature maps
是由不同卷積和得到的,卷積和是一種特徵提取,與輸入的影象進行卷積後,相當於再做“啟用”動作,啟用後得到的feature maps
就是具有對應卷積核特徵的圖片,卷積核其實就是濾波器,符合我特徵的,啟用,不符合的,死著呆著,換做另一個卷積核,可能之前被啟用的這次就沒有,而之前死的這次被激活了,所以feature
maps
是被卷積核過濾出來的具有不同特徵的圖片,最後的輸出層就是彙總了這些特徵的圖片,也就是說,到達輸出層這裡的圖片,具有前面每個卷積核的特徵,或者可以理解為,到達輸出層的圖片是輸入圖片的最明顯的特徵的集合體,就像人類對一個圖片做判斷,一個小狗在草地上,另一個圖片是一個小貓在水裡,那麼你判斷圖中的動物是貓還是狗,幾乎不會受到草坪或者水面的影響,而是基於圖片主體本身,或者說基於貓和狗的不同特徵,這就是CNN在模仿人類的判斷方式。


本文參考了以下地址的講解,萬分感謝:
1. http://www.cnblogs.com/nsnow/p/4562308.html
2. https://www.zhihu.com/question/39022858 
3. http://blog.csdn.net/u014365862/article/details/54865609
4. http://blog.csdn.net/hjimce/article/details/47323463

via https://www.zhihu.com/question/39022858


人工智慧大資料與深度學習

搜尋新增微信公眾號:weic2c

640?wx_fmt=png

長按圖片,識別二維碼,點關注



大資料探勘DT資料分析

搜尋新增微信公眾號:datadw


教你機器學習,教你資料探勘

640?wx_fmt=jpeg

長按圖片,識別二維碼,點關注