这是 100 页综述的精讲系列,共 5 篇

这一篇在干嘛?

本篇精讲 Luo 等人发表于 ACM TECS 2024 的百页综述《Efficient Deep Learning Infrastructures for Embedded Computing Systems: A Comprehensive Survey and Future Envision》的第 4 章:面向嵌入式计算系统的网络压缩(Network Compression)。 第 2、3 章讲的是”怎么从头设计一个本来就很小的网络”,这一章换了一条路:网络已经在手上了(不管是手工设计的还是 NAS 搜出来的),怎么把它压得更小、更快,同时尽量不掉精度。三条主线是剪枝(Pruning)、量化(Quantization)和蒸馏(Distillation)。 最值得记住的几个数字:Deep Compression 把 VGGNet 从 552 MB 压到 11.3 MB(×49) 而精度基本不掉;权重剪枝可以让网络小 90%;INT8 量化带来约 ×4 的体积压缩且精度损失”可忽略”;二值/三值网络理论上有 ×16~×32 的加速潜力但要专用硬件;知识蒸馏不改网络结构,纯粹从精度一侧把准确率—效率权衡往前推。 一句话概括三者的关系:剪枝和量化从”效率侧”动手,蒸馏从”精度侧”动手,三者互相正交,可以叠加使用。

一、先建立坐标系:三种压缩到底在动什么

在动手之前,先把这三条路线的”作用点”分清楚。很多初学者把剪枝、量化、蒸馏混为一谈,是因为它们都叫”模型压缩”;但它们修改的对象完全不同。

路线动的是什么网络结构变了吗数值精度变了吗主要收益
剪枝 Pruning去掉冗余的权重/通道/层变了(更窄更浅)不变(仍 FP32)参数量、FLOPs 双降
量化 Quantization降低权重与激活的位宽不变(层数和通道数照旧)变了(FP32→INT8/2bit/1bit)存储 ×1/4,带宽 ×1/4,能耗大降
蒸馏 Distillation改的是训练方式,用一个大模型带小模型不变不变精度提升,常与剪枝/量化配合

论文里有一句非常关键的话值得抄下来:剪枝和量化是从效率视角(efficiency perspective)改进准确率—效率权衡,而蒸馏是从精度视角(accuracy perspective)改进它。

也就是说:

  • 剪枝和量化的逻辑是:“我要把一个大模型变小,代价是精度会掉一点,我尽量让这一点越少越好。”
  • 蒸馏的逻辑是:“网络结构我不动,我就是想让这个网络训练得更好、精度更高。”

所以蒸馏严格来说不是压缩技术,它是”精度补偿技术”。这也是为什么工业界最常见的流水线是:先剪枝 → 再量化 → 全程用蒸馏把掉的点补回来。三者不是三选一,而是三个可以串联的工序。

论文还强调了一个容易被忽略的事实:这三类技术可以跨网络类型泛化。剪枝、量化、蒸馏最早都是在卷积神经网络(CNN)上做的,但同样可以用在 Transformer、图网络、脉冲网络上。第 4 章的例子以 CNN 为主,但结论并不局限于 CNN。


图 17(原论文):不同剪枝策略的粒度示意。权重剪枝(Weight Pruning)是非结构化的,去掉的是零散的单个权重连接;通道剪枝(Channel Pruning)和层剪枝(Layer Pruning)是结构化的,去掉的是整条通道或整个层。

二、剪枝:到底”剪”的是什么,剪完为什么不掉点

2.1 前提:网络是过参数化的

剪枝能成立,靠的是一个经验事实:深度神经网络通常是过参数化(over-parameterized)的——它的参数量和通道数远多于完成任务真正需要的量。

你可以这样理解:一个在 ImageNet 上训练好的 ResNet-50 有 2500 万个参数,但其中相当一部分是”陪跑”的。有的卷积核学到的特征图和别的卷积核高度雷同;有的权重数值小到对输出几乎没有影响。既然如此,把它们去掉,网络的表达能力理论上不该有大的损失。

