论文:Run, Don’t Walk: Chasing Higher FLOPS for Faster Neural Networks
先熟悉两个概念:FLOPS和FLOPs(s一个大写一个小写)
FLOPS: FLoating point Operations Per Second的缩写,即每秒浮点运算次数,或表示为计算速度。是一个衡量硬件性能的指标。
FLOPs: FLoating point OPerationS 即 浮点计算次数,包含乘法和加法,只和模型有关,可以用来衡量其复杂度。
总结起来,S大写的是计算速度,小写的是计算量。计算量 / 计算速度 = 计算时间Latency
摘要部分
之前很多网络都聚焦在减少计算量(FLOPs)上,但是作者发现即使FLOPs减少了,latency也没有相应地线性减少。
认为这是由于速度FLOPS并没有相应地提高,而较低的FLOPS是由于频繁地访问内存。
为此,paper主要研究了DWConv(Depthwise convolution).
提出了部分卷积PConv. 可以同时降低FLOPs和提高FLOPS,进而提高速率。
又提出了以PConv为主要元素的backbone网络FasterNet, 有T,S,M,L版本,在提高效率的同时也提高精度。
背景
对比一些降低了计算量FLOPs的网络,它们的计算速度FLOPS对比,作者发现它们大部分的FLOPS比ResNet50都低。
因为Latency = FLOPs / FLOPS.
所以即使降低了FLOPs,而FLOPS较低,也不会缩短相应的计算时间。
相关工作
CNN:
在实际应用中,CNN的计算效率和精度一样重要,所以有很多改进效率的工作,
较流行的是group卷积和深度可分离卷积,应用它们的有MobileNet, ShuffleNet, GhostNet等。
这些工作通过考虑filter的冗余,减少参数和FLOPs。但是为了补偿下降的精度,一般会增加channel,而channel的增加会导致内存访问量的增加。
而作者通过考虑feature map的冗余,提出部分卷积PConv,降低FLOPs, 同时降低内存访问量。
ViT,MLP和变体
很多工作致力于改进ViT的结构和训练方式,主要的趋势是通过降低attention, 卷积的复杂度,追求一种精度和计算时间的平衡。
还有工作把attention换成MLP。不过这些常演变成类似于CNN的工作。
作者根据以往paper认为attention相比于CNN的优势还不清晰,而且attention比CNN要慢,在工业界没有CNN那么受欢迎。
目前深度可分离卷积仍然比较流行,所以作者就专注研究DWConv, 找出困扰FLOPS的点。
对深度可分离卷积不太熟悉的可参考MobileNetV1。
内存访问量
之前提到FLOPS受限于内存访问量,下面就看一下内存访问量。
假设input size为:(c, h, w), 卷积核为k*k, output size为(c, h, w)
那么DWConv的FLOPs为
(卷积核窗口移动次数为output size, 每次计算量为k2 *c,不需要扩张channel)
普通卷积的FLOPs为
(卷积核窗口移动次数为output size, 普通卷积会把channel扩张后计算,参见下图,因为input 和output channel都是c, 所以扩张后为c2)
深度可分离卷积中DWConv后面会跟一个1x1卷积,即PWConv(pointwise convolution)。
深度可分离卷积不能算是普通卷积的替代品,因为精度会下降,对此实际应用中会增加channel作为补偿。
channel也称为网络宽度,假设DWConv的channel增加到c’ (c’ > c), 例如在inverted residual blocks中channel就扩张了6倍。
channel的扩张增加了内存访问量,增加时间延迟,尤其是I/O-bound设备。
这里访问图片/特征图 和 卷积filter的内存访问量为:
DWConv:
普通卷积:
其中h * w * 2c’是I/O操作的内存访问,很难再进一步优化(乘2是访问input和output内存,假设了它们size相同)。
提出部分卷积PConv
部分卷积如下图,不同于以往对input的所有channel都做卷积,PConv只对其中一部分channel cp做卷积,剩下的放在那不去处理。
为什么可以只做部分卷积而不影响精度?
是由于作者观察到不同channel的feature map高度相似,如下图。这个feature map的冗余在其他的paper中也提到过。
这是一个预训练的ResNet50的特征图。
既然特征图这么多冗余,不如只用其中的一部分进行卷积。
为了内存的连续性,选取前段或后段连续cp个channel,用来代表整个特征图。
仍然假设input和output 的channel一样,那么PConv的FLOPs为
(卷积核和input map一个窗口计算量为k2 * cp2(普通卷积计算),卷积核窗口移动次数为output size)
如果cp / c = 1/4, 那么PConv的FLOPs就仅为普通卷积的1/16.
PConv的内存访问量:
(input,output feature map 和 卷积核内存访问)
如果cp / c = 1/4, 那么内存访问量将是普通卷积的1/4.
既然只取1/4的input channel, 那是不是可以把剩下的channel移除?
如果移除,就变成了更少channel的普通卷积,不再是部分卷积了;而且留着这些channel可以让后续的PWConv利用起来。
既然说到了后续的PWConv。
PConv接PWConv(1x1卷积)
前面说到PConv只利用了一部分channel, channel没有被充分利用啊。
这时后面再跟一个PWConv就可以充分利用channel信息。
PConv和PWConv的结合体有点像T型的卷积,如下图。感受野集中在中间位置。而普通卷积是均匀分布的。
那么感受野集中在中间有没有影响呢?为此作者调查了一下ResNet18的每一个filter,
用Frobenius norm计算重要性,卷积核size为k2 * c。值越大认为越重要。
然后统计出来下面的直方图,3x3的卷积核位置依次为1~9,
从图中大致认为中间的位置5重要性最高,因此认为上面的T型卷积应该可以近似普通卷积。
虽然T型卷积可以直接计算,不过作者认为拆分成PConv和PWConv更好,可以利用中间卷积的冗余性,而且进一步降低FLOPs.
假设input和output的size都是(h,w,c), 那么T型卷积的FLOPs为
拆分成PConv和PWConv的FLOPs为
FasterNet
作者提出了一个用PConv构建出来的backbone网络FasterNet, 结构尽可能simple.
结构图如下,4个stage.
其中embedding layer是一个4x4 conv, stride=4, 相当于一个卷积核对图片的每一块处理。
merging layer是2x2 conv, stride=2, 相当于把前面分割成块处理的图 有overlap地合并起来。
这样做也可以下采样,扩张channel.
观察到最后2个stage中的block访问内存较少,有较高的FLOPS, 所以相对地把后2个stage多放一些blocks.
每个PConv跟2个1x1卷积,加上residual.
BN层和激活函数仅放在中间的PWConv后面,以保持feature多样性,降低复杂度。
选择BN而不是其他的归一化是因为BN可以和Conv层结合到一起。
激活函数的选择也是根据实验得来的,小模型用GELU,大模型用ReLU.
同样实验得到 cp / c 最好是1/4.
几种卷积在不同平台上FLOPS, latency对比
为了验证PConv是不是真的比DWConv更近似于普通卷积,
作者把ResNet50的4个stage中 每个stage的第一个3x3 conv的input, output 特征图提取出来。
分成train, val, test集,用不同卷积组合训练之后,再用test集测试output特征图的MSE loss.
当然是loss越小,这个卷积组合就越近似于普通卷积(但是比普通卷积更快)。
在COCO数据集上的latency和mAP对比。
最后贴上FasterNet的结构。