跳到主要内容

轻量级 CNN — 给卷积算参数账

这一章讲三件事: 深度可分离卷积这笔约九分之一的账怎么算出来; 小通道上 ReLU 丢信息的发现如何催生「反转残差」;以及从 FLOPS 到真实运行时间的 评估觉醒——四条设计律把前面所有网络挨个批评了一遍。

1. 这一章讲什么

前四章的通天塔越盖越高,这一章换方向:不大幅度降低准确率的前提下,把模型做小做快。 提速只有两个抓手——减少参数的数量,减少整个网络的计算量1。用处也实在: 模型文件小,好保存好传输;参数少,占的存储少2

这一章的六个算法(算法:一套写死的计算步骤;每个网络名背后都是一套)其实是一条「拆卷积」的演化线:先横拆(按通道拆开各自卷), 再按组拆(几通道一组),最后连「哪些连接该留」都交给训练自己学。

2. 顶层全景:一笔乘法账

普通 3×3 卷积(输入 M 通道 → 输出 N 通道)
参数 = 3×3×M×N ← 通道全连通,最贵

拆成两步:
① 深度卷积:每通道一个 3×3 核,各卷各的 参数 = 3×3×M
② 点卷积: 1×1,把 M 个通道混合成 N 个 参数 = M×N
合计 ≈ 3×3×M + M×N ≈ 原来的 1/9(3×3 核时)

图说:跨通道的「混合」被推迟到 1×1 里做,空间滤波与通道混合两步分离。
这就是 MobileNet、Xception、ShuffleNet 共同的地基。

主走查就是把这笔账走全程(3.1 节),外加书里自己跑的一组 MNIST 实验: 普通卷积网络改造成 MobileNet v1 后,卷积部分参数从 239 936 降到 29 1843

3. 核心原理

3.1 SqueezeNet 与 MobileNet:把账算出来

先看一次失败的营销课。SqueezeNet 号称「参数约是 AlexNet 的 1/50」4, 三招:3×3 换 1×1(单个卷积参数变 1/9)、压 3×3 的通道数、把降采样往后挪 (大特征图信息多,但计算量大增)5。书里的揭穿很精彩:AlexNet 的参数大头 根本不在卷积,而在那两层巨大的全连接——「参数的减少和 SqueezeNet 的设计并没有关系」, 去掉全连接后合理的对比是 1/3 而非 1/50;论文标题里那个 0.5MB 还要靠另一篇深度压缩论文 的算法才做得到6。教训:对比要跟同部分的账比,不能拿别人的错当自己的功

真正的账王是 MobileNet v1。深度卷积就是不跨通道的卷积:每个通道配一个独立的 小核,各卷各的,通道之间零交流7;点卷积就是 1×1 卷积,专职把 M 个通道 混合成 N 个、顺便升维降维8。两步相加,参数是 3×3×M + M×N——对 3×3 核来说, 参数和计算量都约为普通卷积的九分之一9。书里的对照实验同样干脆: 同一网络改造前后在 MNIST 上跑,效果略降(参数少了,可以理解),但速度账有个意外—— GPU——就是那块做并行计算的显卡——上反而更慢!原因是 cuDNN 对深度卷积的并行优化没跟上,「是底层框架训练速度慢, 并不是 MobileNet 算法训练速度慢」(书里原话带 v1)10算法账和框架账 是两本账。

3.2 MobileNet v2:小通道上的信息黑洞

v2 给 v1 动了两次手术,刀刀都来自同一个发现。书里借数据处理不等式(第 02 章)论证: ReLU 一定带来信息损耗,「而且这种损耗是没有办法恢复的」;通道数越少,损耗越狠 ——书里的小实验:低维数据过 n 个 ReLU 再试图还原,n 小时还原得很差,n 大时才像样11

手术一:线性瓶颈。既然不能全换线性(网络会塌成一层),那就只在通道数最少的 瓶颈位置用线性激活,其他地方照旧 ReLU12。手术二:反转残差。传统残差块 先压缩再扩张(两头粗中间细);v2 反过来,先把通道扩张 t 倍(实验 t=6),在宽处做 深度卷积,再压回瓶颈——「捷径被转移到了瓶颈层」13。传统残差像漏斗, v2 像沙漏,书里画了一张对子图14。配上 MobileNet 系的 ReLU6(把 ReLU 的输出 截断在 6,防止小模型数值漂)15,这就是后来几乎所有轻量网络的积木。

