神经网络-CNN系列


本来和神经网络-CNN基础为同一篇笔记,但由于篇幅太长,故将其一拆为二,另起一篇

1. LeNet

1989年的论文(比我的年龄还大(⊙ˍ⊙)):

个人基于pytorch的实现代码

网络结构:

卷积神经网络的奠基之作,提出了CNN网络一些最基础的概念:卷积、池化、全连接、反向传播等

2. AlexNet

ISLVRC 2012的分类任务组冠军:ImageNet Classification with Deep Convolutional Neural Networks

个人基于pytorch的实现代码

网络结构:

这是最经典的CNN网络,拥有更深的网络,且增加了ReLUDropout

2.1. Local Response Normalization

论文中还提出一个局部响应归一化(Local Response Normalization,LRN)层,计算公式 \[ b_{x, y}^{i}=a_{x, y}^{i} /\left(k+\alpha \sum_{j=\max (0, i-n / 2)}^{\min (N-1, i+n / 2)}\left(a_{x, y}^{j}\right)^{2}\right)^{\beta} \] 其中,\(a_{x, y}^{i}\) 为输出通道 \(i\) 在位置 \((x,y)\) 处的原始值,\(b_{x, y}^{i}\) 为归一化之后的值。\(n\) 为影响第 \(i\) 个通道的通道数量(分别从左侧、右侧 \(n/2\) 个通道考虑)。\(\alpha,\beta,k\) 为超参数。论文中取 \(k=2,n=5,\alpha=10^{-4},\beta=0.75\)

该层的基本思想是,输出通道 \(i\) 在位置 \((x,y)\) 处的输出会受到相邻通道在相同位置输出的影响。达到横向抑制的效果,即使得不同的卷积核所获得的响应产生竞争

但现在一般认为该结构用处不大(VGG中有相关的证明),只会增加网络的运算量,所以现在该结构很少被使用

2.2. Overlapping Pooling

一般池化都是不重叠的,即步长大于pooling size。AlexNet中允许可重叠的池化,即步长小于pooling size,并认为这种做法可以轻微的减轻过拟合的问题。

对此,一种观点认为,重叠池化会带来更多的特征,这些特征很可能会有利于提高模型的泛化能力。

2.3. Data Augmentation

  • 统一尺寸。先对图片等比resize,使短边至固定长度;然后裁剪长边,使其与短边相等,便得到了一个大小固定的矩形图片
  • 尺寸修剪。训练阶段,对同一张图片进行随机性的裁剪(256->224),然后随机水平翻转;预测阶段,裁剪出四个角落位置、一个中心位置,再加上水平翻转的图片,共10张裁剪后图片(256->224)。预测结果的均值作为最终的预测输出
  • 颜色抖动。裁剪翻转的图片,经过PCA降维去噪后,放大一个随机(服从 \(N(0,0.1)\) 正态分布)的因子倍数 \(\alpha\),即 \(\left[\mathbf{p}_1, \mathbf{p}_2, \mathbf{p}_3\right]\left[\alpha_1 \lambda_1, \alpha_2 \lambda_2, \alpha_3 \lambda_3\right]^T\),其中,\(\mathbf{p}_i,\lambda_i\) 分别为PCA降维后的特征向量矩阵和特征值

3. VGG-Net

ILSVRC 2014的分类任务组亚军:Very Deep Convolutional Networks for Large-Scale Image Recognition

个人基于pytorch的实现代码

网络结构:

3.1. 小卷积核

一般来说,卷积核越大,感受野面积越大,获取到的特征越好。但卷积核越大,需要训练的参数也越大。而VGG则证明了小尺寸卷积核的深层网络要优于大尺寸卷积核的浅层网络,这也是这篇论文最大的贡献

使用多个小卷积核取代一个大的卷积核,需要训练的参数量大大减少。例如,一个 \(5\times 5\)​ 的卷积核,要使得输出的特征图面积不变,则需要2个 \(3\times 3\)​ 的卷积核替代,而替代后的参数只有原来的 \(\frac{2 \times 3 \times 3}{5\times 5} = 0.72\)​ 倍

