深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言
在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄像头、机器人等资源受限的设备上。
于是我们就想出了一个办法:给模型“瘦身”,让它又快又轻,还能保持不错的准确率。
这就是——模型压缩!
模型压缩有三种最常用的方法:
模型剪枝
模型量化
知识蒸馏
下面我们分别来通俗地讲讲它们是什么、怎么做的、为什么有用。
二、模型剪枝(Model Pruning)——“砍掉不重要的部分”
定义:
模型剪枝是指通过移除神经网络中“不重要”的权重连接或通道,从而减少模型大小和计算量的方法。想象你有一台超级豪华的电脑,里面有很多复杂的部件。有些零件非常重要(比如 CPU 和显卡),有些其实可有可无(比如多余的风扇、装饰灯)。模型剪枝就像是在做“减法”——把那些不太重要的部分删掉,让整台电脑更轻便,性能也差不多。
核心原理:
核心原理:
- 权重剪枝:神经网络中有成千上万的连接(权重),其中一些对结果影响很小,移除接近零的权重,影响不大;
- 通道剪枝(Channel Pruning):移除卷积层中影响较小的通道;
- 结构化剪枝 vs 非结构化剪枝:
- 结构化剪枝:剪掉整个通道或层,便于硬件加速;
- 非结构化剪枝:剪掉任意位置的权重,压缩效果更强但难以加速;
必要性:
- 减少模型体积,利于部署;
- 提高推理速度,降低内存占用;
- 在有限算力设备上运行大模型;
举个例子:
你有一个 YOLOv8s 模型,它本来有 100 层。经过分析发现其中有 10 层几乎没用,那我们就直接删掉这 10 层,剩下的 90 层再训练(微调)一下,就能得到一个更快、更小的模型!
三、模型量化(Model Quantization)——“用更少的比特表示同样的信息”
定义:
模型量化是将模型中的浮点数(FP32)转换为低精度表示(如 INT8、FP16)的过程,从而减少模型大小并提升推理速度。你在学校考试时,满分是 100 分,但有时候老师会说:“60 分以上就算及格”。也就是说,你并不需要精确到每个分数,只要知道大致等级就可以了。
模型量化也是类似的思想:我们不需要用“32位浮点数”这么高精度的数字来表示神经网络中的参数,可以用“8位整数”代替,这样计算更快、占用空间更小。
一句话总结:模型量化 = 用更小的数字类型表达原来的模型,减少存储和计算量。
核心原理:
- 训练感知量化(QAT, Quantization-Aware Training):
- 在训练过程中模拟量化过程,使模型适应低精度;
- 后训练量化(PTQ, Post-Training Quantization):
- 不需要重新训练,直接对已训练好的模型进行量化,把原本使用 32 位浮点数(FP32)的参数,转换为 8 位整数(INT8);;
- 校准机制:使用少量数据统计激活值范围,用于量化映射;
必要性:
- 显著减少模型体积(INT8 相比 FP32 可减少 4 倍);
- 提升推理速度(INT8 运算更快);
- 支持嵌入式平台(如 Jetson Nano、树莓派)部署;
举个例子:
一个 FP32 的数字占用 4 字节,而一个 INT8 的数字只占 1 字节。如果你把整个模型从 FP32 转成 INT8,那模型体积就缩小了 4 倍,推理速度也提升了 2~3 倍!
一般的操作方式如下:
# 示例:使用 TorchVision 导出 ResNet 为 ONNX 并量化
import torch
from torchvision import modelsmodel = models.resnet18(pretrained=True)
dummy_input = torch.randn(1, 3, 224, 224)torch.onnx.export(model, dummy_input, "resnet18.onnx")# 使用 ONNX Runtime 进行量化
from onnxruntime.quantization import quantize_dynamic, QuantTypequantize_dynamic(model_input="resnet18.onnx",model_output="resnet18_quantized.onnx",weight_type=QuantType.QInt8
)
四、知识蒸馏(Knowledge Distillation)——“学生模仿老师的学习方法”
定义:
知识蒸馏是一种模型压缩技术,其核心思想是让一个小模型(学生模型)模仿一个大模型(教师模型)的行为,从而获得更优的性能。你是一个小学生,正在学数学题。你可以自己慢慢摸索,也可以找一个成绩很好的同学当老师,他怎么做题你就跟着学。这样你就能快速学会解题技巧,虽然你不如老师厉害,但能做得还不错。
知识蒸馏就是这个道理:我们用一个小模型去模仿一个大模型的行为,从而提升小模型的能力。
一句话总结:知识蒸馏 = 让小模型模仿大模型的行为,从而获得更好的性能。
核心原理:
- 先训练一个强大的大模型(叫教师模型,教师模型输出 soft labels(概率分布);
- 然后让一个小模型(叫学生模型)去学习大模型的输出,学生模型同时学习 hard label(真实标签)和 soft labels;
- 学生不仅学正确答案,还学大模型给出的“置信度”,使用 KL 散度等衡量两者输出差异,最终学生模型就可以学到老师的“经验”,表现得更好;
- 公式示例:
L t o t a l = α ⋅ L h a r d + ( 1 − α ) ⋅ T 2 ⋅ L s o f t \mathcal{L}_{total} = \alpha \cdot \mathcal{L}_{hard} + (1 - \alpha) \cdot T^2 \cdot \mathcal{L}_{soft} Ltotal=α⋅Lhard+(1−α)⋅T2⋅Lsoft
其中 T 是温度系数, α \alpha α控制 hard label 的权重。
必要性:
- 小模型通常泛化能力差,蒸馏能显著提升性能;
- 可用于压缩 DETR、Vision Transformer 等复杂模型;
- 适合资源受限的部署环境;
举个例子:
你想做一个能在手机上运行的目标检测模型,但是手机算力有限。你可以先训练一个大模型(如 YOLOv8l),然后让学生模型(如 YOLOv8n)去模仿它。这样即使学生模型很小,也能做出不错的结果。
五、三者对比:区别与关联性
维度 | 模型剪枝 | 模型量化 | 知识蒸馏 |
---|---|---|---|
目的 | 减少参数数量 | 减少计算精度 | 提升小模型性能 |
核心操作 | 删除冗余权重或通道 | 将 FP32 → INT8/FP16 | 小模型模仿大模型 |
是否改变结构 | ✅(剪枝可能删除层) | ❌ | ❌ |
是否需要微调 | ✅ | ✅ | ✅ |
是否依赖教师模型 | ❌ | ❌ | ✅ |
部署友好度 | ✅(结构化剪枝) | ✅(INT8 加速明显) | ✅(蒸馏后模型可进一步压缩) |
关联性总结:
- 剪枝 + 量化:先剪枝再量化,双重压缩;
- 蒸馏 + 量化:先蒸馏得到高性能小模型,再量化部署;
- 剪枝 + 蒸馏:剪枝后的模型可通过蒸馏恢复精度;
- 三者结合:可用于构建极致轻量、高性能、易部署的小模型(如 Tiny-YOLO、MobileViT 蒸馏模型);
六、实战应用指南:如何利用三者提升模型性能与部署效率?
场景一:YOLOv8 部署优化
步骤:
- 模型剪枝:对骨干网络进行通道剪枝,减少参数;
- 知识蒸馏:用 YOLOv8l 蒸馏 YOLOv8s,提升小模型精度;
- 模型量化:将剪枝+蒸馏后的模型导出为 INT8;
- 部署:使用 TensorRT / OpenVINO 部署,实现毫秒级推理;
💡 效果:相比原模型,推理速度提升 2x,模型大小缩小 4x,精度下降 < 1%。
场景二:Vision Transformer 压缩部署
步骤:
- 知识蒸馏:使用 DeiT 蒸馏出 MobileViT;
- 模型剪枝:对注意力头或 MLP 中的部分通道进行剪枝;
- 模型量化:将 ViT 转换为 INT8 模型;
- 部署:使用 ONNX Runtime 或 NCNN 部署到手机端;
💡 效果:Transformer 模型在移动端部署不再是难题。
场景三:工业质检中的模型轻量化部署
步骤:
- 原始模型:ResNet-101;
- 知识蒸馏:蒸馏为 ShuffleNet;
- 模型剪枝:对 ShuffleNet 进行通道剪枝;
- 模型量化:导出为 INT8;
- 部署:使用 TensorRT 加速,在产线摄像头中部署;
💡 效果:从 177M 参数 → 1.2M 参数,推理速度从 10 FPS → 60 FPS。
七、推荐实践路线图
[大模型] ↓(剪枝)
[轻量模型]↓(量化)
[INT8/FP16 模型]↓(蒸馏)
[高性能小模型]↓(部署)
[ONNX / TensorRT / CoreML]
八、结语:模型压缩是迈向落地的关键一步
在实际工程中,我们往往不会只使用一种压缩技术,而是多种方法协同使用,例如:
- 先剪枝再量化;
- 蒸馏 + 量化;
- 剪枝 + 蒸馏 + 量化;