这就是剪枝的基本假设消除冗余的权重和通道,能以最小的精度代价换来可观的效率收益,从而适配嵌入式场景里紧张的算力和存储。

2.2 非结构化剪枝:最细的粒度,最”骗人”的收益

非结构化剪枝(Non-structured Pruning),也叫权重剪枝(Weight Pruning),去掉的是单个权重连接。它是最细粒度的剪枝方式,如图 17 左侧所示。

这条路线的历史其实很老了。早在 1990 年代,Optimal Brain Damage(OBD)Optimal Brain Surgeon(OBS) 就研究了在全连接网络上按损失函数的 Hessian(二阶导数)来剔除不重要的权重。真正让它在深度学习时代火起来的是 Han 等人在 2015 年的工作:他们发现权重的绝对值越小,对精度的贡献通常也越小,于是直接按绝对值大小来剪。

来看一个具体的小例子。假设某个卷积核的 5 个权重是:

按绝对值排序:。如果要求剪掉 40%(即 2 个),被剪掉的就是 。这两个权重乘上激活值之后贡献的输出本来就微乎其微,所以砍掉它们对结果几乎没影响——这就是**基于幅度的剪枝(Magnitude-based Pruning)**的全部直觉。

这个方法后来被集成进著名的 Deep Compression,效果极其夸张:

VGGNet:552 MB → 11.3 MB,压缩 ×49,ImageNet 精度基本不变。

但是,这里有一个巨大的陷阱,也是初学者最容易踩的坑。

2.3 非结构化剪枝的”阿喀琉斯之踵”:为什么不省时间

论文里明确写道:

网络体积(size)的下降不能直接翻译成目标硬件上的加速(speedup),因为压缩后的网络具有高度不规则的稀疏性(irregular network sparsity)。

这句话值得展开讲透。假设你把一个 的权重矩阵剪掉了 90% 的权重,剩下 10 万个非零值。问题来了:

1. 矩阵形状没变。 对 GPU/CPU 来说,它看到的仍然是一个 的矩阵,只不过里面 90% 的位置是 0。如果你用稠密(dense)格式存储,它占用的内存一点没少,计算量一点没少——乘 0 也是要做乘法的。

2. 用稀疏格式存储会引入额外开销。 你可能会说:“那我用 CSR/COO 稀疏格式存,只存非零值和它的坐标不就行了?“没错,但这样一来每个非零权重都要额外带一个索引(通常 4 字节甚至更多)。权重本身 FP32 也是 4 字节。也就是说,在 4 字节索引的稀疏格式下,剪枝率不超过 50% 时你的存储甚至可能变大。Deep Compression 之所以能把 552 MB 压到 11.3 MB,是因为它还叠加了量化(把 32 位权重压到 5 位甚至更少)+ 霍夫曼编码来压索引,而不只是”把权重置零”。

3. 不规则访存破坏了硬件的并行前提。 现代 GPU 是 SIMT 架构:一堆线程锁步执行同一条指令,靠连续的内存访问把带宽吃满。稀疏权重意味着访存地址是跳变的,一个 warp 里 32 个线程可能要访问 32 个不连续的地址,缓存命中率崩塌,访存反而变成了瓶颈。而嵌入式推理恰恰是”访存受限(memory-bound)“而不是”计算受限(compute-bound)“的。

4. 计算单元仍在空转。 0 权重仍然占据一个乘加(MAC)单元的执行槽位,除非硬件有专门的”跳过零”逻辑。

所以论文的结论是:非结构化剪枝高度依赖专用硬件加速器,无法在现代嵌入式计算系统上提供真实的运行时加速。 这也是为什么 EIE(Efficient Inference Engine)这类专用推理引擎、Cambricon-X 这类带”访存高效索引模块”的加速器会被专门设计出来——它们做的事本质上就是把不规则的权重挑出来、搬到各个处理单元(PE)本地去做计算,减少跨 PE 的不规则访存开销