3.3 Xception 与 ResNeXt:同一笔账的两种视角

Xception 的名字就是「极端的 Inception」:第 02 章的 Inception 是「1×1 分组后再接 3×3」,把分组推到极致——每组只剩一个通道——就得到「逐通道 3×3 + 1×1 混合」, 与深度可分离卷积几乎等价。两个差别:Xception 先点卷积后深度卷积(顺序相反), 且瓶颈处用线性激活(承 v2 的发现)16。同一个拆法,MobileNet 从「拆普通 卷积」推出,Xception 从「解耦 Inception」推出——独立发现,殊途同归17

ResNeXt 则拿走了「拆」的中间档:分组卷积——通道分成几组,组内普通卷积, 组间不通信18。它把 Inception 各分支「人工雕琢」的不同拓扑统一成同一结构, 用一个数(基数,组数)控制折中程度19。书里的点评两面都记:同等条件下 ResNeXt 速度应更好(相同拓扑对 GPU 友好),但「在更多的环境中我们发现 Inception v4 的效果 是优于 ResNeXt 的」——废掉不同感受野的多样性,「不是很合理」20。 分组卷积的隐患也埋在这:组与组之间没有信息交换——这正是下一节的靶子。

3.4 ShuffleNet:给分组卷积通电话

ShuffleNet v1 的靶子链条:深度可分离的瓶颈在点卷积;ResNeXt 改成组内点卷积省了账, 但「网络趋近于由多个结构类似的网络构成的模型」,准确率大打折扣21; 于是补一个几乎不花钱的操作——通道洗牌:把分组特征图按固定规则重新排一次座,让下一层的组 混合了上一层的各组。书里给了一维例子:9 个通道 3 组,洗完之后从 [0,1,2,3,4,5,6,7,8] 变成 [0,3,6,1,4,7,2,5,8]——每组都沾到别人组的血统, 而且「步步可微分」,不破坏训练22。g=1 时 ShuffleNet 退化为 Xception23

ShuffleNet v2 则做了一件更重要的事:换评估指标——指标,就是给模型打分用的那把尺。 书里原话:FLOPS 这种普遍的评估方式「是非常不合理的」——真实运行时间里计算只占一半,内存读写、GPU 并行、文件读写 占另一半24。由此立下四条设计律25:

内容谁违反了
G1输入输出通道数相等时,内存访问代价最小ShuffleNet v1 的瓶颈结构
G2分组数越大,内存访问代价越高ShuffleNet v1 自己
G3分支越多,并行能力越差MobileNet v2 的多分支
G4逐元素操作(ReLU、偏置、相加)很耗时,能省则省深度可分离处用 ReLU6

按四条律重做,得到 v2 的通道拆分:一半通道原地直通,另一半做普通深度可分离卷积, 最后拼接——分支少(G3)、通道相等(G1)、不分组(G2)、拼接合并(G4)。 而那直通的一半,恰是 DenseNet 式的特征重用,只是「只映射了一半」——轻量模型和 高精度模型在这里汇合了26

3.5 CondenseNet:让训练自己决定留哪些连接

DenseNet 的全连接是拍脑袋的「全都留」。CondenseNet(还是 DenseNet 原班团队)说: 密集连接有冗余,不如在训练中对不重要的权值剪枝(把没用的连接裁掉,学出一个 稀疏网络)27

怎么判断哪条连接没用?看它的权值:每条连接权重的绝对值加总,行话叫 L1 范数(范数:衡量一个向量有多长的量), 越接近零说明这条连接越没用。每裁掉一批就再训若干轮,反复若干阶段;配合 group lasso 正则项,让「整组整组」的权值一起归零——这样才能整组剪、整组用28

细节书里交代得很诚实:剪枝不是真删,是掩码置零,训练时间一点没省,还要多花显存 存掩码29

真正提速发生在测试:引入一张索引——哪一格连到哪一格的清单——训练完照着清单 把特征图整理成组,之后就能用现成的分组卷积高速跑30

