在笔者的上一篇博客中,解析caffe的卷积层时,在conv_layer.cpp中有一个卷积核膨胀操作,在conv_layer.cpp的第17行有如下代码
const int kernel_extent = dilation_data[i] * (kernel_shape_data[i] - 1) + 1;
上面的代码描述了卷积核的膨胀操作,我们不妨来做个假设,卷积核为3*3的,膨胀系数为2,那么,卷积核膨胀之后,卷积核的单边尺寸就变成了2*(3-1)+1,即卷积核的尺寸变成了5*5,笔者在最初看到这一行代码的时候相当疑惑,不太明白卷积核由3*3变成5*5是怎么操作的,这个时候,caffe.proto就起了作用,我们打开caffe.proto,找到卷积层的参数定义,在message ConvolutionParameter中,找到关于dilation的定义如下
// Factor used to dilate the kernel, (implicitly) zero-filling the resulting
// holes. (Kernel dilation is sometimes referred to by its use in the
// algorithme à trous from Holschneider et al. 1987.)
repeated uint32 dilation = 18; // The dilation; defaults to 1
在caffe.proto中,阐述了卷积核膨胀的使用情景,即在à trous算法中,这是一个有关小波分析的算法。卷积核膨胀是将卷积核扩张到膨胀尺度约束的尺度中,并将原卷积核没有占用的区域填充零,为了使说明更加形象,下面笔者绘制卷积核膨胀示意图为大家解析一下卷积核膨胀操作:
在上面的示意图中,卷积核由3*3膨胀到了5*5,读者朋友们可以看到,膨胀后的卷积核中填充了一些0,读者朋友们可以试着画出其他尺寸的卷积核搭配不同膨胀系数的膨胀效果,而具体的膨胀操作是在img2col中实现的,img2col.cpp笔者将在后话解析。
下面笔者分析一下膨胀系数与卷积核膨胀的关系,首先回到卷积核膨胀公式:
膨胀的卷积核尺寸 = 膨胀系数 * (原始卷积核尺寸 - 1) + 1
首先由于卷积的操作特性,卷积核尺寸是奇数,则原始卷积核尺寸减一为偶数。那么,在上述公式中,膨胀系数*偶数-1为奇数,保证了膨胀的卷积核尺寸为奇数。其次,笔者认为,卷积核的膨胀系数刻画了卷积核高和宽方向的扩张倍数,可将上述公式看作:
膨胀的卷积核尺寸 - 1 = 膨胀系数 * (原始卷积核尺寸 - 1)
到此为止,卷积核膨胀就解析完毕了,通过对卷积核膨胀的理解,笔者感受到,在阅读源码不明白时,尤其在对卷积这种抽象的操作中的细节不明白时,可以动笔画一画,将不形象转为形象,问题就迎刃而解了!
在下一篇博客中,笔者打算解析一下caffe中卷积层实现必不可少的的im2col_cpu和col2im_cpu函数,作为caffe卷积层解析的尾声。
欢迎阅读笔者后续解析caffe源码的博客,各位读者朋友的支持与鼓励是我最大的动力!
---------------------
作者:jiongnima
来源:CSDN
原文:https://blog.csdn.net/jiongnima/article/details/69487519
版权声明:本文为博主原创文章,转载请附上博文链接!