点击我爱计算机视觉标星,更快获取CVML新技术


本文作者为姚旭峰,原载于知乎:

https://zhuanlan.zhihu.com/p/81975819

已获作者授权转载,禁止二次转载。

我在Gammalab的时候工程组有个特别聪明的同事叫金戈,人特别聪明,时常会问我一些我答不上来的问题。比如今天他就问我:“旭峰,人脸检测为什么要用三通道来做呢?灰度图应该够用了吧?”

我想了半天不知道怎么回答他,于是说:“产品经理问的?”

金哥回复我说:“我就是在思考如果产品经理问我我该怎么回答。”

我…

anyway,本篇新坑就以金哥为榜样来学习一下模型压缩。模型压缩是工程化必不可少的技术,可以说AI越落地,人们就越会关心模型压缩。模型压缩有多种技术,包括结构,量化,剪枝,蒸馏及各种其他方法。本文先从最基本的模型结构开始。

经典的模型结构论文包括:

MobileNet_v1: MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications

https://arxiv.org/pdf/1704.04861.pdf

MobileNet_v2: MobileNetV2: Inverted Residuals and Linear Bottlenecks

https://arxiv.org/abs/1801.04381

MobileNet_v3: Searching for MobileNetV3

https://arxiv.org/abs/1905.02244

ShuffleNet_v1: ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices

https://arxiv.org/abs/1707.01083

ShuffleNet_v2: ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design

https://arxiv.org/abs/1807.11164

IGC_v1: Interleaved Group Convolutions for Deep Neural Networks

https://arxiv.org/abs/1707.02725

IGC_v2: IGCV2: Interleaved Structured Sparse Convolutional Neural Networks

https://arxiv.org/abs/1804.06202

IGC_v3: IGCV3: Interleaved Low-Rank Group Convolutions for Efficient Deep Neural Networks

https://arxiv.org/abs/1806.00178

SqueezeNet_v1: SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <0.5MB model size

https://arxiv.org/abs/1602.07360

SqueezeNext: SqueezeNext: Hardware-Aware Neural Network Design

https://arxiv.org/abs/1803.10615

本文我们会从基础讲起,从头学习,作为一个入门的小综述吧。

模型压缩主要考察两个指标,Params 和Flops,其中Params指的是模型的参数,因为我们训练模型一般都是以float32为精度的,所以模型大小一般是参数的4倍。Flops全称为floating point operations per second。意指每秒浮点运算速度。所以Params和Flops分别度量了模型的大小以及其算数。我们做模型压缩,目标就是使Params和Flops尽可能地小。

金哥:但是我们工程当中…

我:你不要问这种我答不上来的问题,工程的环境是复杂的,我们这边就单单讨论Params和Flops。

好,我们继续,既然制定了metrics,让我们回忆一下标注卷积的Params和Flops吧。

如图所示,在一个标准的conv当中,我们的Params和Flops应该为:

Params:(K_h * K_w * C_in)* C_out

其中K_h和K_w 代表了kernel的input_size, C_in是input feature map的channel数,C_out是output feature map的channel数

Flops: (K_h * K_w * C_in * C_out) * (H_out * W_out)

其中H_out和W_out 分别代表了output feature map的size

在全连接层中,对应的Params和Flops分别为:

Params:C_in * C_out

Flops:C_in * C_out

金哥:你是不是忘记把bias给加上了?

我:由于bias网上貌似本身也有些分歧,这里暂时就先忽略不计。

金哥:为什么卷积的params和Flops和全连接计算不同?

我:好问题,要不你思考一下?为什么卷积的计算方式和全连接不同,以及这种不同会造成什么样的影响和优化方式呢?

介绍完标准卷积的计算方式,我们接下来介绍一下模型压缩中的经典方法Group Conv, 可以说,理解了Group Conv,也就算对模型压缩入门了。

所谓Group Conv,其实就是把input feature进行分组计算,为什么要进行这步操作呢?因为早期大家都比较不富裕,显存不够,只好想歪招进行分组训练。我们来看一下Group Conv的Params和Flops:

Param:G * (K_h * K_w * C_in / G) * (C_out / G) = K_h * K_w * C_in * C_out / G

Flops:K_h * K_w * C_in * C_out * H_out * H_in / G

其中G为group数。

通过公式我们可以发现,只要G足够大,Params和Flops就足够小。经典的MobileNet就是把Group Conv的一个特例,在MobileNet,G设置为了input feature map的channel数。

