MobileNet-V2论文:Inverted Residuals and Linear Bottlenecks, MobileNet-V2网络是由google团队在2018年提出的,相比MobileNetV1网络,准确率更高,模型更小 。
网络中的亮点
- Inverted Residuals (倒残差结构)
- Linear Bottlenecks
Inverted Residuals (倒残差结构)
普通的残差结构
Resnet 网络提供的残差结构,如下图:
- 首先对输入特征矩阵,通过
1x1 卷积进行压缩,降低channel 的大小 - 然后通过
3x3 的卷积核进行卷积处理 - 最后通过
1x1 的卷积核来扩充channel
这样就形成了,两头大中间小的瓶颈结构
倒残差结构
MobileNet-V2网络采用的是倒残差结构,网络结构如下图:
- 首先对输入特征矩阵,通过
1x1 卷积进行升维,增加channel 的大小 - 然后通过
3x3 的DW 卷积核进行卷积处理 - 最后通过
1x1 的卷积核进行降维
可以看出:普通的残差结构 先通过1x1卷积进行降维 ,最后通过1x1卷积升维 ;倒残差结构 刚好相反,首先通过1x1卷积进行升维 ,最后通过1x1卷积进行降维 ,所以它和我们普通的残差结构正好是相反的,因此取名(Inverted residual block )倒残差结构。
还有一个要注意 的是:普通残差结构使用的激活函数是relu ,但倒残差结构使用的是relu6 激活函数。
ReLU6激活函数
- 对于
ReLU 激活函数,当我们的输入值小于0的时候,默认都将它置0.当输入值大于0的时候,输出值跟输入值一样,不做处理 - 对于
ReLU6 激活函数,同样当我们的输入值小于0的时候,默认都将它置0.在[0,6]区间内我们也同样不会改变它的输入值,但是当输入值大于6的时候,就会将输出值置为6.
Linear Bottlenecks
在原文中,倒残差解雇最后1x1 卷积层,它使用了线性激活函数,而不是我们之前所说的ReLU 激活函数。为什么要这么做呢 ,在原论文中作者进行了相关实验。 假设我们输入的是二维矩阵,channel=1.分别使用不同的矩阵
T
T
T将它变换到不同维度上,在使用ReLU 激活函数进行输出,然后在使用逆矩阵
T
?
1
T^{-1}
T?1将它还原为2D的特征矩阵。当我们的矩阵
T
T
T的维度是2和3的时候对应的是图中output/dim=2 和output/dim=3 ,这两幅图。通过这两幅图我们可以知道当还原为2维矩阵会丢失很多信息。但随着矩阵
T
T
T维度不断加深丢失的信息就越来越少。
通过该实验可以了解ReL激活函数对低纬特征造成大量损失 , 由于我们倒残差结构是两头细中间粗 的结构,所以输出的时候是一个低纬的特征。为了避免信息的丢失我们就需要使用一个线性的激活函数替代ReLU激活函数。
对于倒残差结构,首先通过1x1 卷积,它的激活函数为ReLU6 ;紧接着通过DW 卷积,卷积核为3x3 ,它的激活函数为Relu6 ,最后在通过再通过1x1 的卷积处理,使用的是Linear 激活函数而不是ReLU6 激活函数,也就是对应于表中所给的每一层信息。
首先对于输入特征为h x w x k (高、宽、channel), 使用1x1 的卷积核对它进行升维处理,经过升维后,输出特征矩阵的channel变为tk ,t 表示扩充因子。紧接着第二层,它的输入对应于上一层的输出h x w x tk ,使用DW 卷积,卷积核为3x3 步距为s ,激活函数为ReLU6,经过DW卷积,它不会改变channel 的大小,输出的channel 和输入是一样的,同时由于我们步距为s ,因此输出特征矩阵h,w变为原来的1/s倍。最后通过1x1 的卷积层,使用Linear激活函数,进行降维操作,降维后输出的channel个数为
k
′
k^{'}
k′.
注意 : 在MobileNetV2版本中,它的倒残差结构,并不是每个倒残差结构都有shortcut 分支(捷径分支),只有当stride=1 且输入特征矩阵与输出特征矩阵的shape 相同时才有shortcut分支。
MobileNet-V2 网络结构
网络结构图图中参数说明:
- t是扩展因子
- c是输出特征矩阵深度channel
- n是
bottleneck 的重复次数, bottleneck 这里指倒残差结构 - s是步距
其中这里的s 代表的是每个block (多个bottleneck组成)第一层bottleneck的步距 ,其他都是为1的 ),比如这里表中第3行对应n=2 的时候,对应的bottlenec k需要重复2遍的,对它而言,它的第一层bottleneck步距是为2的,它的第二层步距s是等于1的。 另外需要注意的是,在网络结构图中第一个bottleneck,它这里的t 是等于1 的,也就是说扩展因子为1,就是说第一层卷积层对输入特征的深度是没有做调整的,并且这层的步距s=1 。 tensorflow 和 pytorch 官方实现是没有使用1x1 的卷积的,直接使用后面的DW 卷积的,因此第一个bottleneck中的1x1 卷积是可以不要的。
举例说明:只有当stride=1 且输入特征矩阵与输出特征矩阵的shape 相同时才有shortcut分支。 对于图中红框标出的block ,总共有3个bottleneck ,它的第一层肯定是没有shutcut 分支的,因为输入特征channel 是64 ,输出channel 为96,输入输出特征矩阵channel 是不相等的,没法使用shutcuts的add 操作。对于第二层,它的步距还是等于1 的,我们说过这里的步距s 只针对第一层,其他层s 都为1.然后它的输入特征矩阵是上一层的输出特征矩阵的channel ,即channel 为96,然后它的输出特征也是等于96的,因此输入输出的特征矩阵尺寸和channel 都一样,因此可以通过shortcuts 进行相加。
最后一层是一个卷积层1x1x1280 ,这里的卷积层就是一个全连接层。这里的k 对应于我们的分类个数
网络的性能对比
MobileNet-V2 论文中给出了网络性能对比
分类任务
对于MobieNet V2 Top1 准确率为72.0 ,相对于MobieNet V1准确率为70.6,准确率提升了。同时参数,运算量和运算时间都明显比MobieNet V1更加优秀。在cpu上MobieNet V2 运算时间只有75ml,基本上可以实现在移动设备上实时推理效果。
当卷积核倍率因子为1.4 时,MobieNet V2 TOP1 准确率达到74.7 ,比论文中其他网络的准确率高
目标检测论文
在论文中,将MobileNet V2与我们的SSD进行联合使用的,也就是说将我们MobileNet当作我们的backbone,并将SSD当中的一些卷积层也换成了我们深度可分(DW+PW )卷积,相比于最原始的 SSD300、SSD512,YOLOV2 ,以及MobileNet V1+SSD ,它的准确率为22.1%比YOLO V2要好,其中参数,运算量,运算时间都是最优的,在CPU中检测时间达到了200ms.随着MobieNet网络的提出,实现了在移动识别、嵌入式设备中跑我们的模型了。
|