模型压缩与加速
本页介绍深度学习落地必备的模型压缩与加速技术:在不显著损失精度的前提下,让模型更小、更快、更省电。它是深度学习概览的工程延伸——训练出好模型只是第一步,把它塞进手机、车载芯片、IoT 设备才是真正的挑战。
模型压缩就像给一个臃肿的快递包裹做瘦身,三种最经典的手法:
- 量化(Quantization)= 把高清照片压成标清:模型权重从 32 位浮点(FP32)压缩到 8 位整数(INT8)甚至 4 位(INT4)。一张 10MB 的图压到 2MB,乍看差不多,体积省了 80%——精度略损但推理快得多。
- 剪枝(Pruning)= 砍掉枯枝:神经网络里很多连接权重接近 0(“枯枝”),对输出几乎没贡献。把这些冗余参数置零或删除,模型变小、变快,几乎不影响精度。剪到极致就是稀疏网络(Sparse Network,大部分权重为零的网络)。
- 知识蒸馏(Knowledge Distillation)= 名师出高徒:让一个庞大的”教师模型”手把手教一个”学生模型”。学生不只学正确答案(硬标签),还学教师对每个类别的置信度分布(软标签 / 暗知识)——小模型因此获得了大模型的部分”直觉”,精度远超它自己从头学。
三者常常组合使用:先蒸馏得到一个小模型,再剪枝去掉冗余,最后量化到 INT8——一部手机就能实时跑的 MobileNet 就是这样炼成的。
量化:数学原理
Section titled “量化:数学原理”量化的核心思想是将连续的浮点数映射到有限的离散值集合。对于从 FP32 到 INT8 的对称量化:
对于非对称量化(适用于激活值,因为激活通常非负):
量化误差的来源:量化本质是有损压缩。 引入的误差最大为 。对于权重范围在 [-1, 1] 的网络层,INT8 量化的 ,误差极小。但如果某些权重范围极大(如 [-100, 100]),,误差就不可忽略了——这正是需要量化感知训练(QAT)的原因。
训练后量化(PTQ)vs 量化感知训练(QAT)
Section titled “训练后量化(PTQ)vs 量化感知训练(QAT)”- 训练后量化(Post-Training Quantization, PTQ):模型训练完成后直接量化。只需少量校准数据(calibration data,约 100-500 张样本)来估计激活值的统计分布,无需重训练。简单快速,但极端量化(如 INT4)时精度损失大。
- 量化感知训练(Quantization-Aware Training, QAT):在训练过程中模拟量化误差。具体做法是在前向传播时插入”假量化”操作(Fake Quantization):先按量化公式计算,再反量化回浮点,模拟真实的量化-反量化过程。这样模型在训练时就能感知量化带来的信息损失,学会调整权重来补偿。反向传播时用直通估计器(Straight-Through Estimator, STE)——对 round() 函数的梯度直接当作 1 处理(因为 round 不可导)。
剪枝:稀疏化网络
Section titled “剪枝:稀疏化网络”幅度剪枝(Magnitude Pruning)
Section titled “幅度剪枝(Magnitude Pruning)”最经典也最常用的剪枝方法:直接删除绝对值最小的权重。直觉是”小权重对输出的贡献也小,删了影响不大”。
# 幅度剪枝的核心步骤1. 计算所有权重的绝对值 |w|2. 设定稀疏度目标 sparsity(如 50%)3. 找到第 sparsity 分位数的阈值 threshold4. 将 |w| < threshold 的权重置零(结构化)或删除(非结构化)5. (可选)对剪枝后的网络做几步微调,恢复精度非结构化 vs 结构化剪枝
Section titled “非结构化 vs 结构化剪枝”- 非结构化剪枝(Unstructured Pruning):逐个权重置零,产生不规则的稀疏模式。理论上可以达到极高的稀疏度(如 90%+),但需要专门的稀疏矩阵运算库才能加速——标准 GPU/CPU 硬件对不规则稀疏的加速很有限。
- 结构化剪枝(Structured Pruning):整行、整列、整个通道(channel)或整个注意力头为单位删除。稀疏模式规则,可以直接减少矩阵维度,标准硬件就能加速。代价是同等精度下稀疏度不如非结构化。
# 结构化剪枝示例:按通道剪枝# 假设第 L 层有 256 个输出通道,剪掉贡献最小的 50%channel_importance = sum(|W_L[:, c, :, :]| for each channel c) # 每个通道的 L1 范数threshold = percentile(channel_importance, 50) # 第 50 百分位keep_mask = channel_importance > threshold # 保留 128 个通道# 删除不需要的通道后,第 L 层和第 L+1 层的维度都要相应缩减彩票假设(Lottery Ticket Hypothesis)
Section titled “彩票假设(Lottery Ticket Hypothesis)”2018 年 Frankle 和 Carbin 提出了一个著名发现:在一个训练好的稠密网络中,存在一个极小的子网络(“中奖彩票”),如果用原始初始化权重重新训练这个子网络,能达到和原始网络相当甚至更好的精度。这意味着大网络中大部分参数是”冗余的”,真正起作用的只是少数关键连接。
这个假设的实践意义:剪枝不是简单的”删小的”,而是要找到那个”中奖子网络”。后续工作(如 LTH 的迭代版本、边缘弹出算法)进一步优化了寻找中奖彩票的效率。
知识蒸馏:暗知识的传递
Section titled “知识蒸馏:暗知识的传递”知识蒸馏的核心是让小模型学习大模型的输出分布,而非只学最终标签。
温度 softmax 的数学
Section titled “温度 softmax 的数学”标准 softmax 将 logits 转换为概率分布:
蒸馏时引入温度参数 T(Temperature)来软化分布:
当 T=1 时就是标准 softmax;T 越大,分布越”平滑”(各类别概率越接近均匀)。例如对于一张猫的图片,标准 softmax 可能输出 [0.99, 0.005, 0.003, 0.002](猫 99%,狗 0.5%,汽车 0.3%),而 T=4 的软标签可能是 [0.7, 0.15, 0.1, 0.05]——这暴露了”猫和狗在视觉上更相似”这个关键信息(暗知识 / Dark Knowledge),而硬标签只告诉你”这是猫”。
蒸馏损失函数
Section titled “蒸馏损失函数”乘子的含义:因为 softmax 中除以了 T,梯度会被缩小 倍,所以反向传播时要乘回 来保持梯度量级不变。 通常取 0.5-0.9(软标签权重高于硬标签,因为软标签信息更丰富)。
特征蒸馏(Feature-based Distillation)
Section titled “特征蒸馏(Feature-based Distillation)”除了在输出层做蒸馏,还可以在中间特征层做对齐(让学生网络的中间层特征逼近教师网络的中间层特征)。代表方法 FitNets、AT(Attention Transfer):
特征蒸馏通常比纯输出蒸馏效果更好——中间层特征包含了更丰富的结构化信息。
三大压缩方法对比
Section titled “三大压缩方法对比”知识蒸馏:Teacher → Student
Section titled “知识蒸馏:Teacher → Student”量化原理:FP32 → INT8
Section titled “量化原理:FP32 → INT8”PyTorch 动态量化(最简量化示例)
Section titled “PyTorch 动态量化(最简量化示例)”import torchimport torch.nn as nnfrom torchvision.models import mobilenet_v3_small
model = mobilenet_v3_small(pretrained=True).eval() # 加载预训练 MobileNet
# 动态量化 Linear 层:FP32 → INT8(一行搞定)quantized = torch.quantization.quantize_dynamic( model, {nn.Linear}, dtype=torch.qint8)
print(f"原模型: {sum(p.numel() for p in model.parameters())} 参数")# 量化后体积更小、CPU 推理更快dummy = torch.randn(1, 3, 224, 224)print(quantized(dummy).argmax()) # 推理正常输出PyTorch 静态量化(PTQ,含校准)
Section titled “PyTorch 静态量化(PTQ,含校准)”import torchimport torch.nn as nnfrom torchvision.models import mobilenet_v3_small
model = mobilenet_v3_small(pretrained=True).eval()
# 静态量化需要对 Conv2D 和 Linear 都量化# 第 1 步:准备量化配置model.qconfig = torch.quantization.get_default_qconfig('fbgemm') # x86 CPUmodel_fused = torch.quantization.fuse_modules(model, [['features.0.0', 'features.0.1']])
# 第 2 步:插入观察者(Observer)model_prepared = torch.quantization.prepare_qat(model_fused)
# 第 3 步:用校准数据做前向传播(收集激活值统计信息)for _ in range(200): dummy = torch.randn(1, 3, 224, 224) model_prepared(dummy)
# 第 4 步:转换为量化模型model_quantized = torch.quantization.convert(model_prepared)print(f"量化后模型大小: {torch.save(model_quantized.state_dict(), 'tmp.pth')}")知识蒸馏概念代码
Section titled “知识蒸馏概念代码”import torch.nn as nnimport torch.nn.functional as F
def distill_loss(student_logits, teacher_logits, labels, T=4.0, alpha=0.5): """学生模仿教师的输出分布 + 真实标签""" soft = F.kl_div( F.log_softmax(student_logits / T, dim=1), # 学生软概率 F.softmax(teacher_logits / T, dim=1), # 教师软概率 reduction="batchmean") * (T * T) # 温度缩放 hard = F.cross_entropy(student_logits, labels) # 硬标签损失 return alpha * soft + (1 - alpha) * hard # 加权组合知识蒸馏完整训练循环
Section titled “知识蒸馏完整训练循环”import torchimport torch.nn as nnimport torch.nn.functional as F
def train_with_distillation(student, teacher, train_loader, epochs=50, T=4.0, alpha=0.7, lr=0.001): """ 完整的知识蒸馏训练循环。 student: 小模型(学生) teacher: 大模型(教师,冻结参数) """ teacher.eval() # 教师模型不更新 for p in teacher.parameters(): p.requires_grad = False
optimizer = torch.optim.AdamW(student.parameters(), lr=lr, weight_decay=1e-4) scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=epochs)
for epoch in range(epochs): student.train() for images, labels in train_loader: # 教师前向(不计算梯度) with torch.no_grad(): teacher_logits = teacher(images)
# 学生前向 student_logits = student(images)
# 蒸馏损失 loss = distill_loss(student_logits, teacher_logits, labels, T=T, alpha=alpha)
optimizer.zero_grad() loss.backward() optimizer.step() scheduler.step() print(f"Epoch {epoch+1}/{epochs}, Loss: {loss.item():.4f}")PyTorch 幅度剪枝示例
Section titled “PyTorch 幅度剪枝示例”import torchimport torch.nn.utils.prune as prune
def magnitude_prune(model, amount=0.5): """对模型所有 Conv2d 做非结构化幅度剪枝""" for name, module in model.named_modules(): if isinstance(module, torch.nn.Conv2d): prune.l1_unstructured(module, name='weight', amount=amount) prune.remove(module, 'weight') # 永久化剪枝(删除零权重) print(f"剪枝 {name}: 稀疏度 {amount*100:.0f}%")
# 使用:将 MobileNet 50% 的卷积权重剪掉model = mobilenet_v3_small(pretrained=True)magnitude_prune(model, amount=0.5)# 剪枝后建议做几个 epoch 的微调恢复精度训练技巧与实践要点
Section titled “训练技巧与实践要点”量化的实践要点
Section titled “量化的实践要点”- 优先尝试 PTQ:训练后量化是最快的压缩手段。对于 INT8,大多数 CNN 在 PTQ 后精度损失 < 1%。先 PTQ,不行再上 QAT。
- 校准数据要代表性:PTQ 的校准数据必须来自真实推理分布(同域、同分辨率),否则激活值统计不准,量化误差大。
- 量化敏感层跳过:某些层(如最后的分类头、超低 bit 输出)对量化极敏感,可以保持 FP32(混合精度量化)。
- INT4 是极限挑战:INT4 量化通常精度损失显著,需要 QAT + 特殊技巧(如分组量化、Learnable Quantization Scale)。
剪枝的实践要点
Section titled “剪枝的实践要点”- 渐进式剪枝:不要一步到位剪到 90%。从 20% 开始,逐步增加到目标稀疏度,每次剪枝后微调几个 epoch,效果远好于一次性剪枝。
- 剪枝后微调至关重要:剪枝破坏了网络的功能,必须用原学习率(或更低)微调恢复。通常微调 10-30% 的原始训练 epoch 数即可恢复。
- 结构化剪枝更适合落地:非结构化剪枝虽然稀疏度高,但需要专门的稀疏计算硬件支持(如 NVIDIA Ampere 的 2:4 结构化稀疏)。结构化剪枝(通道剪枝)直接减少矩阵维度,标准硬件即受益。
蒸馏的实践要点
Section titled “蒸馏的实践要点”- 教师选择:教师越大、越强,学生受益越多。用 10 倍参数量的教师蒸馏出的学生,通常比自己训练的学生高 2-5% 精度。
- 温度选择:T=2-10 是常用范围。类别数越多(如 1000 类),T 可以大一些(如 4-6),让软标签更平滑。
- 数据增强一致性:教师和学生必须看到相同的输入(含相同数据增强),否则软标签对不上。
- 特征蒸馏增强效果:在中间层加特征对齐损失,通常比纯输出蒸馏多 1-3% 精度。
- 经典流水线:蒸馏 → 剪枝 → 量化。蒸馏先得到一个好学生,剪枝去冗余,量化减精度。每步都要评估精度,及时止损。
- 量化蒸馏:在蒸馏的同时做量化感知训练,让学生模型在量化约束下学习教师的暗知识——这是 INT4 量化模型能保持高精度的关键技巧。
最新进展(2024-2026)
Section titled “最新进展(2024-2026)”大语言模型(LLM)量化
Section titled “大语言模型(LLM)量化”大模型的爆发催生了大量 LLM 专用量化方法:
- GPTQ:基于二阶信息(近似 Hessian)的训练后量化方法。能将 LLaMA 等大模型量化到 3-4 bit,精度损失极小。核心思想是逐层用 Hessian 信息指导量化,补偿每个权重量化对输出的影响。
- AWQ(Activation-aware Weight Quantization):基于”不是所有权重同等重要”的洞察——激活值大的通道对应的权重对输出影响也大。AWQ 通过保持这些”显著”通道的高精度来减少整体量化误差。
- SmoothQuant:将量化的难度从激活值转移到权重上。通过数学等价变换
Y = (X / s) * (s * W),将激活值中的”离群点”(outlier,个别极大的激活值导致量化困难)缩小 s 倍,同时将权重放大 s 倍。因为权重分布更均匀,放大后量化误差更可控。 - GGUF / llama.cpp 格式:社区驱动的量化格式,支持 2-8 bit 的混合精度量化。llama.cpp 让普通用户在笔记本甚至手机上运行量化后的 LLM。常见量化等级如 Q4_K_M(4 bit 均值,关键层保留更高精度)在消费级硬件上广受欢迎。
- EXL2 / EXL3:ExLlamaV2 的量化方案,支持任意 bit 精度(如 2.5 bit、4.5 bit),通过逐层最优 bit 分配实现极致压缩。
1-bit / 2-bit 大模型
Section titled “1-bit / 2-bit 大模型”2024 年最激进的研究方向是极低比特量化:
- BitNet(1-bit LLM):微软提出的 1-bit Transformer 架构,权重只有 -1 / 0 / +1 三种值。推理时完全不需要矩阵乘法(只需加减法),内存占用降到原来的 1/32。BitNet b1.58(2024)将权重三值化为 {-1, 0, 1},在 3B 参数量级上匹配了 FP16 LLaMA 的精度。
- 训练时量化(Quantization in Training):传统方法先训练 FP32 再量化(PTQ/QAT),新方法直接在低精度下训练——权重在训练过程中就是 INT4 或 1-bit,省去量化步骤。
结构化剪枝在 Transformer 中的应用
Section titled “结构化剪枝在 Transformer 中的应用”- LLM-Pruner / Wanda:针对大语言模型的结构化剪枝方法。Wanda(Pruning by Weights and Activations)不需要重训练,只需一次前向传播就能确定哪些权重可以安全剪除。
- Sheared LLaMA:将 LLaMA-7B 通过结构化剪枝压缩到 2.7B/1.3B,精度接近同尺寸的从头训练模型。
推测解码(Speculative Decoding)
Section titled “推测解码(Speculative Decoding)”不是压缩模型本身,而是通过”小模型猜测 + 大模型验证”的方式加速 LLM 推理:一个小模型(draft model)先生成候选 token,大模型(target model)并行验证。验证通过的部分无需大模型逐 token 自回归生成,推理速度提升 2-3 倍且输出完全一致。
移动端 LLM 部署
Section titled “移动端 LLM 部署”- MLC-LLM:基于 TVM 编译器的端侧 LLM 推理框架,支持将量化后的 LLM 部署到 iPhone、Android、浏览器。
- ExecuTorch:PyTorch 官方端侧推理框架(2024 正式发布),支持 LLM 和 CNN 的端侧量化部署。
- Apple MLX:Apple 的机器学习推理框架,针对 Apple Silicon 优化了量化 LLM 推理,统一内存架构让手机端运行 7B 模型成为可能。
- 手机端 AI(MobileNet 系列):Google 的 MobileNet 通过深度可分离卷积 + 量化,让手机实时跑图像分类、人脸解锁、AR 特效——Pixel、iPhone 的相机 AI 功能都依赖这类轻量模型。详见MobileNet 与移动端推理。
- 自动驾驶芯片(Tesla FSD / 地平线):车载芯片算力受限、功耗敏感,量产方案均用量化(INT8)+ 剪枝把检测网络压到芯片可实时运行的尺寸,延迟要求 < 30ms。
- 边缘设备部署(智能摄像头 / IoT):工厂产线缺陷检测、智能门禁人脸识别,依赖 ONNX Runtime / OpenVINO 做量化推理,在无 GPU 的边缘盒子上跑深度学习。
- 降低云端推理成本:大厂 API 服务通过量化(FP16→INT8)将单卡吞吐翻倍,直接砍掉一半 GPU 服务器——百亿级 token 服务中,这是数百万美元级的成本节省。
- 大模型本地部署:通过 GGUF 4-bit 量化,LLaMA-3-8B 可以在 6GB 显存的消费级显卡上运行,Phi-3-mini 量化后可在手机上运行——这让个人隐私数据无需上云的本地 AI 成为现实。
典型类库与工具
Section titled “典型类库与工具”| 类库 | 语言 | 说明 |
|---|---|---|
| TensorRT | C++/Python | NVIDIA 官方推理加速库,支持 INT8/FP16 量化与算子融合 |
| ONNX Runtime | C++/Python | 跨平台推理引擎,支持动态量化,CPU/GPU/移动端通吃 |
| OpenVINO | C++/Python | Intel 推理工具包,针对 Intel CPU/核显优化,支持 PTQ |
| torch.quantization | Python | PyTorch 内置量化工具,支持动态量化、静态量化、QAT |
| NNCF | Python | OpenVINO 的神经网压缩框架,集成量化+剪枝+蒸馏 |
| TFLite | C++/Python | TensorFlow Lite,移动端推理标配,支持全整数量化 |
| llama.cpp | C++ | 社区驱动的 LLM 推理框架,支持 GGUF 格式 2-8bit 量化 |
| AutoGPTQ | Python | LLM 训练后量化工具,基于 GPTQ 算法 |
| AutoAWQ | Python | LLM 量化工具,基于 AWQ 算法 |
| MLC-LLM | Python/C++ | 端侧 LLM 部署框架,支持量化模型在手机/浏览器运行 |
| 术语 | 英文 | 解释 |
|---|---|---|
| 量化 | Quantization | 将权重/激活从高精度浮点压缩到低位整数(INT8/INT4) |
| 训练后量化 | Post-Training Quantization (PTQ) | 模型训练完成后直接量化,无需重训练,简单快速 |
| 量化感知训练 | Quantization-Aware Training (QAT) | 训练时模拟量化误差,精度比 PTQ 更高 |
| 直通估计器 | Straight-Through Estimator (STE) | QAT 中处理 round() 不可导的技巧,反向传播时当作恒等映射 |
| 对称量化 | Symmetric Quantization | 零点固定为 0 的量化方式,适用于权重 |
| 非对称量化 | Asymmetric Quantization | 零点不为 0 的量化方式,适用于非负的激活值 |
| 剪枝 | Pruning | 删除权重接近零的冗余连接,使网络稀疏化 |
| 非结构化剪枝 | Unstructured Pruning | 逐个权重置零,稀疏度高但需要专用硬件加速 |
| 结构化剪枝 | Structured Pruning | 以通道/层为单位删除,标准硬件即可加速 |
| 彩票假设 | Lottery Ticket Hypothesis | 稠密网络中存在稀疏子网络,用原始初始化重训可达到同等精度 |
| 知识蒸馏 | Knowledge Distillation | 用大模型(教师)的输出指导小模型(学生)训练 |
| 教师/学生模型 | Teacher / Student Model | 蒸馏中的大模型(教师)与被训练的小模型(学生) |
| 稀疏性 | Sparsity | 网络中零值参数的比例,越高模型越”瘦” |
| ONNX | Open Neural Network Exchange | 开放神经网络交换格式,跨框架部署的中间表示 |
| 暗知识 | Dark Knowledge | 教师模型软标签中蕴含的类别间相似度信息 |
| 温度参数 | Temperature (T) | 蒸馏中软化 softmax 分布的参数,T 越大分布越平滑 |
| 推测解码 | Speculative Decoding | 小模型先生成候选、大模型验证的 LLM 推理加速方法 |
- 知识蒸馏开山作:Hinton et al., “Distilling the Knowledge in a Neural Network”, NeurIPS Workshop 2015. 提出”暗知识”与温度 softmax,奠定了知识蒸馏范式。
- 深度压缩:Han et al., “Deep Compression: Compressing Deep Neural Networks with Pruning, Trained Quantization and Huffman Coding”, ICLR 2016. 将剪枝、量化、编码三者串联,AlexNet 压缩 35× 几乎不损精度。
- 模型剪枝:Han et al., “Learning both Weights and Connections for Efficient Neural Networks”, NeurIPS 2015. 基于”小权重不重要”的幅度剪枝法,是工业界最常用的剪枝思路。
- 彩票假设:Frankle & Carbin, “The Lottery Ticket Hypothesis: Finding Sparse, Trainable Neural Networks”, ICLR 2019. 揭示稠密网络中存在可独立训练的稀疏子网络。
- MobileNet 系列:Howard et al., “MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications”, 2017. 深度可分离卷积的奠基工作,移动端 CNN 的标杆。
- GPTQ:Frantar et al., “GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers”, ICLR 2023. LLM 训练后量化的里程碑工作。
- AWQ:Lin et al., “AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration”, MLSys 2024. 基于激活感知的大模型量化方法。
- BitNet:Wang et al., “BitNet: Scaling 1-bit Transformers for Large Language Models”, 2023. 1-bit LLM 架构的奠基工作;后续 BitNet b1.58 (2024) 将权重三值化。
- SmoothQuant:Xiao et al., “SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models”, ICML 2023. 将量化难度从激活转移到权重的方法。