具体group conv怎么用呢,也很简单,我们看一下pytorch的参数:

其中groups就代表了分组数,解释得很清楚了吧,金哥你有什么问题吗?

金哥:Group Conv有什么理论依据吗?还是仅仅为了减少参数而被应用的?

我:好问题,我们稍后就分析。还有吗?

金哥:有,你有没有觉得你的字实在是太难看了?

我:有。

金哥:那你还写?

我:我只是以前看别人写觉得很好看….

好了我们不纠结字的问题了,回归主题,group conv究竟有没有道理呢?我们通过一个经典的backbone来重新认识一下group conv——resnext。在resnext中,作者总结了一种神经网络的范式:split-transform-merge,以经典的Inception为例,我们看一下Inception的经典结构:

可以看到,Inception在一个input上有不同的分支(也就是不同的group)来进行不同的非线性变换来获取不同的feature特征进行融合以获取更好的特征。他的操作方式为:1)split:先把feature转换为一个low-dimension的特征向量,在Incetion中,就是conv1*1;2)transform:运用不同的transform方式进行非线性变换;3)merge:融合特征,获得了更好的特征表示。

Split-transform-merge的核心在于(其实也就是Inception的核心),在计算复杂度比较低的情况下,获取和那些密集复杂网络相同的特征表示能力。但是Inception的问题在于,他人工设计的痕迹太重,因此在resnext中,作者把网络的blocks改成了:

其中a是resnext的网络结构,b是Xception的网络结构,c是原始的resnet。我们可以发现,其实Xception和Resnext非常像,两者的思想也非常接近。

金哥:那你为什么要用resnext举例子?

我:你看看resnext最后一个作者,是我校友好吗?

金哥:那你就是瞧不上google咯?

我:google爸爸要我我肯定真香啊。

金哥:你这人怎么这么没用原则…

好吧,让我们看一下resnext的效果:

在相似的参数条件下,resnext的效果要显著好于resnet。

进一步思考,为什么resnext这种结构更加优秀呢?首先,group conv最让人觉得困惑的地方其实在于,在一般的CNN中,卷积的channel其实是相互作用的。Group conv,极端一点,把G设置为input feature的通道数的话,其实就完全孤立了各个通道,这显然也是不符合常识的。那为什么依旧使用group conv这种操作呢?一种可能性是,就如同卷积大获成功的原因之一是,我们运用卷积能有效地抽取局部特征(因此代替了全连接)。那通道是否也有这样的性质呢?显然,不是每个通道都应该获得同样的关注。

2017ImageNet的冠军SENet就提供了一种通道关系的解决方案:

SENet的block其实也非常简单,对于一个input feature map 分成两支,一支是先经过Global Average Pooling加一个全连接层过sigmoid转换为一个关系向量,另一支直接过网络,然后把过sigmoid后的权值乘到channel上以控制channel的重要性。

今天看来这个结构相当简单,类似attention的思想也比较符合常识。当然,我们也需要意识到的是,这个结构的成功是基于ImageNet这样大规模的数据集上的,普通小数据集用这样的attention,很可能调参不成反被惨虐。

当然,这个模型结构的成功一定程度上说明了某些channel是冗余的,因此group conv还有一种可能不错的解释就是,一定程度上防止了过拟合?

金哥:你这么说你心里不慌呢?

我:不慌…

Ok,铺垫了这么多,让我们来进入正题,看一看经典的小模型框架。我们从MobileNet_v1开始入手。

MobileNet_v1的核心在于两点,Depthwise + Pointwise

如图所示,左边是经典的一个小block,右边是MobileNet_v1的block。其中DepthWise其实就是Group Conv的一个特殊版。

Params:K_h * K_w * C_in

Flops: (K_h * K_w * C_in) * (H_out * W_out)

和标准的卷积相比,参数量少了C_out倍。正如前文所说,独立的通道也是有问题的。因此MobileNet_v1巧妙地加上PointWise,也就是1*1的conv层,既可以把维度调整到和其他的backbone一致作为对比,也可以使打通通道,好操作。通过Depthwise及Pointwise的操作,参数量下降了:

嗯,这个倍数…..其中D_k代表了kernel_size, D_F代表了output的feature size。

当然,良心的google还为广大工程师提供了两个超参,分别是Width Multiplier宽度乘子及Resolution Multiplier分辨率乘子。其中宽度乘子主要控制input_channels和out_channels的数目,一般来说设置为[1, 0.75, 0.5],于是整体的参数就可以计算为:

来看一下效果:

可以看到,当乘子为0.75和0.5时,网络依旧能保持不错的性能,amazing!

分辨率因子也很好理解,通过缩小图片分辨率减少计算量,我们也来看一下实验效果:

由实验可以看出,图片分辨率的降低并没有显著降低精度。这个现象符合常识吗,特别是ImageNet这种有1000类标签的大数据集?暂时没有想到合理的解释,也希望有大神推荐一下相关的paper。后面实验各种nb的结果就不放了,大家有兴趣可以自己去看一下。

OK,我们来总结一下MobileNet_v1, 巧妙地利用了Depthwise + Pointwise的结构,既降低了参数量,又使模型保持了不错的信息特征。各种实验也印证了这的确是个好backbone。现在问题来了,baseline这么优秀,后面人怎么吃饭呢?

事实证明总有大神能够突破创新的,让我们一起来看一下ShuffleNet_v1吧。讲ShuffleNet前,我们不妨想想MobileNet还有什么问题,我们从Params的角度来分析一下:

这是MobilNet_v1的参数分布,可以看到,Conv1*1占据了大量的参数量。因此,如何有效地降低Conv1*1是最大的问题。

根据我们前面的分析,当想减少参数的时候,Group Conv是种非常有效的手段,但是Group Conv的缺点在于,无法有效地使通道之间交换信息,在MobileNet中是用Conv1*1解决了这个问题,但是我们本身的目的就是为了解决Conv1*1参数量过高的问题,怎么办呢?ShuffleNet提出了Channel Shuffle for Group Conv来解决这个问题。

首先,让我们来看一下总体bottleneck上的改进:

可以看到,最左边其实是MobileNet_v1的结构。ShuffleNet首先把conv1*1换成了Group Conv1*1,大大缩减了计算量,其次用Channel Shuffle的方法打破了Group之间的孤立状态,之后再连上DWConv3*3以及GConv1*1,参数量我就不写了,眼见的在各个环节上都有降低,并且实实在在解决了Conv1*1的问题。

接下来我们来分析一下神秘的Channel Shuffle到底是怎么一回事:

非常简单的思路,从Group Conv得到feature进行concat后把所有feature map打乱shuffle传递到下一层以进行不同group的信息沟通,好想法,非常简单有效。但是这个shuffle规则是人工设置的,感觉还是并不合理。并且实现相当困难,在此给旷世的团队鼓鼓掌,的确厉害。

感受一下这个恐怖的Flops:

看一下模型效果:

其中1,0.5代表了channels数scale的设置,越小则channel相应越小。可见在较小的模型中,channels越少则效果越差(显然),group数越多反而效果越好。看一下论文的解释:

ShuffleNet后文还有大量翔实的实验,比较有兴趣,这里不多介绍了,大家可以去当个彩蛋看一下,非常有意思。

大概花了差不多一天不到的时间学习并整理模型压缩的结构篇,说实话还是蛮累的。最缺的是实验验证以及代码的理解,这些以后有机会慢慢补上。噢,差点忘了金哥了,金哥你有啥要补充的。

金哥:那之前立下的MobileNet_v2, ShuffleNet_v2, Mobile Net_v3 这些flag呢?

我:em….让我们下次再好好讨论吧!


模型压缩与应用部署交流群

关注最新最前沿的轻量级模型设计、压缩、减枝、AI推断技术,扫码添加CV君拉你入群,(如已为CV君其他账号好友请直接私信)

(请务必注明:部署)

喜欢在QQ交流的童鞋,可以加52CV官方QQ群:805388940。

(不会时时在线,如果没能及时通过验证还请见谅)


长按关注我爱计算机视觉