常见坑 1:看到"剪掉 90% 参数"就以为快了 10 倍

论文原文说得很清楚:权重剪枝能让网络小 90%(这是存储收益),但不能直接得到 10 倍加速(这是时间收益)。审稿人和工程师问”你的方法在 ARM Cortex-M 上快了多少”时,报压缩率是答非所问的。只有结构化剪枝才能在主流的 GPU 和 CPU 上拿到真实的 wall-clock 加速

2.4 半结构化剪枝:一个务实的折中

既然完全不规则不行、完全结构化又不够灵活,就有了半结构化剪枝(Semi-structured Pruning):它去掉的是连续的权重连接,从而让稀疏模式变得规则。

最典型的是 N:M 稀疏:在每 M 个连续权重中,只保留 N 个。比如 NVIDIA Ampere 架构支持的 2:4 稀疏——每 4 个连续权重里保留 2 个(固定 50% 稀疏率)。举例:

因为”哪两个位置保留”的候选组合只有 种,硬件可以预先设计好数据通路,索引开销极低。论文给出的实测数字是:

流行的 BERT 模型在 NVIDIA A100 GPU 上用优化后的稀疏张量核(sparse tensor cores),可以获得约 1.3× 到 1.6× 的运行时推理加速。

而且半结构化稀疏已经被 cuSPARSELtTVM 等主流深度学习库原生支持,工程落地难度远低于非结构化。代价是:稀疏率被硬件格式固定(2:4 就是 50%),不能像非结构化那样自由地压到 90%。

2.5 权重重要性准则:不只”看绝对值”

剪枝的核心问题是:怎么判断一个权重重不重要? 论文列举了几类代表性准则:

准则思路代表工作
幅度(Magnitude)用绝对值 $w
二阶导数(Hessian)看删掉这个权重后损失函数的增量OBD [307]、OBS [308]
泰勒展开(Taylor Expansion)用一阶泰勒近似估计删除后的损失变化[316]
输出敏感度(Output Sensitivity)看权重扰动对网络输出的影响[317]
可学习门(Learnable Gate)引入一个可学习的门控参数,训练中自动极化GDP [312]

幅度准则之所以流行,是因为概念简单却意外地强。但它的隐含假设是”小权重 = 不重要”,这个假设并不总成立(在剪枝的现代研究里已经被反复挑战)。

GDP(Gates with Differentiable Polarization,可微分极化门) 是一个很漂亮的做法:它给每个权重引入一个可学习的门 ,训练时通过正则化让门的值两极分化——要么精确为 0,要么明显非 0,中间地带被挤压掉。训练结束后,门为 0 的权重直接删掉,剩下的非零门合并(merge)回网络权重里,因此不引入任何额外的推理开销


图 18(原论文):GDP 方法中权重门的分布。可以看到门的取值被推向两个极端——精确为 0 的一簇(对应被剪掉的权重)和明显非零的一簇(对应保留的权重),中间几乎没有过渡地带。这种”极化”让剪枝决策变得干净,而且仍然允许梯度优化。

论文也坦率地承认:高效且有效的重要性准则的设计仍然是一个开放的挑战(open challenge),这块远没有被充分探索。

2.6 稀疏训练:剪完之后怎么把精度找回来

剪完直接扔到硬件上用是不行的——精度会掉。这里有一整套**稀疏训练(Sparse Training)**技术来恢复精度:

策略一:微调(Fine-tuning)。 剪完之后,用继承下来的权重作为初值,在小学习率下继续训练几轮,让剩下的权重”接管”被删掉权重的工作。

策略二:迭代剪枝(Iterative Pruning)。 Deep Compression 的做法——“剪一点 → 微调 → 再剪一点 → 再微调……” 循环多次,而不是一次剪到底。直觉是:一次剪 90% 对网络的冲击太大,分 10 次每次剪一点,网络每次都能缓过来。这也是工程上最常用、最稳妥的做法。

