卷積運算本質上就是在濾波器和輸入數據的局部區域間做點積,最直觀明了的方法就是用滑窗的方式,c++簡單實現如下:
輸入:imput[IC][IH][IW] IC = input.channels IH = input.height IW = input.width 卷積核: kernel[KC1][KC2][KH][KW] KC1 = OC KC2 = IC KH = kernel.height KW = kernel.width 輸出:output[OC][OH][OW] OC = output.channels OH = output.height OW = output.width 其中,padding = VALID,stride=1, OH = IH - KH + 1 OW = IW - KW + 1 for(int ch=0;ch<output.channels;ch++) { for(int oh=0;oh<output.height;oh++) { for(int ow=0;ow<output.width;ow++) { float sum=0; for(int kc=0;kc<kernel.channels;kc++) { for(int kh=0;kh<kernel.height;kh++) { for(int kw=0;kw<kernel.width;kw++) { sum += input[kc][oh+kh][ow+kw]*kernel[ch][kc][kh][kw]; } } } //if(bias) sum +=bias[] output[ch][oh][ow]=sum; } } }
直接用滑窗的方法計算卷積,效率比較低,因此一般把卷積操作轉換為矩陣乘法。這樣可以高效的利用優化之后的矩陣乘法,具體可以參考Caffe中的im2col的實現。
- 在上圖中, input features每一個二維矩陣對應與 RGB 圖像的 channel 或者是 feature map 中的channel。
- 目前常見的卷積都是 cross channel 的卷積, 既卷積核矩陣是 3 維的(width, height, depth), depth 的大小和feature map 的depth.(depth 就是有幾張 feature map)。
- 3維卷積核的方法與 2 維的類似, 也是與 feature map 中相應的一個 3 維的矩陣對應位置元素相乘積。然后相加,2 維的卷積相當於 depth=1 的 3 維的卷
下圖闡述了簡單的二維卷積實現,輸入圖像是3*3的RGB數據,組成12*4的矩陣,2個2*2(*3)卷積核,卷積核組成2*12的矩陣,輸出矩陣維度為2*4。
最后,將得到的2*4重新reshape成2*2*2,即可。
內容主要來自與:
https://zhuanlan.zhihu.com/p/30086163
https://blog.csdn.net/gavin__zhou/article/details/72723494
http://courses.cs.tau.ac.il/Caffe_workshop/Bootcamp/pdf_lectures/Lecture%203%20CNN%20-%20backpropagation.pdf