**权值共享方法**
- 在同一特征图和不同通道特征图都使用共享权值,这样的卷积参数是最少的,例如上一层为30*30*40,当使用3*3*120的卷积核进行卷积时,卷积参数为:3*3*120个.(卷积跟mlp有区别也有联系一个神经元是平面排列,一个是线性排列)
- 第二种只在同一特征图上使用共享权值,根据上面的例子,则卷积参数为:3*3*40*120.
**权值共享方法**
CNN中权值共享理解
借用前人的介绍:
(1) 针对一个神经元,例如一幅640*360图像,一个神经元要对应640*360个像素点,即一个神经元对应全局图像,全连接的话一个神经元就有640*360个参数;
(2) 图像的空间联系是局部的,就像人是通过一个局部的感受野去感受外界图像一样,每一个神经元都不需要对全局图像做感受,每个神经元只感受局部的图像区域,然后在更高层,将这些不同局部的神经元综合起来就可以得到全局信息。假如每个局部感受野1010,每个局部感受野只需要和1010的局部图像连接,这样一个神经元就只需要10*10个参数;
(3) 全局图像是640360,但局部图像只有1010大小,1010个参数只针对局部图像,如果全局图像中各个局部图像之间权值共享的话,即1010个参数在不同局部图像上参数应用相同的话,则在全局图像上通过全局共享则只需要10*10个参数;
(4) 1010个参数只针对一个神经元,要是有100万个神经元,则需要100万1010个参数,神经元多后,参数还是太大,如果每个神经元的这1010个参数相同呢,这样就还是只需要1010参数,因而经过局部感受野到权值共享再到每个神经元的1010个参数相同,不管图像多大,不管每层神经元个数多少,而两层间连接还是只需要求解10*10个参数;
(5) 由于只有一个滤波器,只提取了一种特征,特征也太少了。一种滤波器也就是一种卷积核就是提取图像一种特征,例如某个方向的边缘。那么我们需要提取不同特征怎么办,多加几个滤波器不就行了。假设我们加到100种滤波器,每种滤波器的参数不一样,表示提取输入图像不同特征,例如不同边缘。**这样不同滤波器去卷积图像就得到不同特征的放映,我们称之为Feature Map,所以100中卷积核就有100个Feature Map,**这100个Feature Map就组成了一层神经元。我们这一层有多少个参数到这时候就明了吧,100种卷积核 * 每种卷积核100个参数 = 100 * 100 = 10000个参数。
(6) 刚才说每一个隐藏层的参数个数和隐藏层的神经元个数无关,只和滤波器大小和滤波器种类数有关,那么隐藏层的神经元个数怎么确定呢?它和原图像,也就是输入的大小(神经元个数)、滤波器的大小和滤波器在图像中的滑动步长都有关!假如我的图像是10001000像素的,而滤波器大小是1010,假设步长为10,即滤波器没有重叠,这样隐藏层的神经元个数就是 1000 * 1000 / (1010) = 100100个神经元(如果步长为8,卷积核会重叠2个像素)。这只是一种滤波器,也就是一个Feature Map的神经元个数哦,如果100个Feature Map就是100倍了,
需要注意一点,上面的讨论都没有考虑每个神经元的偏置部分,所以权值个数需要加1,这也是同一种滤波器共享。如滤波器1010,卷积核个数6,则参数个数为:
(1010 +1) * 6 = 606.
1×1的卷积大概有两个方面的作用吧:
1. 实现跨通道的交互和信息整合
2. 进行卷积核通道数的降维和升维
3、减少卷积核参数(简化模型),对于单通道feature map 用单核卷积即为乘以一个参数,而一般情况都是多核卷积多通道,实现多个feature map的线性组合
4、可以实现与全连接层等价的效果。如在faster-rcnn中用1*1*m的卷积核卷积n(如512)个特征图的每一个位置(像素点),其实对于每一个位置的1*1卷积本质上都是对该位置上n个通道组成的n维vector的全连接操作。
1,2点解释
以GoogLeNet的3a模块为例:
输入的feature map是28×28×192,3a模块中1×1卷积通道为64,3×3卷积通道为128,5×5卷积通道为32,
如果是左图结构,那么卷积核参数为1×1×192×64+3×3×192×128+5×5×192×32,
而右图对3×3和5×5卷积层前分别加入了通道数为96和16的1×1卷积层,这样卷积核参数就变成了1×1×192×64+(1×1×192×96+3×3×96×128)+(1×1×192×16+5×5×16×32),参数大约减少到原来的三分之一。
同时在并行pooling层后面加入1×1卷积层后也可以降低输出的feature map数量,左图pooling后feature map是不变的,再加卷积层得到的feature map,会使输出的feature map扩大到416,如果每个模块都这样,网络的输出会越来越大。
而右图在pooling后面加了通道为32的1×1卷积,使得输出的feature map数降到了256。GoogLeNet利用1×1的卷积降维后,得到了更为紧凑的网络结构,虽然总共有22层,但是参数数量却只是8层的AlexNet的十二分之一。
比如输入是28x28x192(WxDxK,K代表通道数),然后在3x3的卷积核,卷积通道数为128,那么卷积的参数有3x3x192x128,其中前两个对应的每个卷积里面的参数,后两个对应的卷积总的个数(一般理解为,卷积核的权值共享只在每个单独通道上有效,至于通道与通道间的对应的卷积核是独立不共享的,所以这里是192x128)。
3,4点解释
(1) 对于单通道的feature map和单个卷积核之间的卷积来说,1X1卷积核就是对输入的一个比例缩放,因为1X1卷积核只有一个参数,这个核在输入上滑动,就相当于给输入数据乘以一个系数。
(2) 对于多通道而言有一个重要的功能,就是可以在保持feature map 尺寸不变(即不损失分辨率)的前提下大幅增加非线性特性,把网络做得很deep。
(3) CNN里的卷积大都是多通道的feature map和多通道的卷积核之间的操作**(输入的多通道的feature map和一组卷积核做卷积求和得到一个输出的feature map)**,**如果使用1x1的卷积核,这个操作实现的就是多个feature map的线性组合,可以实现feature map在通道个数上的变化。**接在普通的卷积层的后面,配合激活函数,就可以实现network in network的结构了。
引用大佬的计算说明。
上来先说1∗1卷积核的作用:
1. 特征降维,节省计算量
2. 增加模型非线性表达能力
举例:因为bottleneck(1∗11*11∗1卷积核)是在2014年的GoogLeNet中首先应用的,所以我们就拿GoogLeNet来举例。在GoogLeNet(2014)之前,网络的设计思路是一直在stack(堆叠)层数,当时的假设是网络越deeper,网络的performance越好。到了2014年,GoogLeNet横空出世,GoogLeNet改变了这个假设:除了增加深度,还增加了网络的宽度。GoogLeNet的结构如下:
下面我们一步步来推倒出Inception module的设计,先来看初始版本的Naive Inception module。Naive Inception module就是对同一个输入,用不同大小的卷积核去卷积,然后分别把它们的结果给concatenate(注意这里要求不同卷积操作输出的feature map的大小要相同,不然没法特征拼接呀)起来。但这样有个问题:计算量太大了!
注:上图3∗3333∗3卷积的padding=1padding=1padding=1,5∗5555∗5卷积的padding=2padding=2padding=2(为保证不同卷积操作输出的特征图大小一样,以便于后面的特征拼接)
Naive Inception module的计算量的计算过程如下,可见Naive Inception module的计算量是相当大的(这还只是一层)。
那么我们应该如何减少计算量呢?用的是什么理念和思想呢?
这就不得不提到从2014年一直延续至今的神经网络设计思想:bottleneck。使用bottleneck(即1∗11*11∗1的卷积核)来进行特征降维,减少特征图的层数,从而减少计算量。
bottleneck的过程如下面两张图片所示:
所以到这里,Naive Inception module就升级为了Inception module。
此时这一个Inception module的计算量为358M ops,相比之前的854M ops,使用“bottleneck”的Inception module的计算量降低了一半多!
[1] https://blog.csdn.net/weixin_43430243/article/details/89512069
[2] https://www.cnblogs.com/lqc-nogi/p/9740906.html
[3] https://www.cnblogs.com/eilearn/p/9202834.html
[4] https://blog.csdn.net/ft_sunshine/article/details/90953784
[5] https://blog.csdn.net/lien0906/article/details/51249947
来源:CSDN
作者:xlhao的博客
链接:https://blog.csdn.net/weixin_43430243/article/details/103470874