策略三:逃离局部最优。 有工作发现训练稀疏网络时容易掉进”次优局部极小值(suboptimal local minima)“,于是提出在训练中让网络在稠密子空间和稀疏子空间之间来回穿越,借此跳出坏的解。

策略四:改训练协议。 更激进的做法是干脆不用标准的训练流程——在训练早期引入”幽灵神经元(ghost neurons)“和跳连(skip connections),并刻意修改初始化和标签,让稀疏网络从一开始就更容易训好。

2.7 彩票假说:一个反直觉的发现

彩票假说(Lottery Ticket Hypothesis, LTH) 是剪枝领域近十年最有名的发现之一,必须讲清楚。

它的内容是:

一个随机初始化的未剪枝网络里,包含着若干稀疏子网络(即”中奖彩票” / winning tickets);这些子网络如果用它们原本的初始化值、并单独从头训练(in isolation),能够达到和完整网络相当的精度,而且训练轮数不超过原网络。中奖彩票可以比原网络小 90%

这个结论反直觉在哪?在于它说:重要的不只是”哪些连接被保留”,还有”这些连接的初始值是什么”。 如果你把剪出来的子网络重新随机初始化再训,反而训不好——这就证明了原初始化里藏着”中奖”的信息。

找中奖彩票的标准流程是这四步:

  1. 随机初始化未剪枝网络 ,其中
  2. 训练 轮,得到权重
  3. 剪掉 的权重,得到稀疏掩码(mask)
  4. 把剩下的权重重置回 中对应的值,得到中奖彩票

第 4 步是精髓——不是沿用训练后的 ,而是回退到初始的

论文还指出:一次性剪掉 会导致明显的精度损失、训练也不稳定。所以 LTH 采用迭代式剪枝(iterative pruning):重复”训练 → 剪枝 → 重置”共 轮,每轮只剪 。比如总共要剪 90%(剩 10%),分 10 轮,那么每轮的保留比例是 ,也就是每轮剪掉约 20.6%。

后续工作给 LTH 补上了理论证明,也发现了它的失效场景:在 ResNet、DenseNet 这类很深的网络上,LTH 会出现”性能崩塌(performance collapse)“。解决办法是 rewinding iteration(回绕迭代)——不重置到第 0 轮的 ,而是重置到训练早期第 轮的 ,这样训练就稳定了。LTH 还被推广到了图网络、脉冲网络、光子网络等非 CNN 架构上。


图 19(原论文):第 4.1 节讨论过的非结构化与结构化剪枝工作全景图。这张图把两大类剪枝方法按技术路线做了归类,是理解整个剪枝领域版图的一张”地图”。可以看到非结构化一侧(权重剪枝、稀疏训练、彩票假说)与结构化一侧(通道剪枝、层剪枝,以及基于权重/激活/BN 统计/搜索的四类准则)是并行发展的两条主线。

三、结构化剪枝:嵌入式场景真正用得上的那一类

结构化剪枝(Structured Pruning)包括通道剪枝(Channel Pruning)层剪枝(Layer Pruning),去掉的是整条通道或整个层。

先把关系理清楚:层剪枝是通道剪枝的特例——当某一层的所有通道都被剪掉时,这一层就没了,通道剪枝就退化成了层剪枝。

结构化剪枝为什么香?因为通道数变少了,张量形状真的变小了。一个卷积层从 256 通道剪到 128 通道,它的输出特征图直接少一半,后续所有层的输入也少一半——FLOPs 和访存量同步下降,而且是规则的、连续的,GPU/CPU 原生就能吃下这个收益,不需要任何专用硬件

论文因此说:结构化剪枝可以轻易地在 GPU 和 CPU 这类主流硬件上获得真实加速,这让它成为”硬件友好网络方案设计”里的首选。

代价是:粒度粗,剪起来”下手重”,在同等压缩率下精度损失通常比非结构化大。

3.1 四类通道重要性准则

论文把结构化剪枝的工作归纳为四类:

(1)基于权重的(Weight-Based) 直接看这条通道对应卷积核的权重。最常用的是 范数:

  • 范数:Li 等人提出按 范数剪通道, 小的通道被认为不重要。
  • 范数:有工作发现 范数的剪枝效果比 更好。

举个手算例子。假设某层有两个 卷积核:

准则, 被剪掉——因为它对整个输出的贡献微乎其微。

但这里有个重要的反驳:有工作挑战了”/ 小的通道就一定不重要”这个经验假设,指出它并不必然成立。替代方案是看通道相关性(channel correlation)

靠近几何中位数(geometric median)的通道通常是冗余的,因为它们和同层里其他通道表达的特征图很相似。删掉这些”人云亦云”的通道,精度损失最小。

这个想法很符合直觉:如果一层里有 10 个通道都检测”边缘”,那保留 2 个就够了,剩下 8 个是冗余。基于这个思路,后续工作先对每层权重做标量哈希(scalar hashing),再按权重相似度去重;还有工作把冗余的考察范围从”同一层内”扩展到”跨多层”。

(2)基于激活的(Activation-Based) 不看权重,看这条通道实际产生的特征图(activation map / feature map)。论文总结了三个技术路线:

  • 当前层:先试着删掉某通道,然后看第 层输出特征图的重建误差(reconstruction error)。误差小的通道说明删了也无妨,就真删掉。类似的还有按分解误差(decomposition error)通道独立性(channel independence)、**激活后特征图(post-activation maps)**来衡量。
  • 相邻层:现代网络是严格串行堆叠的,层与层之间有强依赖。因此可以用第 层的激活图来反推第 层通道的重要性;也有工作反过来用前面层的激活图预测后面层的通道重要性。
  • 最后一层:直接用网络的最终输出来判断——因为剪完之后网络精度好不好,本来就是看输出。可以用重建误差、或用整个网络的**判别性(discrimination)**作为指标。

(3)基于 BN 统计量的(Statistics-Based) 这是工程上最常用的一种,因为它极其简单却异常有效

回忆一下批归一化(Batch Normalization, BN)。BN 是即插即用的标准件,用来加速和稳定训练、减少内部协变量偏移(internal covariate shift)。它对输入 做如下变换(论文式 13):

其中:

  • 是输入 的均值与标准差;
  • 是一个极小常数(例如 ),防止除零;
  • 可学习的缩放与平移参数,训练中优化以恢复输入 的表达能力;
  • 关键: 的维度等于输入通道数

最后这一条是 BN 能被用来剪枝的原因:每个通道都有一个专属的

于是 Network Slimming 的思路就出来了: 施加 正则化,让不重要的通道的 被推向 0。训练结束后, 接近 0 的通道相当于被”关掉”(输出恒为 中的缩放项没了),直接删掉即可。Gate Decorator 用同样的思路提出门控批归一化(gated batch normalization),把 当作通道开关,并配合迭代剪枝 + 微调逐步瘦身。

但论文也指出了 正则的缺陷:判别力不足——因为 会把所有 都往 0 推,导致”重要通道”和”不重要通道”的 值拉不开差距。后续工作因此改用其他正则形式。

为什么"基于 BN 的剪枝"在嵌入式落地里最常见?

三个原因:① 零额外计算—— 是网络训练时本来就有的参数,不需要额外前向;② 通道级粒度天然结构化——剪完直接瘦身,通用硬件立刻加速;③ 一行代码就能加——在损失函数里加一个 的正则项即可。对初学者来说,这是最值得先动手实践的一种剪枝。

(4)基于搜索的(Search-Based) 既然 NAS 能用搜索代替人工设计网络,那能不能用搜索代替人工设计剪枝策略?答案是能,而且做得很好。论文把这类工作分三种:

  • 强化学习搜索。代表性工作 AMC(AutoML for Model Compression) 训练一个 DDPG(Deep Deterministic Policy Gradient)智能体,让它逐层输出最优的通道剪枝率以最大化预设的奖励函数(通常是”精度 × 延迟/能耗”权衡)。AMC 的洞见是:不同层对剪枝的敏感度完全不同,手工设定统一的剪枝率是次优的,应该让 RL 自己学。


