MobileNet由谷歌于2017年提出,它是一种能够用在端侧设备上的轻量级网络。GhostNet是华为诺亚实验室开发的一款轻量级网络,论文发表在CVPR2020。我认为学习论文还是要实际跑一跑代码,这样才能有更深入的体会和理解,本文首先简介两个网络的原理,然后在cifar10上进行对比试验,并展开一定的讨论分析。毕竟个人水平有限,资源也有限试验开展的不够充分,所以理解不正确的地方还请批评指正。
MobileNet论文:https://arxiv.org/abs/1704.04861
MobileNet代码:https://github.com/Zehaos/MobileNet
GhostNet论文:https://arxiv.org/abs/1911.11907
GhostNet代码:https://github.com/huawei-noah/ghostnet
一、主要原理
1.MobileNet的深度可分离卷积
MobileNet的核心是深度可分离卷积,就是把普通卷积操作分成两步:第一步称为Depthwise卷积,先对各通道进行单通道的卷积,每次输出也是单通道的特征图,再合并起来得到和输入通道数相同的特征图,这个操作比原操作大大降低了参数量和计算量(FLOPs,浮点运算数,即加法和乘法的次数),但是它没有结合各通道间的信息,所以还要第二步;第二步称为Pointwise卷积,对第一步输出的特征图进行1×1卷积,进行通道信息混合后按需要的通道数输出。
普通卷积的参数量是:
k
2
×
C
i
n
×
C
o
u
t
k^2×C_{in}×C_{out}
k2×Cin×Cout
普通卷积的FLOPs是:
2
k
2
×
C
i
n
×
C
o
u
t
×
H
o
u
t
×
W
o
u
t
2k^2×C_{in}×C_{out}×H_{out}×W_{out}
2k2×Cin×Cout×Hout×Wout
可分离卷积的参数量是:
k
2
×
C
i
n
+
C
i
n
×
C
o
u
t
k^2×C_{in} + C_{in}×C_{out}
k2×Cin+Cin×Cout
可分离卷积的FLOPs是:
2
k
2
×
C
i
n
×
H
o
u
t
×
W
o
u
t
+
2
C
i
n
×
C
o
u
t
×
H
o
u
t
×
W
o
u
t
2k^2×C_{in}×H_{out}×W_{out} + 2C_{in}×C_{out}×H_{out}×W_{out}
2k2×Cin×Hout×Wout+2Cin×Cout×Hout×Wout
通常中间层的通道数和特征图尺寸数都较大,可分离卷积的参数量和计算量主要集中在第二步1×1卷积部分,与比较常用的3×3卷积的普通卷积相比,它的参数量核计算量只有1/9。
2.GhostNet的幻影模块
GhostNet的核心是提出了GhostModule,我们暂且称为幻影模块,幻影模块也是把普通卷积分为两步:作者认为普通卷积生成的特征图中有大量冗余,所以第一步用原卷积运算先生成少部分通道数的特征图;第二步再用“廉价运算”Cheap Operation对第一步生成的特征图再简单运算生成更多的特征,把两步生成的特征图cat合并得到和原来普通卷积同样尺寸的特征图。所谓的廉价运算,就是指的单通道分组卷积,和Depthwise卷积差不多。参数量和计算量主要集中在第一步,第一步生成的通道数和原卷积通道数的比例被称为压缩比,如果压缩比为2,则参数量和计算量就大约是原卷积参数量和计算量的1/2,考虑到精度影响,根据作者的试验数据,压缩比以2为佳,不宜超过4。
由于MobileNet的深度可分离卷积通常可以实现1/9左右的压缩,所以如果仅把普通卷积替换为幻影模块,压缩量还不如MobileNet。看作者的开源代码,如果我理解没错的话,实际上是对MobileNet的1×1卷积Pointwise部分再替换为幻影模块,也就是说在压缩基础上再压缩。
二、cifar10数据试验
1.试验说明
由于cifar10的图片尺寸是32×32的,运算速度特别快,我卡只一个,人只一枚,所以就在cifar10上做一些对比试验。训练的时候没有使用各种tricks,比如数据增广、学习率调整等等,所以训练远未充分,我的主要目的是通过实际跑代码深入学习理解两个网络,并不作为测评对比指标。
使用的网络如下表:
VGG16 | VGG16(DW-PW) | VGG16(Ghost) |
---|---|---|
VGG16 开源 | 把VGG16的卷积替换为深度可分离卷积 | 替换为Ghost模块 |
ResNet34 | ResNet34(DW-PW) | ResNet34(Ghost) |
ResNet34开源 | 把ResNet34的非1×1卷积替换为深度可分离卷积 | 替换为Ghost模块 |
GhostNet | GhostNet(DW-PW) | GhostNet(Conv) |
GhostNet开源代码 | 把GhostNet的GhostModule替换为深度可分离卷积 | 替换为普通卷积 |
试验配置:
数据:cifar10, 训练集50000张32×32×3图片,测试集10000张32×32×3图片,10类。
训练:Adam(lr=0.01),batch_size=512, epoch=50, GPU: 2080Ti×1
2.试验结果
其中参数量和FLOPs仅指所有卷积层的,计算方法和代码参见我之前的博客:https://blog.csdn.net/Brikie/article/details/112646865
由于训练不充分,精度比文献给出的值低不少。
网络 | 参数量 | FLOPs | 训练速度/epoch | 验证速度 | 推理速度/单图 | 显存 | 精度% |
---|---|---|---|---|---|---|---|
VGG16 | 14.7M | 626M | 10.6s | 1.68s | 5.9ms | 4.8G | 83.9 |
VGG16(DW-PW) | 1.68M | 72.9M | 8.03s | 1.59s | 3.3ms | 3.6G | 82.1 |
VGG16(Ghost) | 877K | 40.6M | 9.97s | 1.62s | 5.9ms | 3.9G | 82.0 |
ResNet34 | 21.26M | 2.32G | 27.7s | 2.66s | 4.7ms | 6.5GB | 84.3 |
ResNet34(DW-PW) | 2.58M | 283M | 24.0s | 2.37s | 7.2ms | 9.5GB | 85.4 |
ResNet34(Ghost) | 1.44M | 163M | 32.3s | 2.92s | 4.8ms | 10.5GB | 84.8 |
GhostNet(Conv) | 19.1M | 80.7M | 6.41s | 1.48s | 7.0ms | 5.1GB | 75.6 |
GhostNet(DW-PW) | 4.81M | 15.3M | 6.38s | 1.44s | 9.5ms | 5.9GB | 75.3 |
GhostNet | 3.88M | 11.0M | 6.99s | 1.49s | 13.3ms | 5.0GB | 74.2 |
3.结果分析
(1)能够明显观察到使用深度可分离卷积以及使用Ghost模块后,参数量和浮点运算量都会明显下降。
(2)但是观察训练速度、推理速度以及显存占用都没有明显下降甚至还有上升。我认为这可能是电脑GPU上的CUDA没有专门针对可分离卷积以及Ghost模块进行优化导致的,因为加入可分离卷积或Ghost模块后虽然参数量下降,但是卷积层数变多,这导致串行运算更多,没有专门优化的时候速度反而会下降。显存为什么会变多我没有弄清楚。但可以肯定的是这些轻量级网络在端侧设备应用时还必须有专门的优化才能发挥其性能。
(3)深度可分离卷积和幻影模块加入后训练精度没有明显降低,甚至还有提高,和论文结论不一致,可能是训练不够充分没能观察到最终的结果。
三、讨论
下面的一些讨论涉及的试验数据不再给出,仅给出结论。
1,深度可分离卷积中为什么先DW后PW,反过来会怎样?
反过来也是可以的,效果没有太大的区别。
2,Ghost模块中的cheap特征毕竟是用简单运算生成的,我们想知道是否它们是必要的?如果我们直接用无参数的线性变换生成cheap特征会怎样?如果去掉它们会怎样?
试验发现cheap特征是有用的,使用全部置零的方式放弃这部分特征会降低精度。如果使用固定的线性变换生成cheap特征,即不使用含可学习参数的卷积运算也会导致精度降低。所以这些特征是必要的。