另外,论文中也证明了深度对网络的泛化性能的重要性

3.2. 尺寸抖动(scale jittering)

论文采用的数据增强方式:训练前选取一个随机值 \(S \in [S_{\min},S_{\max}]\) ,等比resize,使短边为 \(S\),然后再裁剪成固定尺寸的图片。

论文通过实验认为,相比resize固定短边后再裁剪成固定尺寸图片的方式,scale jittering可以显著提升模型效果

除了尺寸抖动的方式,为了应对多尺度图片输入,论文还训练了多个不同尺度输入的模型,然后对这些网络的结果求平均。

注:大尺寸的网络是在小网络的基础上finetune出来的,但论文认为这只是为了节省时间,就是不承认finetune,啧啧啧~

4. GoogLeNet(Inception系列)

ILSVRC 2014的分类任务组冠军:Going deeper with convolutions

这篇论文其实是专门讲Inception的,GoogLeNet只是顺带提一下。另外,GoogLeNet中L是大写,是为向LeCuns做出的贡献表示敬意。

网络结构:

4.1. Inception

个人基于pytorch的实现代码

Inception原义有开端、全面启动等意思,还有一部电影也叫Inception,译名盗梦空间,作者取这个名字,除了受到电影中“We need to go deeper”台词的影响,是不是也展示了他对该结构的自信与野心?事实上,这的确是一个很富有开端式的结构

当时的CNN都是通过堆叠串联卷积层,将网络做深,是模型具有更好的性能。但网络变深,一方面意味着过拟合变严重,另一方面计算量也变大。

GoogLeNet应用了一种Inception结构,这种结构将串行的卷积层变成并行的,然后再将每个卷积层的结构耦合(沿深度方向拼接)在一起。具体结构如下:

最原始的Inception结构如图a所示,3个不同尺寸的卷积层并行计算,其输出特征图然后再按高度拼接到一起。为了使得输出的特征图大小一致,需要进行padding操作。另外,结构还直接拼接了一个最大池化层,这一层是为了获取输入的原始特征。

拼接一个简单的卷积层或池化层的操作,就很有后面resnet提出的残差层那味了

另外,网络结构每一层的参数没有太多的规律,看来是使用了一些网络搜索的技巧。

论文中认为原始的结构最终的通道数可能会太大了,所以预先分别输入一个 \(1*1\) 的卷积层进行降维,所以这是一种稀疏连接。有一点需要注意的是,需要先池化再进行降维,这是因为先降维,池化不是获取最原始的输入特征了。

Inception结构从网络的宽度入手,将串行变成并行,一方面降低模型的深度,减轻过拟合程度;另一方面有利于集群并行计算,侧面降低了计算成本。

4.2. Inception V2

2015年的论文:Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

个人基于pytorch的实现代码

注:Inception V2以及后面的Inception系列已经不包含在GoogLeNet中,这里为了方便,都写在同一个章节里面。

该论文提出了经典的批次归一化(Batch Normalization,BN)处理

前向计算:

反向计算:

优点:

  • 加快训练速度
  • 提高模型泛化能力

除了BN,后面还提出了layer normalization(LN),以及其他各种的normalization。其实就是一个立方体,无论是正切、反切、斜切、对半切,其实都可以。只要结果是work的,再倒回来自圆其说就可以了。

4.3. Inception V3

2015年的论文:Rethinking the Inception Architecture for Computer Vision

个人基于pytorch的实现代码

注:网上找资料的时候,有一些材料认为这是Inception V2,而且论文里面有一个章节说这是Inception V2的结构。但我网上并未找到其他Inception V3的结构,如果这是Inception V2,那如果这是Inception V3的结构长什么样呢?所以这个地方先存疑。

将大卷积核转换成小卷积核,这个在VGG中已经讲过了

论文中还提出将大卷积转换成非对称式的卷积核,即将一个 \(n \times n\) 的卷积核转换成一个 \(1 \times n\) 和一个 \(n \times 1\) 的卷积核,从而减少训练参数。

这是一个很巧妙的设计,一个大卷积核拆成两个非对称的卷积核后,两者最终输出特征图的大小是一样的,但参数后者只有前者的 \(\frac{2}{n}\)

一不做二不休,论文最后还继续将两个非对称的卷积核改成并联模式(有点丧心病狂了:-))

4.4. Inception V4 & Inception-ResNet

2016年的论文:Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning

该论文同时提出了两种结构:Inception V4 和 Inception-ResNet

Inception V4,总体没有太大的改进,就是在v3的基础上增加或减少一些卷积层,缝缝补补(非常能体现搭积木的思想)。整体结构图如下:

其中Inception-A/B/C以及Reduction-A/B都是一些比较基础的Inception结构,这里就不放结构图了,直接看论文就可以了。下面挑一些stem的结构进行展示:

Inception-ResNet,就是结合了ResNet的残差结构。残差结构放在ResNet章节中重点分析,下面直接给出网络结构图:

stem结构:

Inception-ResNet-A结构:

4.5. Xception

2016年的论文:Xception: Deep Learning with Depthwise Separable Convolutions

Xception,即Extreme Inception,将每个通道使用一个filter,改为所有通道共用一个filter,即

  • simple Inception:\([D_W \cdot D_H \cdot M] * [1 \cdot 1 \cdot M \cdot N] * [D_{K} \cdot D_{K} \cdot N \cdot M] \rightarrow [D_W \cdot D_H \cdot M]\)
  • Xception:\([D_W \cdot D_H \cdot M] * [1 \cdot 1 \cdot 1 \cdot M] * [D_{K} \cdot D_{K} \cdot 1 \cdot M] \rightarrow [D_W \cdot D_H \cdot M]\)

优点:

  • 减少的参数量,降低了模型复杂度
  • 加强了通道相关性和空间相关性

5. ResNet

CVPR 2016的最佳论文:Deep Residual Learning for Image Recognition

个人基于pytorch的实现代码

网络结构:

5.1. Deep Residual Learning

论文发现,当模型加深的时候,除了会引起梯度爆炸/消失问题(这个问题已经在Inception V2中通过BN有所减轻),还会引起网络退化的问题。

所谓的网络退化,就是上一层网络的误差不断累积到下一层,随着网络加深,网络逐渐偏离原来问题的中心(准确率达到饱和并有下降趋势),甚至已经退化成解决其他问题的网络。

于是,论文中提出了大名鼎鼎的残差结构(如下图所示)来对抗网络退化问题。

数学表达式 \[ x_l=\mathcal{F}\left(x_{l-1},W_{k}\right)+W_{s} x_{l-1} \] 该结构包括两部分内容:残差表示Residual Representations) 和 短路连接Shortcut Connections)。其中,

  • 残差表示就是 \(F(x) + x\) 的表达形式;
  • 短路连接就是输入和输出直接耦合的做法,就像电路的短路一样。

对于残差结构的作用,

  • 一种具象化的解释是:下一层耦合了上一层的数据后,下一层网络其实需要完成两个任务。一个是对上一层输入的优化,一个是对上一层输出的优化。或者说,网络参考着上一层的优化结果,重新对问题进行优化,从而将网络重新拉回问题中心,从而可以对抗网络退化。

  • 数学推导上分析,普遍的观点认为残差结构通过减轻梯度消失来对抗网络退化。因为在反向传播中,有 \[ \frac{\partial x_l}{\partial x_{l-1}} = W_s \cdot 1 + \frac{\partial }{\partial x_{l-1}}(\sum \mathcal{F_i}) \] 可以看到,原始输入的梯度被完整的传递下去了,保证了梯度不会消失

5.2. bottleneck

为了节省训练时间,当网络比较深时,论文将两层卷积的残差结构改为三层的。其中第一个1x1卷积用于降维,中间的3x3卷积用于提取信息,最后一个1x1卷积用于升维。

6. DenseNet

CVPR 2017的最佳论文:Densely Connected Convolutional Networks

代码实现:

网络结构:

6.1. Dense Block

ResNet残差结构的升级版,其结构如下:

数学表达式 \[ x_l=\mathcal{F}\left(x_{l-1},W_{k}\right)+ \sum_{i=0}^{l-1} W_{i} x_{i} \] ResNet是只与前面一层相连,而DenseNet则索性将当前层与前面所有层直接相连,非常稠密(dense),DenseNet称这样的处理为特征重用(feature reuse)

优点:

  • 可以比ResNet在参数和计算成本更少的情形下拥有更优的性能
  • 更进一步的减轻梯度消失的问题,是网络更加容易训练,提升网络的学习能力

7. SENet

ILSVRC 2017分类任务组冠军:Squeeze-and-Excitation Networks

代码实现:

这篇论文最大的亮点是提出了一个Squeeze-Excitation(SE) block的结构,这种结构可以很好的嵌入到众多主流的CNN框架(如Inception、ResNet等)中,并提高了网络的表达能力

7.1. SE block

通过显式地对通道之间的相互依赖关系建模,自适应的重新校准通道维度的特征响应,从而提高了网络的表达能力

  1. Transformation。一些卷积操作 \[ \mathbf{u}_{c} = \mathbf{F}_{tr}\left(\mathbf{v}_{c}\right) = \mathbf{v}_{c} * \mathbf{X} \]

  2. Squeeze。一个global pooling,分别对每个通道求平均,即 \[ z_{c}=\mathbf{F}_{s q}\left(\mathbf{u}_{c}\right)=\frac{1}{H \times W} \sum_{i=1}^{H} \sum_{j=1}^{W} \mathbf{u}_{c}(i, j) \] 这一步将一个三维的矩阵压缩成一个一维的向量编码,可以理解为每个通道的权重。

  3. Excitation。这一步实际上是两个全连接层,即 \[ \mathbf{s}=\mathbf{F}_{e x}(\mathbf{z}, \mathbf{W})=\sigma(g(\mathbf{z}, \mathbf{W}))=\sigma\left(\mathbf{W}_{2} \delta\left(\mathbf{W}_{1} \mathbf{z}\right)\right) \\ where\quad \delta = Relu,\sigma = Sigmoid,\mathbf{W}_1 \in \mathbb R^{\frac{C}{r} \times C},\mathbf{W}_2 \in \mathbb R^{C \times \frac{C}{r}} \] 可以理解为通过先降维再升维,来提高网络的泛化能力。

  4. Scale。用输入乘上权重,得到最终输出,即 \[ \widetilde{\mathbf{x}}_{c}=\mathbf{F}_{\text {scale }}\left(\mathbf{u}_{c}, s_{c}\right)=s_{c} \mathbf{u}_{c} \]

论文中认为这实际上就是一种attention的机制。

8. SqueezeNet

2016年的论文:Squeezenet: Alexnet-level accuracy with 50x fewer parameters and< 0.5 mb model size

代码实现:

网络结构:

SqueezeNet是一个轻量化的网路,论文题目也非常直白:我就是冲着网络轻量化去的。

一般为了获得更好的效果,都是将神经网络做大做深。但随着移动端的崛起,神经网络也逐渐往轻量化方向发展。

一个轻量化模型的标准:数据量小于150 MFLOPs(一次前向推断需要n百万次浮点运算)

8.1. Fire module

SqueezeNet的核心是fire module,其结构如下:

其包含两部分操作:

  • squeeze,普通的 \(1 \times 1\) 的卷积层
  • expand,将一部分 \(3 \times 3\) 的卷积核直接削减成 \(1 \times 1\) 的卷积核,然后将两部分的结果沿深度拼接

减少参数量的方法非常简单粗暴,就是直接缩小卷积核的尺寸,然后做了下实验,发现参数少了50倍,但模型效果只降低一点,这笔买卖非常合得来。

其实也从侧面说明,对于一些数据量不大的任务,完全没必要使用很大的卷积核,即使是最简单的 \(1 \times 1\) 的卷积层(这是其实就变成全连接层了)也是足以胜任的。

8.2. 模型压缩

SqueezeNet还使用了一些模型压缩的算法,如SVD,网络剪枝(network pruning)和量化(quantization)等,这里就不展开讲了

9. MobileNet系列

MobileNet也是一个轻量化的神经网络。

9.1. MobileNet V1

2017年的论文:MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications

