caffe卷積輸入通道如何到輸出通道


今天一個同學問 卷積過程好像是對 一個通道的圖像進行卷積, 比如10個卷積核,得到10個feature map, 那么輸入圖像為RGB三個通道呢,輸出就為 30個feature map 嗎, 答案肯定不是的, 輸出的個數依然是 卷積核的個數。 可以查看常用模型,比如lenet 手寫體,Alex imagenet 模型, 每一層輸出feature map 個數 就是該層卷積核的個數。

 

1、 一通道單個卷積核卷積過程

 

 

 

2、 一通道 多個卷積核卷積過程

 

 

一個卷積核得到的特征提取是不充分的,我們可以添加多個卷積核,比如32個卷積核,可以學習32種特征。在有多個卷積核時,如下圖所示:輸出就為32個feature map

卷積神經網絡

 

 

3、 多通道的多個卷積核

 

下圖展示了在四個通道上的卷積操作,有兩個卷積核,生成兩個通道。其中需要注意的是,四個通道上每個通道對應一個卷積核,先將w2忽略,只看w1,那么在w1的某位置(i,j)處的值,是由四個通道上(i,j)處的卷積結果相加然后再取激活函數值得到的。  所以最后得到兩個feature map, 即輸出層的卷積核核個數為 feature map 的個數。

卷積神經網絡

卷積神經網絡

所以,在上圖由4個通道卷積得到2個通道的過程中,參數的數目為4×2×2×2個,其中4表示4個通道,第一個2表示生成2個通道,最后的2×2表示卷積核大小。

 

下面是常見模型, 理解一下 每層feature map 個數,為上一層卷積核的個數

 

下圖即為Alex的CNN結構圖。需要注意的是,該模型采用了2-GPU並行結構,即第1、2、4、5卷積層都是將模型參數分為2部分進行訓練的。在這里,更進一步,並行結構分為數據並行與模型並行。數據並行是指在不同的GPU上,模型結構相同,但將訓練數據進行切分,分別訓練得到不同的模型,然后再將模型進行融合。而模型並行則是,將若干層的模型參數進行切分,不同的GPU上使用相同的數據進行訓練,得到的結果直接連接作為下一層的輸入。

卷積神經網絡

上圖模型的基本參數為:

輸入:224×224大小的圖片,3通道
第一層卷積:5×5大小的卷積核96個,每個GPU上48個。
第一層max-pooling:2×2的核。
第二層卷積:3×3卷積核256個,每個GPU上128個。
第二層max-pooling:2×2的核。
第三層卷積:與上一層是全連接,3*3的卷積核384個。分到兩個GPU上個192個。
第四層卷積:3×3的卷積核384個,兩個GPU各192個。該層與上一層連接沒有經過pooling層。
第五層卷積:3×3的卷積核256個,兩個GPU上個128個。
第五層max-pooling:2×2的核。
第一層全連接:4096維,將第五層max-pooling的輸出連接成為一個一維向量,作為該層的輸入。
第二層全連接:4096維
Softmax層:輸出為1000,輸出的每一維都是圖片屬於該類別的概率。

4 DeepID網絡結構

DeepID網絡結構是香港中文大學的Sun Yi開發出來用來學習人臉特征的卷積神經網絡。每張輸入的人臉被表示為160維的向量,學習到的向量經過其他模型進行分類,在人臉驗證試驗上得到了97.45%的正確率,更進一步的,原作者改進了CNN,又得到了99.15%的正確率。

如下圖所示,該結構與ImageNet的具體參數類似,所以只解釋一下不同的部分吧。

卷積神經網絡

上圖中的結構,在最后只有一層全連接層,然后就是softmax層了。論文中就是以該全連接層作為圖像的表示。在全連接層,以第四層卷積和第三層max-pooling的輸出作為全連接層的輸入,這樣可以學習到局部的和全局的特征。

 

 

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

下面講一下,caffe中的實現。

 

Caffe中的卷積計算是將卷積核矩陣和輸入圖像矩陣變換為兩個大的矩陣A與B,然后A與B進行矩陣相乘得到結果C(利用GPU進行矩陣相乘的高效性),三個矩陣的說明如下:

(1)在矩陣A中

        M為卷積核個數,K=k*k,等於卷積核大小,即第一個矩陣每行為一個卷積核向量(是將二維的卷積核轉化為一維),總共有M行,表示有M個卷積核。

(2)在矩陣B中

        N=((image_h + 2*pad_h – kernel_h)/stride_h+ 1)*((image_w +2*pad_w – kernel_w)/stride_w + 1)

        image_h:輸入圖像的高度

        image_w:輸入圖像的寬度

        pad_h:在輸入圖像的高度方向兩邊各增加pad_h個單位長度(因為有兩邊,所以乘以2)

        pad_w:在輸入圖像的寬度方向兩邊各增加pad_w個單位長度(因為有兩邊,所以乘以2)

        kernel_h:卷積核的高度

        kernel_w:卷積核的寬度

        stride_h:高度方向的滑動步長;

        stride_w:寬度方向的滑動步長。

        因此,N為輸出圖像大小的長寬乘積,也是卷積核在輸入圖像上滑動可截取的最大特征數。

        K=k*k,表示利用卷積核大小的框在輸入圖像上滑動所截取的數據大小,與卷積核大小一樣大。

(3)在矩陣C中

        矩陣C為矩陣A和矩陣B相乘的結果,得到一個M*N的矩陣,其中每行表示一個輸出圖像即feature map,共有M個輸出圖像(輸出圖像數目等於卷積核數目)

 

 (在Caffe中是使用src/caffe/util/im2col.cu中的im2col和col2im來完成矩陣的變形和還原操作)

 

 舉個例子(方便理解):

     假設有兩個卷積核為,因此M=2,kernel_h=2,kernel_w=2,K= kernel_h * kernel_w=4

     輸入圖像矩陣為,因此image_h=3,image_w=3,令邊界擴展為0即pad_h=0,pad_w=0,滑動步長為1,即stride_h=1,stride_w=1

     故N=[(3+2*0-2)/1+1]*[ (3+2*0-2)/1+1]=2*2=4

 

    A矩陣(M*K)為(一行為一個卷積核),B矩陣(K*N)為(B矩陣的每一列為一個卷積核要卷積的大小)

    A 矩陣的由來:::    

    B矩陣的由來:(caffe 有 imtocol.cpp代碼,專門用於實現) 

 

 

    C=A*B=*=

    C中的分別為兩個輸出特征圖像即feature map。驗證了 有幾個卷積核就有幾個feature map

 

    在Caffe源碼中,src/caffe/util/math_functions.cu(如果使用CPU則是src/util/math_functions.cpp)中的caffe_gpu_gemm()函數,其中有兩個矩陣A(M*K)

    與矩陣    B(K*N),大家可以通過輸出M、K、N的值即相應的矩陣內容來驗證上述的原理,代碼中的C矩陣與上述的C矩陣不一樣,代碼中的C矩陣存儲的是偏置bias,

    是A  與B相乘后得到M*N大小的矩陣,然后再跟這個存儲偏置的矩陣C相加完成卷積過程。如果是跑Mnist訓練網絡的話,可以看到第一個卷積層卷積過程中,

    M=20,K=25,N=24*24=576。

  (caffe中涉及卷積具體過程的文件主要有:src/caffe/layers/conv_layer.cu、src/caffe/layers/base_conv_layer.cpp、                src/caffe/util/math_functions.cu、src/caffe/util/im2col.cu)

    另外大家也可以參考知乎上賈揚清大神的回答,幫助理解http://www.zhihu.com/question/28385679

  (對於他給出的ppt上的C表示圖像通道個數,如果是RGB圖像則通道數為3,對應於caffe代碼中的變量為src/caffe/layers/base_conv_layer.cpp中

     函數forward_gpu_gemm中的group_)

 

賈揚清的PPT如下:

下面看這個就簡單多了, im2col.cpp 的代碼也好理解了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM