最近,在看caffe源码时,偶然在网上看到一个问题?以为挺有意思,因而,仔细的查了相关资料,并将总结写在这里,供你们迷惑时,起到一点启示做用吧。html
问题的题目是CNN中的一个卷积层输入64个通道的特征子图,输出256个通道的特征子图,那么,该层一共包含多少个卷积核?git
对于上面这个问题,目前有两种答案,每一种答案的区别是所基于的卷积核的维度不一样而致使的。下面是两种答案的解析过程:github
第一种答案:卷积核是二维的(caffe源码中以卷积核二维转化成相应矩阵),那么就须要64*256个卷积核来对输入特征子图进行卷积,其中,输入的每一个通道对应64种不一样的卷积核进行卷积,再将64种卷积核获得的卷积结果合并成一张输出特征子图;这样,就会获得256个通道的特征子图。ide
第二种答案:卷积核是三维的(caffe大神贾杨清老师的回答中就是这么认为的),那么一个卷积核的表示为C*H*W(C:通道数,H:卷积核的高,W:卷积核宽)。那么对于输入的特征子图,就须要一个大小为64*h*w的卷积核进行卷积,获得一张特征子图。这样,就须要256个不一样卷积核,每一个卷积核的通道数为64,从而获得256个通道的特征子图。学习
显然,这两种答案都有必定的依据,无论如何认为,其最终的目的都是要将卷积层复杂的卷积问题转化为矩阵的相乘问题,从而大大的提升计算速度。spa
那么,确定有不少朋友,尤为是像我这种深度学习的菜鸟,一开始仍是比较迷糊的,对于上面的解释仍是不知所云。那么,下面,我就来对这两种观点进行具体分析,不足之处,但愿你们能指出来,共同窗习。3d
一,卷积核是二维的:orm
咱们知道,在caffe中卷积层的运算是首先经过img2col()将各个卷积核和输入特征子图转化为向量,而后多个卷积核或输入特征子图的向量组合成为矩阵;接下来,经过矩阵相乘运算获得卷积的结果,再经过col2img()将向量转化为特征子图。M个卷积核卷积一张输入图像的矩阵计算以下图所示:htm
图来自http://www.cnblogs.com/laiqun/p/6055498.htmlblog
其中,M表示二维卷积核的个数,K=k*k表示二维卷积核的大小;这样,每一个k*k大小的二维卷积核转化为一个行向量,M个二维卷积核对应M个行向量就获得了M*K的卷积矩阵A。
再说矩阵B:假设输入的每张特征子图大小为r*r,二维卷积核的大小为k*k,扩展大小pad,步长为stride,那么对于每张特征子图,按卷积核每次卷积图像的大小k*k,将该块卷积的图像转化为行向量,长度也为k*k=K,这样,依据卷积核与输入图像卷积的过程,将每一次卷积核卷积的区域转化为一个行向量,各个行向量按照卷积前后顺序以列进行排列,从而获得了矩阵B。此外,对于卷积后获得的二维特征子图的大小,在caffe中的计算公式以下(这里假设,输入图像和卷积和大小都是q*q的,即长与宽相等):
输出特征子图大小:n*n=[(r+2*pad-k)/strde+1]*[(r+2*pad-k)/strde+1]
若是咱们令pad=0,stride=1,那么就会变成咱们熟悉的形式,即n*n=[(r-k)+1]*[(r-k)/+1]。好比,输入特征图大小为32*32,卷积核大小为3*3,那么输出的特征子图大小为(32-3+1)*(32-3+1)=28*28。
好了,如今咱们知道了矩阵B的列N=n*n,而后经过矩阵相乘运行,即A*BT=(M*K)*(N*K)T=(M*K)*(K*N)=(M*N)=C,即获得了最终的矩阵C。固然,在caffe中可能会存在偏置项,那么这个矩阵C还要加上偏置矩阵P,而后获得最终的输出矩阵D,再经过col2img()将D中的每一行转化为一张特征图,就获得了输出的各个特征子图,从而完成了该卷积层的卷积运算。
二,卷积核是三维的:
对于卷积核是三维的状况,主要参考的是贾杨清老师在知乎上的一个解答。即认为每一个输入图像和每一个卷积核的大小表示为C*H*W,即:
由上图知道,一个输入特征图的表示是C*H*W(通道数*长*宽),一个卷积核的大小表示为C*K*K(注意:这里,若是认为卷积核是三维的,就必须保证卷积核的通道数跟输入特征图的通道数相同,不然卷积失败),那么根据卷积核一次卷积的图像区域,将该区域图像转化为行向量,即获得一个C*k*k的行向量。
按此方式,将一张图像按照卷积的顺序获得的行向量按列排列,就获得了最终的特征矩阵以下:
上图知道,对于一个C*H*W的图像,按照卷积核大小进行卷积,转化为的特征矩阵大小为:(H*W)*(C*K*K)。
那么,对于多个卷积核而言,将多个卷积核转化为卷积矩阵过程以下:
这里,卷积核的个数为Cout,每一个卷积核的大小为C*K*K,同理,将每一个卷积核转化为一个行向量C*K*K,按照卷积核个数按列排列,就获得卷积矩阵Cout*(C*K*K)。
最后,将卷积矩阵与输入特征矩阵的转置进行相乘,就获得了最终的输出特征矩阵[Cout*(C*K*K)]*[(H*W)*(C*K*K)]T=[Cout*(C*K*K)]*[(C*K*K)*(H*W)]=Cout*(H*W)。这样,再将输出矩阵的每一行转化为一张特征图,就获得了Cout张输出特征子图。而这,也就印证了:卷积层输出的特征图个数等于卷积核的个数。
以上,就是对两种对于卷积核的维度不一样见解的具体分析,无论怎么定义,都有其充分的理由和实践证实。而且,最重要的是,无论卷积核定义为二维仍是三维,都是为了数据转化为矩阵的形式,从而将卷积层的复杂的卷积过程,转化为矩阵的相乘的简单运算,大大的提升了计算的速度。
最后,经过一个具体的例子,来看一下将卷积转化为矩阵运算的过程:
参考连接:http://www.cnblogs.com/laiqun/p/6055498.html
https://www.zhihu.com/question/28385679
Convolution in Caffe: a memo · Yangqing/caffe Wiki · GitHub