个人基于pytorch的实现代码

网络结构:

注:

上表中,倒数第3、4层的input size有误,应为4x4x1024

MobileNet的结构和Xception的结构是很像的,而MobileNet的发表时间比Xception稍晚,但据说当时是两个团队同时研究,但MobileNet的发表较晚。而且都是同一个公司的出品,其实也不存在谁抄袭谁的说法了,只能说研究方向撞车了。

另外,两者最大的不同之处是MobileNet是先depthwise再pointwise;而Xception是先pointwise再depthwise

9.1.1. Depthwise Separable Convolution

使用深度可分离卷积(Depthwise Separable Convolution)替换普通卷积,两者的计算流程(默认padding)分别为:

  • 普通卷积:\([D_W \cdot D_H \cdot M] * [D_{K} \cdot D_{K} \cdot M \cdot N] \rightarrow [D_W \cdot D_H \cdot N]\)
  • 深度可分离卷积:\([D_W \cdot D_H \cdot M] * [D_{K} \cdot D_{K} \cdot 1 \cdot M] * [1 \cdot 1 \cdot M \cdot N] \rightarrow [D_W \cdot D_H \cdot N]\)

可以看出,深度可分离卷积将卷积计算分成了两部分,其中,\([D_{K} \cdot D_{K} \cdot 1 \cdot M]\) 部分的卷积称为深度(depthwise)卷积\([1 \cdot 1 \cdot M \cdot N]\) 部分的卷积称为逐点(pointwise)卷积

参数量和计算量替换前后(分子替换前,分母替换后)比较: \[ \text{参数量比} = \frac{D_{K} \cdot D_{K} \cdot M +M \cdot N }{D_{K} \cdot D_{K} \cdot M \cdot N } =\frac{1}{N}+\frac{1}{D_{K}^{2}} \\ \text{计算量比} = \frac{D_{K} \cdot D_{K} \cdot M \cdot D_W \cdot D_H +M \cdot N \cdot D_W \cdot D_H}{D_{K} \cdot D_{K} \cdot M \cdot N \cdot D_W \cdot D_H} = \frac{1}{N}+\frac{1}{D_{K}^{2}} \] 可以看出,在保持最终输出的特征图大小一致的前提下,参数量和计算量比较都下降了 \(\frac{1}{N}+\frac{1}{D_{K}^{2}}\),例如,常用的 \(3\times3\) 卷积核,下降量为八分之一左右。

9.1.2. width multiplier & resolution multiplier

  • width multiplier,宽度因子 \(\alpha\),等比例降低输入输出的通道数,参数量下降 \(\alpha^2\) ,计算量不变
  • resolution multiplier,分辨率因子 \(\rho\),等比例降低输入输出的尺寸,参数量不变,计算量下降 \(\rho^2\)

其实我没太懂论文中为什么要把这部分的内容单独拿出来讲,这难道不就是很普通的工程调参吗?

9.2. MobileNet V2

2019年的论文:MobileNetV2: Inverted Residuals and Linear Bottlenecks

网络结构:

9.2.1. Linear Bottlenecks

论文中认为,由于ReLU激活函数的存在,某些通道可能会被全部都置0,从而出现不可逆的信息损失。所以应该在最后几层设置一些不使用激活函数的瓶颈(bottlenecks)层,即所谓的线性瓶颈(Linear Bottlenecks)结构。

9.2.2. Inverted residuals

一般的残差结构会使用一个\(1 \times 1\)的卷积核降维,而反转残差(Inverted residuals)结构,则先使用一个\(1 \times 1\)的卷积核升维,然后是卷积操作,最后再使用一个\(1 \times 1\) 的卷积核降维至原来的大小。

需要注意的是,最后一步的降维操作不需要使用激活函数,是一个瓶颈层。

9.2.3. ReLU6

ReLU6对比ReLU增加了一个上界,其表达式为 \[ \text{ReLU(6)} = \min (\max (0,x),6) \] 作者认为ReLU6在低精度计算下具有更强的鲁棒性

9.3. MobileNet V3

2019年的论文:Searching for MobileNetV3

网络结构(Large):

