卷积运算本质上就是在滤波器和输入数据的局部区域间做点积,最直观明了的方法就是用滑窗的方式,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