架构上再补两刀:增长率改指数级(越靠近输出层通道越多,依据是热力图显示越近输出的 特征贡献越大);块与块之间也连上捷径(全密集连接)31。书里的小结点破天机: 稀疏卷积与分组卷积的共同点是「只有部分权值参与计算」,group lasso 是把「无规律的稀疏」 整成「有规律的分组」的粘合剂32

判断(我们的,不是书里的): 这一章真正的主角不是任何单个网络,而是「评估尺子」 的三次更换:SqueezeNet 用参数量(被揭穿)、MobileNet 用计算量(撞上框架墙)、 ShuffleNet v2 用真实运行时间(顺手把前三名全批评了)。以后看任何「轻了 X 倍」的宣称, 先问:尺子是什么?量到运行时间了吗? 如果错,会错在: 如果硬件专门为某类算子做了优化(比如后来的 NPU 原生支持深度卷积), G3、G4 的结论就要按新尺子重算——四条律是「GPU 时代」的律,不是物理定律。

4. 作者的判断与证据

书里自己跑的实验: 普通卷积 vs MobileNet v1 的参数对照(239 936→29 184)与 CPU/GPU 双环境计时;ReLU 通道数与信息损耗的小实验;「全融合或全不融合都不是最好的 选择」一类的对照在下一章 EfficientNet v2 也有。转述论文的: 四条设计律及其自批 (v1 违背 G2/G1、v2 对 MobileNet v2 批 G3)。作者的判断: 对 Inception v4 vs ResNeXt 的评价、对 SqueezeNet 题目营销的批评、对 CondenseNet「理论上比 ShuffleNet 更好」的推测,都署了作者自己的态度。

5. 边界与局限

  • 九分之一这笔账的口径是 3×3 核、账面上比;实际从头到尾的加速比取决于硬件与实现 (书里 GPU 反而更慢的例子就是明证);
  • G1~G4 基于 ARM/GPU 时代;专用加速芯片上需要重新量尺;
  • CondenseNet 的浓缩率、分组数都是人工定;它的「学习分组」思想到 NAS 一章 (第 07、08 章)会被更彻底地自动化取代。

6. 可带走的

  1. 深度可分离卷积 = 各通道各卷(深度卷积)+ 1×1 混合(点卷积),3×3 场景约省 8/9;
  2. 小通道上的 ReLU 是信息黑洞:瓶颈层改线性激活,是轻量网络的标准动作;
  3. 反转残差:先扩张后压缩,捷径接在窄处;传统残差是漏斗,它是沙漏;
  4. 分组卷积省算力但切断了组间通信,通道洗牌用一次轮转换位把血统混回去;
  5. FLOPS 只占运行时间的一半:内存访问、并行度、逐元素操作都在偷时间—— G1(通道相等)、G2(少分组)、G3(少分支)、G4(少逐元素操作);
  6. 对比实验的口径决定结论:先问「参数少 50 倍」到底比的是哪一部分;
  7. 剪枝想真提速,必须把「无规律稀疏」整理成「有规律分组」——group lasso 加索引归类 是这对组合的名字。

7. 原文地图

