1. 程式人生 > >多通道(比方RGB三通道)卷積過程

多通道(比方RGB三通道)卷積過程

borde caff 一個 特征 結構 load 核數 alt log

今天一個同學問 卷積過程好像是對 一個通道的圖像進行卷積, 比方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 的代碼也好理解了

技術分享

技術分享

多通道(比方RGB三通道)卷積過程