一个很有趣的点是,V3的网络结构是使用NetAdapt算法优化出来的

9.3.1. bneck

直接将V2版本的瓶颈层去掉

9.3.2. h-wish

hard swish(h-wish)是使用近似模拟swish和ReLU函数得出的,其表达式: \[ \operatorname{h-swish}(x)=x \frac{\operatorname{ReLU} 6(x+3)}{6} \] 但论文研究发现,h-wish只在深层网络中效果更好,考虑到其计算成本,所以网络前半部分使用ReLU,后半部分使用h-wish

10. ShuffleNet系列

10.1. ShuffleNet V1

2017年的论文:ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices

代码实现:

论文中发现,像ResNet、MobileNet等网络,计算量占比最大的是 \(1 \times 1\) 的卷积层(约93%的计算量),为此,论文提出采用分组卷积的方式,减少网络的参数。

例如,对于一个输入深度为 \(M\) 、输出深度为 \(N\) 的任务,则需要 \(N\)\(1\times 1 \times M\) 的卷积核,先按通道对输入分成 \(G\) 个组,然后再进行分组卷积,则只需 \(N\)\(1\times 1 \times M/G\) 的卷积核

但每次都按固定分组卷积,每个卷积核学到的都是固定分组内的信息,阻止通道之间的信息流动,降低网络的表达能力。所以在每次分组前,还应该按通道打乱(论文中采用的并非随机打乱,而是有序的打乱,具体的打乱规则见下图),当迭代次数增大时,每个卷积核还是能看到所有通道的信息的

Channel shufflfle

10.2. ShuffleNet V2

2018年的论文:ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design

官方代码:https://github.com/megvii-model/ShuffleNet-Series

论文中指出除了计算量,内存使用量(memory access cost, MAC)同样会影响计算速度。论文中还提出了四个模型轻量化的指导准则:

  • 输入输出通道数相等时,MAC最小
  • 过量使用分组卷积会增大MAC
  • 网络分支会降低并行度
  • 不能忽视元素级操作(例如ReLU、求和等)的影响

针对上述的准则,论文中提出了改进版的ShuffleNet模块

主要改进点:

  • 取消 \(1 \times 1\) 的分组卷积,而只保留 \(3 \times 3\) 的分组卷积
  • 左右两路特征图不再相加,都改为直接拼接
  • 分组打乱移到拼接操作之后

11. IGC系列

IGC系列是分组卷积的集大成者

11.1. IGC V1

2017年的论文:Interleaved Group Convolutions for Deep Neural Networks

个人基于pytorch的实现代码

交错组卷积(Interleaved Group Convolutions,IGC)分成两个部分:

  • Primary group convolutions,使用 \(3 \times 3\) 的分组卷积,主要用来提取特征
  • Secondary group convolutions,使用 \(1 \times 1\) 的分组卷积,主要用来处理通道间的相关性

这两层分组卷积是互补交错的,例如,第一层分组数为 \(L\),每个分组的通道数为 \(M\);则第二层分组数为 \(M\),每个分组的通道数为 \(L\)

论文中认为这样的互补结构可以减少网络的冗余性

11.2. IGC V2

2018年的论文:IGCV2: Interleaved Structured Sparse Convolutional Neural Networks

在V1中,一般第一层分组卷积的分组数较少,而通道数较多,这导致了第二层分组卷积的分组数较多,过于稠密。

于是,V2抛弃了原先两层分组的结构,改为若干个连续的稀疏的分组卷积,更加具体的,将其写成数学表达式为 \[ y = P_L W_L \cdots P_1 W_1 x \] 其中,\(P_l\) 表示交错重排,\(W_l\) 表示分组卷积

可以看出来和ShuffleNet的做法是很像的,只能说又撞车了。

11.3. IGC V3

2018年的论文:IGCV3: Interleaved Low-Rank Group Convolutions for Efficient Deep Neural Networks

官方代码:https://github.com/homles11/IGCV3

V3借鉴了MobileNet V2的Inverted residuals结构,再结合分组卷积,整体流程如下

  1. 进行 \(1\times 1\) 的分组卷积升维
  2. 先进行普通的分组卷积,然后重排
  3. 进行 \(1\times 1\) 的分组卷积降维至原来的维度