主题原书节原文位置
轻量化动机2.1 SqueezeNet(篇首)text/05-p81-100.txt:158(搜「减少可学习的参数」) · text/05-p81-100.txt:169(搜「1/50」)
SqueezeNet 三策略与揭穿2.1.1 / 2.1.5text/05-p81-100.txt:179(搜「降采样后置」) · text/05-p81-100.txt:270(搜「并没有关系」) · text/05-p81-100.txt:272(搜「0.5MB」)
深度卷积与点卷积2.2.1 MobileNet v1text/05-p81-100.txt:312(搜「不跨通道」) · text/05-p81-100.txt:341(搜「点卷积」) · text/05-p81-100.txt:360(搜「普通卷积的」)
参数对照与 GPU 慢2.2.1 MobileNet v1text/05-p81-100.txt:418(搜「239 936」) · text/05-p81-100.txt:437(搜「底层框架」)
ReLU 损耗与线性瓶颈2.2.2 MobileNet v2text/05-p81-100.txt:452(搜「没有办法恢复」) · text/05-p81-100.txt:465(搜「线性激活函数」)
反转残差与沙漏2.2.2 MobileNet v2text/05-p81-100.txt:491(搜「t = 6」) · text/05-p81-100.txt:493(搜「沙漏形」) · text/05-p81-100.txt:499(搜「反转残差块」)
ReLU62.2.2 MobileNet v2text/05-p81-100.txt:480(搜「控制到 6」)
Xception 两点不同2.3.2 Xception 详解text/05-p81-100.txt:590(搜「叫作极端的」) · text/05-p81-100.txt:598(搜「第二个不同点」) · text/05-p81-100.txt:613(搜「充分解耦」)
分组卷积与基数2.4 ResNeXttext/05-p81-100.txt:628(搜「cardinality」) · text/05-p81-100.txt:143(搜「折中方案」)
ResNeXt 点评2.4.5 小结text/06-p101-120.txt:36(搜「优于 ResNeXt」) · text/06-p101-120.txt:38(搜「硬件设计原则」)
通道洗牌2.5.1 ShuffleNet v1text/06-p101-120.txt:82(搜「精度大打折扣」) · text/06-p101-120.txt:89(搜「g 轴和 n 轴转置」) · text/06-p101-120.txt:114(搜「可微分」)
g=1 退化2.5.1 ShuffleNet v1text/06-p101-120.txt:125(搜「退化为 Xception」)
FLOPS 只占一半、四准则2.5.2 ShuffleNet v2text/06-p101-120.txt:150(搜「50% 左右」) · text/06-p101-120.txt:156(搜「MAC 最小」) · text/06-p101-120.txt:177(搜「非常耗时」)
四准则自批2.5.2 ShuffleNet v2text/06-p101-120.txt:190(搜「违背 G2」)
通道拆分与 DenseNet 汇合2.5.2 ShuffleNet v2text/06-p101-120.txt:208(搜「channel split」) · text/06-p101-120.txt:224(搜「只映射了一半」)
CondenseNet 剪枝与浓缩2.6 CondenseNettext/06-p101-120.txt:251(搜「不重要的权值进行剪枝」) · text/06-p101-120.txt:282(搜「condensing」) · text/06-p101-120.txt:293(搜「个浓缩阶段」)
group lasso 与掩码真相2.6.2 可学习分组卷积text/06-p101-120.txt:318(搜「group lasso 正则项」) · text/06-p101-120.txt:325(搜「掩码的形式」)
索引重排2.6.2 可学习分组卷积text/06-p101-120.txt:352(搜「索引层」) · text/06-p101-120.txt:354(搜「3,7,9,12」)
指数增长率、全密集连接2.6.3 架构设计text/06-p101-120.txt:366(搜「指数级增长的增长率」) · text/06-p101-120.txt:370(搜「全密集连接」)
粘合剂小结2.6.4 小结text/06-p101-120.txt:378(搜「有机的结合」)