金哥和你一起学模型压缩——结构篇相关推荐

  1. 降低预测过程计算成本,这些NLP模型压缩方法要知道

    编译 | 凯隐 出品 | AI科技大本营(ID:rgznai100) 近年来,基于谷歌Transformer的语言模型在神经机器翻译,自然语言推理和其他自然语言理解任务上取得了长足进展. 通过多种语言 ...

  2. 深度学习模型压缩与加速综述

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 导读 本文详细介绍了4种主流的压缩与加速技术:结构优化.剪枝.量化 ...

  3. 一文看懂深度学习模型压缩和加速

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:opencv学堂 1 前言 近年来深度学习模型在计算机视 ...

  4. 娓娓道来!那些BERT模型压缩方法

    本文约3000字,建议阅读10+分钟 本文主要介绍知识蒸馏.参数共享和参数矩阵近似方法. 作者 | Chilia 哥伦比亚大学 nlp搜索推荐 整理 | NewBeeNLP 基于Transformer ...

  5. 浅谈模型压缩之量化、剪枝、权重共享

    之前陆陆续续看了许多模型压缩相关的文章,自己业务中也接触过一些相关的客户,今天周末没事做,把模型压缩相关的内容整理一下做个分享.可能更多地从科普的角度去介绍,因为我也不是专业做这方面技术的研究. 首先 ...

  6. 【视频课】深度掌握模型剪枝+模型量化+知识蒸馏3大核心模型压缩技术理论!...

    前言 欢迎大家关注有三AI的视频课程系列,我们的视频课程系列共分为5层境界,内容和学习路线图如下: 第1层:掌握学习算法必要的预备知识,包括Python编程,深度学习基础,数据使用,框架使用. 第2层 ...

  7. 【BERT】BERT模型压缩技术概览

    由于BERT参数众多,模型庞大,推理速度较慢,在一些实时性要求较高.计算资源受限的场景,其应用会受到限制.因此,讨论如何在不过多的损失BERT性能的条件下,对BERT进行模型压缩,是一个非常有现实意义 ...

  8. 可真有你的!EasyEdge模型压缩新姿势……

    近年来,深度学习技术在诸多领域大放异彩,因此广受学术界和工业界的青睐.随着深度学习的发展,神经网络结构变得越来越复杂.复杂的模型固然具有更好的性能,但是高额的存储空间与计算资源消耗使其难以有效地应用在 ...

  9. 四篇NeurIPS 2019论文,快手特效中的模型压缩了解一下

    在即将过去的 2019 年中,快手西雅图实验室在 ICLR.CVPR.AISTATS.ICML 和 NeurIPS 等顶会上发表了十多篇论文. 除了这些研究方面的成果,针对实际业务,西雅图实验室和快手 ...

最新文章

  1. vue 圆形 水波_vue项目百度地图+echarts的涟漪水波效果
  2. python中argsort_浅述python中argsort()函数的实例用法
  3. Go 语言编译过程概述
  4. JavaScript继承理解:ES5继承方式+ES6Class继承对比
  5. 使用tcpdump找出PP用户
  6. 双拼输入法是个啥以及我是如何学会使用它的
  7. 测试人员应该具备的几种思维
  8. Nvidia Jetson AGX Xavier 安装 Swin-Transformer-Object-Detection
  9. 个人收集的mac破解软件免费下载(不断更新中)
  10. C++三种方法求解两个数最大公因数和最小公倍数
  11. 信息学奥赛一本通 1947:【09NOIP普及组】细胞分裂 | 洛谷 P1069 [NOIP2009 普及组] 细胞分裂
  12. poj3580:SuperMemo(块状链表/Splay)
  13. 【C/C++】共用体(union)
  14. 为知一而学十,人生而孤独
  15. 不惑之年一次性通过软考高项的苦与乐
  16. 打开运行PS、AI等软件时卡在启动窗口的解决办法
  17. 科技热点周刊|Linux 30 周年、Horizon Workroom 发布、Humanoid Robot、元宇宙
  18. java a201游戏_A201 Java Spring+SpringMVC+MyBatis开发教育网站视频教程
  19. java测量麦克风音量_Android-使用mediarecorder类获取当前麦克风音量值
  20. Windows 安装 JDK 与环境变量配置

热门文章

  1. MySQL之慢查询日志和连接管理
  2. 汇编8086CPU常用指令——详解
  3. android sdk no space,Android SDK folder taking a lot of disk space. Do
  4. mysql删除不安全的账户_【20200407】MySQL账号不规则删除导致权限错误
  5. Jenkins加上linux slave出现[SSH] Connection closed.问题
  6. python word模板 图_科学网—Python绘制可插入Word的高清矢量图(SVG转EMF) - 任晓东的博文...
  7. linux apache目录权限配置,Linux系统架构-----Apache的用户访问权限的设置
  8. php 下拉菜单 不提交 选中的值,在html中怎样可以做到下拉菜单提交后保留选中值不返回默认值...
  9. amaplocation无法获取高度_kali一款高度可定制的WiFi钓鱼工具 WiFiPhisher
  10. idea新建类包图标_IntelliJ IDEA 常见文件类型的图标介绍