因为是bottleneck结构,所以上述的卷积操作都不需要加激活函数

12. CondenseNet系列

12.1. CondenseNet V1

CVPR 2018的论文:CondenseNet: An Efficient DenseNet using Learned Group Convolutions

代码实现:

denseNet+ShuffleNet的混合体。

论文中认为像denseNet那样的连接密度太高了,里面存在着很多的冗余计算,所以可以尝试加入类似ShuffleNet的分组卷积结构,降低计算的冗余。但通过实验,论文发现,如果只对 \(3 \times 3\) 使用分组卷积,对模型效果影响不大;但如果只对 \(1 \times 1\) 使用分组卷积,模型效果会下降很多。论文认为原因可能是:

  • 通道间并非独立,存在一定的顺序性及相关性,随便分配会打乱这种顺序
  • 每个通道存在着一定的多样性,如果随便分配到不相交的组,会降低特征的重用性
  • 尽管使用了shuffle的策略,但每个卷积核仍然无法看到全局的特征,这里会存在不少的信息损失

所以,要减轻分组带来的影响,一种最直接的方案就是减少分组对通道间相关性的干扰。

论文中提出一个分组的思路,对于 \(1 \times 1\) 的卷积层,训练的时候使用自学习分组卷积(Learned Group Convolution,LGC),得到一个关于输入通道的权重编码;而测试的时候直接使用该权重编码直接进行分组卷积,如下所示

其中,LGC结构如下

当模型迭代到一定的次数的时候,会进入一个mask的stage,该stage又分为浓缩(Condensation)优化(optimization)两个阶段

浓缩阶段:

  1. Filter Groups,对 \(1\times 1\) 的卷积核分组。这里的分组和ShuffleNet的对feature进行分组有所区别。前者卷积核没变,后者卷积核变小了。

  2. Condensation Criterion,计算每个分组内的各个通道的L1范式作为权值,即\(\sum_{i=1}^{O / G} |\mathbf{F}_{i, j}^{g}|\),其中,\(G\)是分组数,\(O\) 是输出通道数。

  3. Group Lasso,计算置0操作所带来的损失,用于反向求解 \[ \sum_{g=1}^{G} \sum_{j=1}^{R} \sqrt{\sum_{i=1}^{O / G} (\mathbf{F}_{i, j}^{g})^2} \]

优化阶段

  1. Condensation Factor,设定一个浓缩因子 \(C\),该值表示一共需要经过 \(C-1\) 次stage
  2. Condensation Procedure,丢弃权值较小的 \(I/C\) 个通道,其中,\(I\) 为输入通道数。这意味着最终只能拿到一个最多只保留 \(I/C\) 个有效值的稀疏卷积核
  3. Learning rate,采用cosine学习率
  4. Index Layer,保存每个分组卷积核最终的权重,这样在测试阶段,就不需要再经过前面分组卷积了,直接使用保存的权重编码即可。

12.2. CondenseNet V2

CVPR 2021年的论文:CondenseNet V2: Sparse Feature Reactivation for Deep Networks

官方代码:https://github.com/jianghaojun/CondenseNetV2

论文中认为V1中直接裁剪冗余特征过于粗暴,即使是冗余的,也有可能存在一定的信息,所以论文提出了稀疏特征重激活(Sparse feature reactivation,SFR)结构,重新利用冗余特征。对比V1的网络结构,V2的网络结构如下:

其中,SFR的结构如下:

流程伪代码(来自论文作者的论文扩展):

对比V1,V2对每个输入也做一次L1正则化,即 \(\sum_{i=1}^{I / G} |\mathbf{F}_{i, j}^{g}|\);然后根据因子 \(S\),选取权值最小的 \(O/S\) 个输出,将其置0

从论文的描述以及伪代码流程来看,是对所有的输入通道做一次筛选,怎么就是重激活了呢?但从图中来看,应该是从被丢弃的 \(I/C\) 的输入通道中做筛选,就相当于重新激活了。所以应该采用后者的做法才对。


评论
  目录