图 20(原论文):AMC 概览。它把通道剪枝建模成一个强化学习搜索问题——智能体观察当前层的状态,输出这一层该剪掉多少通道;环境返回”精度 + 硬件效率”构成的奖励,智能体据此更新策略。这样就能自动找出”哪一层该多剪、哪一层该少剪”,而不依赖人工启发式规则。

后续改进:AGMC 指出 AMC 因为环境状态数固定会陷入次优,于是用图卷积网络(GCN)编码被剪网络的结构、用图编码器—解码器自动学习状态表示;DECORE 则改走多智能体路线,给每层分配一个独立智能体。

  • 进化算法搜索MetaPruning 采用两阶段流水线:第一阶段训练一个过参数的 PruningNet(本质就是 NAS 里的超网 / supernet,涵盖所有可能的剪枝配置);第二阶段用训练好的 PruningNet 快速评估各种剪枝后子网络的精度(权重直接从超网继承,不需要重新训练),再用进化引擎搜索最优的子网络。

  • 梯度搜索(可微搜索)。前两类都在离散空间里搜,效率不高。梯度搜索把搜索空间松弛成连续的:DSA 提出可微稀疏度分配(Differentiable Sparsity Allocation),为每层引入一个可学习的剪枝率(概念上等价于可微 NAS 里的架构参数),然后让它和网络权重一起用标准梯度下降联合优化。效率提升极其显著:

DSA 每做一次剪枝实验只需要约 5 GPU 小时

论文最后点出了搜索式剪枝和 NAS 的本质关系:搜索式剪枝搜的是”剪枝后的网络结构”,NAS 搜的是”独立的网络结构”。二者是同一个问题的两种表述,所以 NAS 领域的任何新进展都可以直接搬过来用于剪枝。

3.2 层剪枝:更狠,但也更疼

层剪枝(Layer Pruning)是通道剪枝的特例,直接把某一层的所有通道全删掉,也就是整层删掉。

它的特点是一把双刃剑:

  • 好处:在同等压缩率下,层剪枝在延迟降低方面的表现比通道剪枝更好。因为减少一层意味着少一次完整的特征图读写,而嵌入式推理里访存才是大头。
  • 坏处天下没有免费的午餐(no free lunch)——层剪枝的精度损失通常比通道剪枝更大。

层剪枝在技术上和通道剪枝高度同构,所以前面讲的权重幅度、激活图、BN 统计量这些准则都可以直接搬过来判断”哪一层不重要”。有工作把这几种准则组合起来用,以更可靠地识别不重要的层。还有工作在层剪枝视角下验证了彩票假说,确认层剪枝里也存在初始化时的中奖彩票,而且这些中奖彩票更环保(碳排放更低)、训练效率更高、对抗鲁棒性更好。

另外还有一类有意思的观察:中间层的非线性激活层也可以被”嫁接”掉而几乎不损失精度。做法是把不重要的非线性激活替换成线性的,然后把多个连续的线性层**重参数化(reparameterize)**合并成一个线性层——这样网络就变浅了。

四、量化:把 32 位浮点换成 8 位整数,到底怎么算

终于到了应用最广、工程价值最高的一块。

4.1 量化的本质:一次仿射映射

如果剪枝是”从结构层面降复杂度”,那么量化就是”从精度层面降复杂度”。量化后的网络结构完全不变(层数、通道数一模一样),只是权重和激活的位宽变低了

论文提到量化同样起源于 1990 年代(玻尔兹曼机、光学网络、MLP),但真正爆发是 2010 年代之后——因为有工作证明:相比全精度(32 位)权重,8 位量化权重可以在主流 CPU 上有效加速推理,且精度没有显著退化。

先讲最核心的数学。所谓量化,就是把一个浮点数 (real value)映射成一个整数 (quantized value)。最通用的是仿射量化(affine quantization),也叫非对称量化(asymmetric quantization)

反过来: