目录
SE-ResNet, SE-ResNeXt (2018 Apr)
ResNet: 跳层残差结构
ResNeXt: 并列的重复模块 增加一个维度
SE Net: 增加通道上的注意力机制 eg:SE ResNeXt
ResNet
论文翻译 https://blog.csdn.net/iModel/article/details/80688394
介绍 https://www.jianshu.com/p/93990a641066
恒等映射 https://blog.csdn.net/wspba/article/details/72789964
ResNet中所提出的Residual block之所以成功,原因有两点,第一,是它的shortcut connection增加了它的信息流动,第二,就是它认为对于一个堆叠的非线性层,那么它最优的情况就是让它成为一个恒等映射,但是shortcut connection的存在恰好使得它能够更加容易的变成一个Identity Mapping。
下面那行的网络其实就是在上面那行网络的基础上新叠加了一层,而新叠加上那层的权重weight,如果能够学习成为一个恒等的矩阵I,那么其实上下两个网络是等价的,那么也就是说如果继续堆叠的层如果能够学到一个恒等矩阵,那么经过堆叠的网络是不会比原始网络的性能差的,也就是说,如果能够很容易的学到一个恒等映射,那么更深层的网络也就更容易产生更好的性能。
identity connection
在近些年中,深度网络逐渐往deeper的方向走,但是deeper会带来特征在正向传播中的消失和梯度在反向传播中的弥散。近来的工作也开始处理这些相关问题。
残差学习
若将输入设为X,将某一有参网络层设为H,那么以X为输入的此层的输出将为H(X)。一般的CNN网络如Alexnet/VGG等会直接通过训练学习出参数函数H的表达,从而直接学习X -> H(X)。
而残差学习则是致力于使用多个有参网络层来学习输入、输出之间的参差即H(X) - X即学习X -> (H(X) - X) + X。其中X这一部分为直接的identity mapping,而H(X) - X则为有参网络层要学习的输入输出间残差。
identity mapping 恒等映射
当输入、输出通道数相同时,我们自然可以如此直接使用X进行相加。而当它们之间的通道数目不同时,我们就需要考虑建立一种有效的identity mapping函数从而可以使得处理后的输入X与输出Y的通道数目相同即Y = F(X, Wi) + Ws*X。 W为linear projection 线性投影
当X与Y通道数目不同时,作者尝试了两种identity mapping的方式。
方式一:简单地将X相对Y缺失的通道直接补零从而使其能够相对齐的方式,
方式二:通过使用1x1的conv来表示Ws映射从而使得最终输入与输出的通道达到一致的方式。
bottleneck构建模块
为了实际计算的考虑,作者提出了一种bottleneck的结构块来代替常规的Resedual block,它像Inception网络那样通过使用1x1 conv来巧妙地缩减或扩张feature map维度从而使得我们的3x3 conv的filters数目不受外界即上一层输入的影响,自然它的输出也不会影响到下一层module。
Bottleneck模块
不过它纯是为了节省计算时间进而缩小整个模型训练所需的时间而设计的,对最终的模型精度并无影响。
具体:
1*1降维 3*3 1*1 升维
上面的topology图中,实线即表示identity shortcut,虚线即表示projection shortcut. 出现projection shortcut的原因是该module内部的操作改变了feature map的dimension(height, width, channel),我们需要一个projection来match dimension。下图中的f指该模块的输出channel数。
h/w和c的关系是:spatial每做一次1/2 down sample, c就乘以2, 所以h*c=常数
DenseNet
详细解析请看 https://yq.aliyun.com/articles/673371 !!!!
shortcut 连接所有层
connect all layers (with matching feature-map sizes) directly with each other
反直觉的好处,那就是参数量可以减少。原因是因为每个layer其实都相当于一个state,signal经过这个layer则改变这个state并将其传播到下一个state。ResNet显式的保存了上一个layer的state并传给了下一个layer可以有效改善网络的accuracy。这意味着一些feature可以被重复利用。但是今年来的一些ResNet变体则发现随机drop掉一些resblock并不会降低多少accuracy,这意味着一些Resblock并没有学习到多少有用的东西,而主要通过shortCut将上一个state进行传递而已。
还一个好处就是信息可以多方向的往下传,而梯度则可以多方向的反向传,这会使得整个网络更加容易训练。
原文链接:https://blog.csdn.net/shwan_ma/article/details/78165966
Inception
split-transform-merge.
指通过在大卷积核层两侧加入 1x1 的网络层,控制核个数,减少参数个数的方式
对输入进行split成a few lower-dimention embeding(1x1),然后在通过(3x3或5x5)的卷积核进行transformed,最后由concatenation来进行merge。
Inception网络的一个motivation就是通过稀疏连接进行近似成large and dense layers
但是超参太多了
Inception的缺点,太复杂了,人工设计的痕迹太重了。
ResNeXt
https://blog.csdn.net/u014380165/article/details/71667916
https://www.cnblogs.com/bonelee/p/9031639.html
https://blog.csdn.net/shwan_ma/article/details/78203020
pytorch 实现 https://blog.csdn.net/winycg/article/details/89077738
提出了 aggregrated transformations,用一种平行堆叠相同拓扑结构的blocks代替原来 ResNet 的三层卷积的block,在不明显增加参数量级的情况下提升了模型的准确率,同时由于拓扑结构相同,超参数也减少了,便于模型移植
贡献
- 网络结构简明,模块化
- 需要手动调节的超参少
- 与 ResNet 相比,相同的参数个数,结果更好:一个 101 层的 ResNeXt 网络,和 200 层的 ResNet 准确度差不多,但是计算量只有后者的一半
为了打破或deeper,或wider的常规思路,ResNeXt则认为可以引入一个新维度,称之为cardinality
ResNeXt Inception-ResNet 通道分组卷积
a是ResNeXt基本单元,如果把输出那里的1x1合并到一起,得到等价网络b拥有和Inception-ResNet相似的结构,而进一步把输入的1x1也合并到一起,得到等价网络c则和通道分组卷积的网络有相似的结构。
到这里,可以看到本文的野心很大,相当于在说,Inception-ResNet和通道分组卷积网络,都只是ResNeXt这一范式的特殊形式而已,进一步说明了split-transform-merge的普遍性和有效性,以及抽象程度更高,更本质一点。
ResNeXt引入的新的自由度,称为cardinality。ResNeXt的名字也源于此,X指的就是 neXt dimension。
将Inception和ResNet进行很好的结合。跟同期的Inception-ResNet不同的是,ResNeXt在每个path中都采取相同的设计(采用相同的卷积参数)
ResNeXt引入Inception结构,通过稀疏连接来approach之前的dense连接。
transform-merge,和 VGG/ResNets 的 repeat layer。
split-transform-merge 是指通过在大卷积核层两侧加入 1x1 的网络层,控制核个数,减少参数个数的方式
repeat layer 则是指重复相同的几层,前提条件是这几层的输出输出具有相同的维度,一般在不同的 repeat layers 之间使用 strip=2 降维,同时核函数的个数乘 2。
SE-ResNet, SE-ResNeXt (2018 Apr)
Squeeze-and-Excitation Networks
代码解析https://blog.csdn.net/xzy528521717/article/details/86582889
res family https://www.cnblogs.com/Matrix_Yao/p/9563063.html
SE NET 详解 https://www.jianshu.com/p/7244f64250a8
2017 google 说Attention is all you need。
可以把SENet看成是channel-wise的attention。如下图,SENet在常规动作后增加了一条专门计算channel-wise scale的branch,然后把得到的值乘到相应的channel上。
这个怎么运作
SENet计算channel-wise attention,分为两个步骤:
- Squeeze: 如下图的红框。把每个input feature map的spatial dimension 从H * W squeeze到1。这里是通过global average pooling完成的。
Squeeze操作,我们顺着空间维度来进行特征压缩,将每个二维的特征通道变成一个实数,这个实数某种程度上具有全局的感受野,并且输出的维度和输入的特征通道数相匹配。它表征着在特征通道上响应的全局分布,而且使得靠近输入的层也可以获得全局的感受野,这一点在很多任务中都是非常有用的
- Excitation: 如下图的绿框。通过一个bottleneck结构来捕捉channel的inter-dependency,从而学到channel的scale factor(或者说是attention factor) 。
Excitation操作,它是一个类似于循环神经网络中门的机制。通过参数 来为每个特征通道生成权重,其中参数 被学习用来显式地建模特征通道间的相关性。
- Reweight的操作
我们将Excitation的输出的权重看做是进过特征选择后的每个特征通道的重要性,然后通过乘法逐通道加权到先前的特征上,完成在通道维度上的对原始特征的重标定。
下图是SE-ResNet, 可以看到SE module被apply到了residual branch上。
上左图是将SE模块嵌入到Inception结构的一个示例。方框旁边的维度信息代表该层的输出。这里我们使用global average pooling作为Squeeze操作。紧接着两个Fully Connected 层组成一个Bottleneck结构去建模通道间的相关性,并输出和输入特征同样数目的权重。我们首先将特征维度降低到输入的1/16,然后经过ReLu激活后再通过一个Fully Connected 层升回到原来的维度。这样做比直接用一个Fully Connected层的好处在于:1)具有更多的非线性,可以更好地拟合通道间复杂的相关性;2)极大地减少了参数量和计算量。然后通过一个Sigmoid的门获得0~1之间归一化的权重,最后通过一个Scale的操作来将归一化后的权重加权到每个通道的特征上。
SE模块还可以嵌入到含有skip-connections的模块中。上右图是将SE嵌入到 ResNet模块中的一个例子,操作过程基本和SE-Inception一样,只不过是在Addition前对分支上Residual的特征进行了特征重标定。如果对Addition后主支上的特征进行重标定,由于在主干上存在0~1的scale操作,在网络较深BP优化时就会在靠近输入层容易出现梯度消散的情况,导致模型难以优化。
下图是网络配置,这里FC后边的方括号里面的数表示和。
Implementation Notes
- SENet的FC等效于1x1的convolution,可以用conv1x1来代替。
- channel wise scale + eltsum可以fuse成channel-wise axpy。
Mind Experiment
- Q: SE module最终实现上其实是channel wise的scale,这个在数学操作上与BN是一样的。那SE module为什么不能被BN代替呢?
A:BN只建模了spatial内的dependency,而SE module不仅建模了spatial dependency还建模了inter-channel的dependency。
涉及到的其他知识:
Global average pooling (GAP)
https://www.jianshu.com/p/04f7771f4da2
gap对整个网络从结构上做正则化防止过拟合
pooling也可以提供一些旋转不变性。
既然全连接网络可以使feature map的维度减少,进而输入到softmax,但是又会造成过拟合,是不是可以用pooling来代替全连接。
答案是肯定的,Network in Network工作使用GAP来取代了最后的全连接层,直接实现了降维,更重要的是极大地减少了网络的参数(CNN网络中占比最大的参数其实后面的全连接层)。Global average pooling的结构如下图所示:
每个讲到全局池化的都会说GAP就是把avg pooling的窗口大小设置成feature map的大小,这虽然是正确的,但这并不是GAP内涵的全部。
GAP的意义是对整个网络从结构上做正则化防止过拟合。
既要参数少避免全连接带来的过拟合风险,又要能达到全连接一样的转换功能,
怎么做呢?直接从feature map的通道上下手,如果我们最终有1000类,那么最后一层卷积输出的feature map就只有1000个channel,然后对这个feature map应用全局池化,输出长度为1000的向量,这就相当于剔除了全连接层黑箱子操作的特征,直接赋予了每个channel实际的类别意义。
实验证明,这种方法是非常有效的,
这样做还有另外一个好处:不用在乎网络输入的图像尺寸。同时需要注意的是,使用gap也有可能造成收敛变慢。
梯度爆炸、梯度消失、 梯度弥散
https://blog.csdn.net/qq_25737169/article/details/78847691
https://blog.csdn.net/zhangbaoanhadoop/article/details/82290129
梯度消失与梯度爆炸其实是一种情况,看接下来的文章就知道了。两种情况下梯度消失经常出现,一是在深层网络中,二是采用了不合适的损失函数,比如sigmoid。梯度爆炸一般出现在深层网络和权值初始化值太大的情况下
深层网络角度:
对激活函数进行求导,如果此部分大于1,那么层数增多的时候,最终的求出的梯度更新将以指数形式增加,即发生梯度爆炸,如果此部分小于1,那么随着层数增多,求出的梯度更新信息将会以指数形式衰减,即发生了梯度消失
从深层网络角度来讲,不同的层学习的速度差异很大,表现为网络中靠近输出的层学习的情况很好,靠近输入的层学习的很慢,有时甚至训练了很久,前几层的权值和刚开始随机初始化的值差不多。因此,梯度消失、爆炸,其根本原因在于反向传播训练法则,属于先天不足,另外多说一句,Hinton提出capsule的原因就是为了彻底抛弃反向传播,如果真能大范围普及,那真是一个革命。
激活函数角度:
sogmoid:函数图像和导数图像
梯度弥散:
权重更新慢----使用反向传播算法传播梯度的时候,随着传播深度的增加,梯度的幅度会急剧减小,会导致浅层神经元的权重更新非常缓慢,不能有效学习。这样一来,深层模型也就变成了前几层相对固定,只能改变最后几层的浅层模型。
激活函数的“饱和----梯度弥散的问题很大程度上是来源于激活函数的“饱和”。因为在后向传播的过程中仍然需要计算激活函数的导数,所以一旦卷积核的输出落入函数的饱和区,它的梯度将变得非常小。
如何解决梯度消失、爆炸、弥散
- 预训练加微调
- 梯度剪切、权重正则(针对梯度爆炸)
- 使用不同的激活函数,Relu代替sigmoid
- 使用batchnorm
- 使用残差结构
- 使用LSTM网络
具体看https://blog.csdn.net/qq_25737169/article/details/78847691
BN层
《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》
顾名思义,batch normalization嘛,就是“批规范化”咯。Google在ICML文中描述的非常清晰,即在每次SGD时,通过mini-batch来对相应的activation做规范化操作,使得结果(输出信号各个维度)的均值为0,方差为1. 而最后的“scale and shift”操作则是为了让因训练所需而“刻意”加入的BN能够有可能还原最初的输入,从而保证整个network的capacity。
那BN到底是什么原理呢?说到底还是为了防止“梯度弥散”。关于梯度弥散,大家都知道一个简单的栗子:。在BN中,是通过将activation规范为均值和方差一致的手段使得原本会减小的activation的scale变大。可以说是一种更有效的local response normalization方法。
BN可以应用于网络中任意的activation set。文中还特别指出在CNN中,BN应作用在非线性映射前,即对x=Wu+b做规范化。另外对CNN的“权值共享”策略,BN还有其对应的做法(详见文中3.2节)。