如何在手机上跑深度神经网络

这天,老板跟你说,希望能在手机上跑深度神经网络,并且准确率要和 VGG、GoogleNet 差不多。

接到这个任务后你有点懵逼,这些网络别说计算量大,就连网络参数也要 100MB 的空间才存得下,放在手机上跑?开玩笑呗。

老板又说,怎么实现是你的事,我要的只是这个功能。

你默默地点了点头。

初步尝试:MobileNet v1

问题出在哪

要在手机上跑深度网络,需要在模型参数和计算量上进行优化。

那深度神经网络的计算量和参数量主要体现在哪呢?这里以 VGG16 为例:

第一层卷积: [224 x 224 x 3] --> [224 x 224 x 64],卷积核大小为 3 x 3(简单起见,这里计算量的计算忽略激活函数)

计算量为:3×3×3×224×224×648.7×107

参数量为:3×3×3×64=1728

第二层卷积:[112 x 112 x 64] --> [112 x 112 x 128],卷积核大小为 3 x 3。

计算量为:3×3×64×112×112×1289.2×108

参数量为:3×3×64×128=73728

......

第一层全连接层:[14 x 14 x 512] --> [4096]。

计算量为:14×14×512×40964.1×108

参数量为:4096×1000=4096000

......

两相对比,同时考虑到网络中卷积层比全连层多,就不难发现深度卷积网络中的计算量主要由卷积层承包,而参数则集中在全链接层。因此,要想对模型做优化,可以在卷积层的计算上做点手脚,同时减小全连接层的维度。

Separable Convolution

虽然找到了问题所在,但具体要如何优化卷积层的计算量呢?幸运的是,你在搜索的过程中发现已经有人针对这个问题给出了解决方案:Separable Convolution。这是一种对卷积运算进行分解的方法。

以下例子摘自文末链接:卷积神经网络中的Separable Convolution

假设现在需要做这样一个卷积操作:[64 x 64 x 3] --> [64 x 64 x 4],那么通常的操作是这样的(假设卷积核大小为 3 x 3):

这种做法的计算量为:3×3×3×64×64×4=442368

参数量为:3×3×3×4=108

而 Separable Convolution 会将该操作分解为两步:Depthwise ConvolutionPointwise Convolution

Depthwise Convolution 的过程其实非常简单,顾名思义,Depthwise 就是每个通道单独做一遍卷积:

这种做法的效果是:[64 x 64 x 3] --> [64 x 64 x 3],由于是 Depthwise 的,所以只需要三个 [3 x 3 x 1] 的 filter 即可。

因此计算量为:3×3×64×64×3=110592

参数量为:3×3×3=27

不过 Depthwise 将不同通道之间的联系断开了,而且输出的通道数与输入是一样的。为了得到 [64 x 64 x 4] 的输出,还需要经过 Pointwise Convolution。

Pointwise Convolution 的过程在 Depthwise 之后进行,它是用一个 [1 x 1] 的卷积核把 [64 x 64 x 3] 的 feature map 转换为 [64 x 64 x 4]:

计算量为:1×1×64×64×3×4=49152

参数量为:1×1×3×4=12

我们发现,通过 Separable Convolution 这种分解的方法也可以拼凑出一个 [64 x 64 x 4] 的 feature map,

而这种方法的计算量为:110592+49152=159744,而总的参数量为:27+12=39

对比原先的 442368 (计算量) 和 108 (参数量),简直实惠了好多。

于是,你通过这种套路构造出了一个适合手机端运行的深度网络,并简化了全连接层的参数:

图中的 Conv dw 指的就是 Depthwise Convolution。由于是为手机设计的网络,因此你取了个形象的名字:Mobilenet。

不过,这个网络的精度会不会下降呢?你赶紧在 ImageNet 数据集上做了实验:

这个结果实在是太感人了,精度几乎和 GoogleNet 相当,但计算量却只有后者的三分之一,参数量也减少了三分之一(当然也可能是图像分类这个问题相对简单)。

为了方便对模型大小的进一步调整,你提供了两个额外的参数: αρα 又称为 Width Multiplier,主要用来控制 feature map 的 channel 数目,因为在某些任务中,很多 feature map 的 channel 可能包含很少的信息,因此少一些,而有些情况可能需要更多的 channel。α=1 时就是上文中提出的基准网络。ρ 则是图像的分辨率,由它控制输入图片的大小。

进阶:ShuffleNet v1

