卷积运算本质上就是在滤波器和输入数据的局部区域间做点积,最直观明了的方法就是用滑窗的方式,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=,
OH = IH - KH +
OW = IW - KW + for(int ch=;ch<output.channels;ch++)
{
for(int oh=;oh<output.height;oh++)
{
for(int ow=;ow<output.width;ow++)
{
float sum=;
for(int kc=;kc<kernel.channels;kc++)
{
for(int kh=;kh<kernel.height;kh++)
{
for(int kw=;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