CNN叫作卷积神经网络,可见卷积在CNN的地位,写出Conv可以说万里长征迈出了第一步。汇聚层跟卷积层类似,只是卷积核内的运算不同。卷积的操作其实很简单,就是若干个for循环的嵌套。可以想象成可以想象一下卷积的过程。
0、复习一下卷积过程
假设蓝色立方体代表卷积核,大小是4*3*3,这意味着输入是4层
图1
蓝绿色立方体代表输入图像,大小是4*6*6
图2
卷积核在输入上滑动
图3
1、首先是要得到卷积核中的点与输入图像中的点的对应关系:
假设输出output[ow][oh]所对应的K*K个点中的[ww][wh],那么在输入图像中对应的点的横坐标x=ow*stride+ww-pad,同理可得纵坐标y
比如output[0][0]中的第7*7个点,那么这个点对应图像中的位置就是(7-pad,7-pad)
2、然后要根据再该层图像中的位置:
假设现在在输入的第id层卷积,那么在这之前的层就有id*width*height个点,这层在它之前的就有y*width+x-1个,所以这个点是所有输入中
的第id*width*height+y*width+x个。
3、读取权重:
与第一步类似,总共有od*id*K*K个权重,计算时将一个卷积核内的所有元素点乘加和如图3,每滑动一次产生od个数据。
图4
图4的所体现的参数:权重层数=输入层数=4,输出层数=5,卷积核大小3*3,输入大小6*6,这里没有考虑pad
之后的就简单了,读取输入相乘加和。需要注意的是如果第一步算出来的x,y有任何一个越界意味着这个点是在pad上,要赋值为0
4、关于汇聚
上一篇文章说过通常pad大小是kernel_size的一半,我在调试的时候就无视了这一点结果总是不对,后来回去翻prototxt后发现有的汇聚层是没有pad的,所以写的时候一定要检查传入参数!!!!遇到问题先别瞎猜哪里出错了,先把所有的输入输出打印出来。
5、在GNet里只有2个卷积后没有接relu,所以可以在最后加上一个判断函数,省得之后再写怪麻烦的。在这个过程中最容易出现的问题是初始化的时候因为不细心或是对基本概念不够清楚而写错传入参数,有时会导致内存访问出错。