Separable Convolution 其实就是 MobileNet v1 的精华了,个人认为,MobileNet v1 能取得成功主要还是那些大网络在处理简单任务时存在大量的冗余,所以 MobileNet v1 用更少的参数量拼凑出同样大小的 feature map 时,性能并没有明显下降。

而 ShuffleNet v1 则是在此基础上进一步压榨卷积操作,它的重点放在了 Pointwise Convolution 上。Pointwise Convolution 的作用是把 feature map 的所有 channel 信息联系起来,但这种联系可能本身就存在冗余。举个例子,一个 [64 x 64 x 4] 的 feature map,通过 [1 x 1 x 4] 的卷积核后,可以得到 [64 x 64 x 1] 的输出,这个 [1 x 1 x 4] 的卷积核其实就是把原来 feature map 上每个位置的所有 channel 信息(一个 [1 x 1 x 4] 的通道向量)进行加权求和,得到下一层 feature map 上的一个点。不过,真的有必要融和整个通道向量的信息吗?如果只对两个通道的信息进行相加,得到的结果会比四个通道差吗?为了探究这个问题,炼丹师们把原来的 Pointwise Convolution 改造成了 Group Convolution,这个 Group Convolution 其实也不是什么新鲜玩意,当年 AlexNet 刚出来的时候,由于显存不足,就曾将卷积操作分为两组,用两张显卡来装 feature map,这种做法导致更少的参数量和计算量,而且在某些任务中并不会对性能产生很大影响。ShuffleNet v1 的炼丹师显然发现了这一点。

Group Convolution 的操作非常简单,还是举之前的例子:一个 [64 x 64 x 4] 的 feature map,要想进一步得到 [64 x 64 x 2] 的 feature map,直接用 Pointwise Convolution 处理的话,需要一个 [1 x 1 x 4 x 2] 的卷积张量。但用上 Group Convolution 后,我们可以这样操作,用一个 [1 x 1 x 2 x 1] 的卷积张量对原来 feature map 四层通道中的前面两层进行卷积操作,得到一个 [64 x 64 x 1] 的 feature map,之后,用另一个 [1 x 1 x 2 x 1] 的卷积张量继续对后面两层进行卷积操作,同样得到一个 [64 x 64 x 1] 的 feature map,这两块 feature map 拼在一起,最终得到一个 [64 x 64 x 2] 的 feature map。

仔细数数,原来 Pointwise Convolution 的计算量为:1×1×64×64×4×2=32768,参数量为:1×1×4×2=8,而现在拆成 Group Convolution 后,计算量为:1×1×64×64×2×2=16384,参数量为:1×1×2×2=4,计算量和参数量都减少了一半。

鸡贼的读者可能还发现,如果把 Group Convolution 做到极致,每个 Group 只有一个 channel 的话,就变成 Depthwise + Pointwise Convolution 了,哈哈,原来又是拼凑游戏,笑出声。

不过,仅仅用 Group Convolution,说性能不会影响很多人是不信的,毕竟本身就是 Pointwise Convolution,相邻点之间的信息已经忽略了,要是通道上的信息也忽略太多,难免会存在问题。所以,ShuffleNet v1 的 Shuffle 该登场了。炼丹师为了增强 Group Convolution 的鲁棒性,在对通道进行相加时,故意打乱了通道顺序。这样一来,在上面的例子中,本来是 1、2 通道结合得到一个新的点,就变成了 1、3 通道结合,2、4 通道结合了。

这也就是这篇论文的精华所在:

当然啦,估计是考虑到 Group Convolution 本身损失的信息有点严重,论文又特意加了 ResNet 中的短路连接,算是弥补了一点信息:

下图给出的是论文中关于 Shuffle 操作的实验:

Cls err 是 ImageNet 数据集上的错误分类率,数值越小证明结果越好,g 则表示 group 的数量。实验结果给出这样一个信息:当 group 的数量越多时,shuffle 的作用也越明显。这一点也很好理解,因为 group 越多,丢失的信息也越多,这时如果能把 channel 打散,那么不同组之间的 channel 信息就有了交流的通道,能在一定程度上增加鲁棒性。

总结

总的来说,MobileNet v1 作为第一个进行手机端优化的工作,其亮点主要是 Depthwise Convolution 和 Pointwise Convolution。ShuffleNet v1 则是在 MobileNet v1 的基础上加入了 Group Convolution,并通过 Shuffle 的方法提高鲁棒性,同时加入短路连接保持网络的表达能力。

参考

欢迎关注我的公众号「AI小男孩」,立志用大白话讲懂AI

posted @   大白话AI  阅读(2784)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示