Footnotes

  1. 出处:「2.1 SqueezeNet」(text/05-p81-100.txt:158,搜「减少可学习的参数」)。提速两法:减少参数数量、减少计算量。

  2. 出处:「2.1 SqueezeNet」(text/05-p81-100.txt:162,搜「保存和传输」)。

  3. 出处:「2.2.1 MobileNet v1」(text/05-p81-100.txt:418,搜「239 936」)。普通卷积部分 239 936 对 MobileNet v1 部分 29 184。

  4. 出处:「2.1 SqueezeNet」(text/05-p81-100.txt:169,搜「1/50」)。原文:达到与 AlexNet 近似效果,参数约是 AlexNet 的 1/50,配合深度压缩模型文件约 1/510。

  5. 出处:「2.1.1 SqueezeNet 的压缩策略」(text/05-p81-100.txt:179,搜「降采样后置」)。

  6. 出处:「2.1.5 小结」(text/05-p81-100.txt:270,搜「并没有关系」)与(text/05-p81-100.txt:272,搜「0.5MB」)。

  7. 出处:「2.2.1 MobileNet v1」(text/05-p81-100.txt:312,搜「不跨通道」)。

  8. 出处:「2.2.1 MobileNet v1」(text/05-p81-100.txt:341,搜「点卷积」)。

  9. 出处:「2.2.1 MobileNet v1」(text/05-p81-100.txt:360,搜「普通卷积的」)。式(2.3)(2.4):对 3×3 核,参数与计算量均为普通卷积的约九分之一。

  10. 出处:「2.2.1 MobileNet v1」(text/05-p81-100.txt:437,搜「底层框架」)。GPU 上普通卷积约 40s、MobileNet v1 约 50s的反常及其解释。

  11. 出处:「2.2.2 MobileNet v2」(text/05-p81-100.txt:452,搜「没有办法恢复」)与(text/05-p81-100.txt:455,搜「还原程度越高」)。

  12. 出处:「2.2.2 MobileNet v2」(text/05-p81-100.txt:465,搜「线性激活函数」)。

  13. 出处:「2.2.2 MobileNet v2」(text/05-p81-100.txt:498,搜「瓶颈层」)。

  14. 出处:「2.2.2 MobileNet v2」(text/05-p81-100.txt:493,搜「沙漏形」)。

  15. 出处:「2.2.2 MobileNet v2」(text/05-p81-100.txt:480,搜「控制到 6」)。

  16. 出处:「2.3.2 Xception 详解」(text/05-p81-100.txt:598,搜「第二个不同点」)。

  17. 出处:「2.3.3 小结」(text/05-p81-100.txt:613,搜「充分解耦」)。

  18. 出处:「2.4 ResNeXt」(text/06-p101-120.txt:23,搜「折中方案」)。

  19. 出处:「2.4 ResNeXt」(text/05-p81-100.txt:628,搜「cardinality」)。

  20. 出处:「2.4.5 小结」(text/06-p101-120.txt:36,搜「优于 ResNeXt」)与(text/06-p101-120.txt:38,搜「硬件设计原则」)。

  21. 出处:「2.5.1 ShuffleNet v1」(text/06-p101-120.txt:82,搜「精度大打折扣」)。

  22. 出处:「2.5.1 ShuffleNet v1」(text/06-p101-120.txt:101,搜「0 3 6 1 4 7 2 5 8」)与(text/06-p101-120.txt:114,搜「可微分」)。

  23. 出处:「2.5.1 ShuffleNet v1」(text/06-p101-120.txt:125,搜「退化为 Xception」)。

  24. 出处:「2.5.2 ShuffleNet v2」(text/06-p101-120.txt:150,搜「50% 左右」)。

  25. 出处:「2.5.2 ShuffleNet v2」(text/06-p101-120.txt:156,搜「MAC 最小」)、(text/06-p101-120.txt:164,搜「成正比」)、(text/06-p101-120.txt:169,搜「降低网络的并行能力」)、(text/06-p101-120.txt:177,搜「非常耗时」)。G1~G4 全部出处。

  26. 出处:「2.5.2 ShuffleNet v2」(text/06-p101-120.txt:220,搜「非常一致的结构」)与(text/06-p101-120.txt:224,搜「只映射了一半」)。

  27. 出处:「2.6 CondenseNet」(text/06-p101-120.txt:251,搜「不重要的权值进行剪枝」)。

  28. 出处:「2.6.2 可学习分组卷积」(text/06-p101-120.txt:293,搜「个浓缩阶段」)与(text/06-p101-120.txt:318,搜「group lasso 正则项」)。浓缩率 C:每阶段剪 1/C,C−1 阶段后仅保留 1/C。

  29. 出处:「2.6.2 可学习分组卷积」(text/06-p101-120.txt:325,搜「掩码的形式」)。

  30. 出处:「2.6.2 可学习分组卷积」(text/06-p101-120.txt:352,搜「索引层」)。原文:索引层把输入特征图重新整理成组,例 (3,7,9,12)、(1,5,10,12)、(5,6,8,11) 重排后可用标准分组卷积。

  31. 出处:「2.6.3 架构设计」(text/06-p101-120.txt:366,搜「指数级增长的增长率」)与(text/06-p101-120.txt:370,搜「全密集连接」)。

  32. 出处:「2.6.4 小结」(text/06-p101-120.txt:378,搜「有机的结合」)。