1. 为什么模型压缩是部署阶段的必修课模型压缩这件事很多人第一次接触是在把训练好的模型往边缘设备或者移动端搬的时候。训练阶段用服务器显卡跑得好好的网络一到部署环节就发现显存吃紧、推理延迟高、功耗压不住。我最早踩这个坑是在一个图像分类的小项目上训练时用的是标准卷积网络参数量大概两千多万在服务器上单张推理不到十毫秒结果往嵌入式板子上移植时光模型文件就接近一百兆内存直接放不下。那时候我才意识到训练和部署是两个完全不同的约束环境训练追求精度上限部署追求的是在有限算力、有限内存、有限功耗下把精度维持住。模型压缩要解决的核心矛盾就是这个在尽量不损失精度的前提下把模型的参数量、计算量、存储占用降下来。围绕这个目标目前主流有四条技术路线——剪枝、量化、蒸馏、AutoML。这四条路线不是互斥的实际项目里经常组合使用比如先剪枝再量化或者用蒸馏训练一个小模型再做量化部署。理解每一条路线的原理和适用边界比记住某个工具的命令行参数重要得多。这篇文章面向的是已经能跑通基础训练流程、准备把模型往实际环境部署的读者。我会把四条路线的核心原理、实操步骤、参数选择逻辑以及我在实际项目中踩过的坑都摊开讲。每条路线都会给出可复现的操作思路而不是停留在概念层面。如果你正在为模型太大、推理太慢发愁或者想系统梳理一下模型压缩的知识体系下面的内容应该能帮到你。在展开之前先明确一个判断标准压缩效果不能只看模型变小了多少要看精度、速度、内存三者之间的平衡。我见过有人把模型压到原来的十分之一结果精度掉了十几个点这种压缩在业务上毫无意义。所以后面每讲一种方法我都会强调它的精度损失特征和适用场景。2. 剪枝从冗余参数里挤出推理速度2.1 剪枝到底在剪什么剪枝的基本假设是训练好的神经网络里存在大量冗余参数这些参数对最终输出的贡献很小去掉之后精度几乎不受影响。这个假设在实践中有大量证据支撑——很多网络在剪掉百分之五十甚至更多参数后精度只掉一两个点。剪枝分两大类结构化剪枝和非结构化剪枝。非结构化剪枝是把权重矩阵里绝对值小的元素置零产生稀疏矩阵。听起来很美好但问题在于普通硬件和推理框架对稀疏矩阵的支持很差置零之后的权重在内存里还是占位置计算时也不会跳过所以非结构化剪枝往往只减小了模型文件的理论大小实际推理速度提升有限。结构化剪枝则是直接删掉整个卷积核、整个通道或者整个层这样得到的模型是稠密的推理框架能真正加速。我个人的经验是如果目标是实际部署加速优先考虑结构化剪枝如果只是想把模型文件压小便于存储或传输非结构化剪枝配合稀疏存储格式也可以用。下面重点讲结构化剪枝因为它的部署价值更高。2.2 基于权重重要性的通道剪枝实操通道剪枝的核心是给每个通道算一个重要性分数然后按分数排序剪掉分数最低的一批通道。重要性怎么算有几种常见做法L1范数把某个通道所有卷积核权重的绝对值加起来作为该通道的重要性。实现简单效果稳定是我最常用的基线方法。L2范数类似L1但对大权重的惩罚更重有时能选出更关键的通道。BN层缩放因子如果网络里有批归一化层可以用BN层的缩放因子作为重要性指标这是某篇经典剪枝论文提出的思路好处是缩放因子在训练中会被网络自己调整相当于让网络自己告诉哪些通道重要。梯度信息用损失函数对通道输出的梯度来衡量重要性计算成本高一些但在某些任务上更准。实操流程大致是这样的先正常训练一个精度达标的大模型然后对每一层计算通道重要性设定一个全局或逐层的剪枝比例剪掉对应通道最后对剪枝后的模型做微调恢复精度。这里有个关键细节剪枝比例不要一次性设太高。我一般从百分之十开始剪完微调看精度恢复情况再决定要不要继续剪。一次性剪百分之五十精度往往崩得厉害微调也救不回来。微调阶段的学习率要调小通常是原始训练学习率的十分之一到百分之一因为此时模型已经接近一个局部最优学习率太大会把好不容易保留的结构破坏掉。微调的轮数不用太多几个epoch通常就够具体看精度曲线什么时候平稳。2.3 剪枝实操中最容易翻车的三个点第一个坑是忽略了通道之间的依赖关系。在残差网络里残差分支和主分支的输出要相加如果你只剪了主分支的通道而没剪残差分支对应的通道相加时维度对不上模型直接报错。所以剪枝时要沿着计算图追踪通道的依赖把关联的通道一起处理。这个问题在简单的链式网络里不存在但在有跨层连接的网络里非常常见。第二个坑是逐层独立剪枝导致全局失衡。如果每一层都按同样的比例剪可能某些本来就紧凑的层被剪过头而某些冗余的层剪得不够。更好的做法是设定全局的参数量或计算量目标然后按各层的敏感度分配剪枝比例。敏感度高的层少剪敏感度低的层多剪。敏感度可以通过逐层试剪并观察精度变化来估计虽然费时间但比拍脑袋定比例靠谱。第三个坑是剪枝后没有重新校准BN层统计量。剪枝改变了每层的输入分布BN层之前记录的均值和方差不再准确。剪枝后应该用一批训练数据重新跑一遍前向传播让BN层更新统计量然后再微调。这一步很多人会漏掉导致剪枝后精度莫名其妙掉很多。提示剪枝比例、微调学习率、微调轮数这三个参数需要一起调建议固定其中两个只调一个否则很难判断是哪个参数起了作用。3. 量化用低位宽换取推理吞吐3.1 量化的本质是数值表示的压缩神经网络训练时默认用32位浮点数存储权重和激活值。量化就是把32位浮点换成更低位的表示比如16位浮点、8位整数甚至4位、2位。位宽越低模型占用越小计算越快但精度损失风险越大。量化分训练后量化和量化感知训练。训练后量化是拿训练好的模型直接转成低位表示不需要重新训练操作简单适合快速验证。量化感知训练是在训练过程中模拟量化的误差让网络提前适应低位表示精度通常更好但需要重新训练成本高。我一般先用训练后量化试水如果精度掉得能接受就直接用如果掉太多再考虑量化感知训练。8位整数量化在大多数视觉任务上精度损失很小往往一个点以内是性价比最高的选择。16位浮点量化精度几乎无损但压缩比只有二比一适合对精度极其敏感的场景。3.2 对称量化与非对称量化的选择逻辑量化的核心操作是把浮点数映射到整数。假设要把浮点范围映射到8位整数需要确定一个缩放因子和一个零点。对称量化把零点固定在零正负范围对称非对称量化的零点可以偏移能更精确地表示非对称分布的数据。权重通常用对称量化因为权重分布一般以零为中心。激活值经过ReLU之后都是非负的分布不对称用非对称量化更合适。这个选择不是绝对的具体要看推理框架支持哪种模式。有些框架对对称量化有硬件加速即使精度略差也值得用。逐层量化和逐通道量化是另一个维度。逐层量化对整层用同一个缩放因子实现简单但精度差逐通道量化对每个通道单独算缩放因子精度好但存储缩放因子的开销增加。对于卷积层逐通道量化几乎是标配因为不同通道的权重分布差异可能很大。3.3 量化实操中的精度排查思路量化后精度掉了怎么定位问题我的排查顺序是这样的先看是哪一层掉得最狠。逐层做量化观察每层输出的误差找到误差最大的层。通常第一层和最后一层比较敏感中间层相对鲁棒。检查激活值的动态范围。如果某一层的激活值范围特别大量化后的分辨率就不够小值会被压成零。这种情况可以考虑对激活值做截断把极端值裁掉牺牲一点动态范围换分辨率。看是否有离群值。某些通道的权重或激活值存在极端的离群值会把整个量化范围拉大导致其他值量化精度下降。处理办法是对离群值单独处理或者用更细粒度的量化。尝试混合精度。敏感层用16位其他层用8位在精度和压缩比之间找平衡。注意量化后的模型一定要在真实推理框架上测精度不能只在训练框架里模拟。不同框架的量化实现细节不同模拟精度和实际精度可能有差距。4. 蒸馏让小模型学会大模型的本事4.1 知识蒸馏的核心思想蒸馏的思路和剪枝、量化完全不同。剪枝和量化是在一个大模型上做减法蒸馏是直接训练一个小模型让这个小模型去模仿大模型的行为。大模型叫教师模型小模型叫学生模型。为什么学生模型能学到比直接训练更好的效果关键在于软标签。直接训练学生模型时监督信号是硬标签比如分类任务里就是one-hot向量正确类为1其他为0。但教师模型的输出是软标签比如正确类概率0.9其他类有0.05、0.03这样的分布。这个分布包含了类与类之间的相似性信息学生模型学这个分布相当于获得了额外的知识。举个例子在手写数字分类里数字1和数字7长得像教师模型对一张写着1的图片可能输出1的概率0.85、7的概率0.1这个0.1就告诉学生模型“这张图有点像7”学生模型学到的决策边界会比只学硬标签更平滑。4.2 温度参数与损失函数设计蒸馏的损失函数通常由两部分组成学生模型输出和硬标签的交叉熵加上学生模型输出和教师模型软标签的散度。软标签部分需要一个温度参数T来控制分布的平滑程度。T等于1时就是普通的softmax输出T越大分布越平滑类与类之间的相对关系信息越丰富。温度参数怎么选我一般从3到5开始试。T太小软标签接近硬标签蒸馏效果不明显T太大分布过于平滑正确类的信息被稀释。这个参数和任务有关类别多的任务可以用大一点的T类别少的任务用小一点的T。两部分损失的权重也需要调。软标签损失的权重通常设大一些因为它是蒸馏的主要知识来源硬标签损失起辅助作用防止学生模型偏离真实目标太远。我常用的权重比是软标签损失占七成硬标签损失占三成但这个比例不是固定的要看具体任务。4.3 蒸馏的几种变体和适用场景最基本的蒸馏是离线蒸馏先训练好教师模型再用教师模型指导学生模型。这是最常用的方式实现简单教师模型可以很大很强。在线蒸馏是教师和学生同时训练互相学习。这种方式不需要预训练教师但训练过程更复杂效果也不一定比离线蒸馏好。自蒸馏是模型自己教自己比如用深层网络的输出指导浅层网络或者用模型后期的预测指导前期的预测。这种方式不需要额外的教师模型适合没有大模型可用的场景。还有一种思路是多教师蒸馏用多个不同结构的教师模型共同指导学生学生能学到更丰富的知识。但多个教师的输出需要融合融合策略本身也是个需要调的问题。蒸馏的局限在于学生模型的结构需要人工设计。你得先想好学生模型长什么样然后才能开始蒸馏。学生模型太小容量不够学不到教师的知识学生模型太大压缩效果不明显。这个结构设计往往靠经验和反复试验。5. AutoML让搜索算法帮你找压缩方案5.1 AutoML在模型压缩中的角色前面三种方法都需要人工设定超参数剪枝比例、量化位宽、学生模型结构。这些超参数的选择很依赖经验而且不同任务的最优值不一样。AutoML的思路是把这些选择交给搜索算法让算法在给定的搜索空间里自动找到最优的压缩方案。在模型压缩场景下AutoML主要做两件事搜索网络结构和搜索压缩策略。搜索网络结构是直接找一个又小又好的网络比如经典的网络结构搜索。搜索压缩策略是给定一个大网络自动决定每层剪多少、量化多少位。5.2 搜索空间与搜索策略的设计搜索空间定义了算法可以探索的范围。以剪枝为例搜索空间可以是每层的剪枝比例比如每层从0到0.9之间选一个值。搜索空间越大找到最优解的可能性越高但搜索成本也越大。搜索策略决定怎么在搜索空间里找。常见的有强化学习用一个控制器网络生成压缩策略根据压缩后模型的精度给控制器反馈控制器逐渐学会生成更好的策略。效果不错但训练成本高。进化算法维护一群候选方案每轮淘汰差的、变异好的逐步进化出最优方案。实现相对简单适合并行化。梯度优化把压缩策略参数化用梯度下降直接优化。速度快但容易陷入局部最优。贝叶斯优化用高斯过程建模目标函数在探索和利用之间平衡。适合搜索空间不大的场景。我实际用下来进化算法和贝叶斯优化在中小规模搜索上性价比最高强化学习适合搜索空间很大、计算资源充足的场景。5.3 AutoML压缩的落地成本与收益权衡AutoML听起来很美好但落地时有几个现实问题。首先是搜索成本每评估一个候选方案都要训练或微调一次模型如果搜索空间有几百个候选计算成本可能比人工调参还高。其次是搜索结果的泛化性在验证集上搜到的最优方案在测试集上不一定最优存在过拟合搜索集的风险。我的建议是如果任务单一、数据稳定AutoML值得投入如果任务多变、数据分布经常变人工调参加经验规则可能更灵活。另外AutoML搜出来的方案往往比较“怪”可解释性差部署时可能遇到框架不支持的问题这也是需要考虑的成本。一个折中做法是用AutoML搜索关键层的压缩策略其他层用固定策略。这样既利用了自动搜索的优势又控制了搜索成本和部署复杂度。6. 四条路线的组合策略与选型建议6.1 不同部署场景下的路线选择四条路线不是非此即彼实际项目里经常组合。下面这张表是我根据经验整理的选型参考场景特征首选路线次选路线说明服务器端推理追求吞吐量化剪枝8位量化加速明显精度损失小移动端部署内存受限剪枝量化蒸馏先剪枝减参数再量化减位宽嵌入式设备算力极低蒸馏量化AutoML直接训小模型再量化精度敏感不能掉点蒸馏16位量化蒸馏可控性更强快速验证压缩效果训练后量化非结构化剪枝不需要重新训练追求极致压缩比AutoML剪枝蒸馏量化组合使用但成本高选型的核心判断依据是你的瓶颈是内存、算力还是功耗。内存瓶颈优先剪枝和量化算力瓶颈优先量化和蒸馏功耗瓶颈通常需要组合方案。6.2 组合压缩的实操顺序如果决定组合使用顺序很重要。我推荐的顺序是先蒸馏得到小模型再剪枝去掉冗余最后量化压缩位宽。理由是蒸馏需要完整的训练过程放在最前面剪枝会改变网络结构放在蒸馏之后量化对结构不敏感放在最后。另一个顺序是先剪枝再蒸馏把大模型剪枝得到一个中等模型作为教师再蒸馏出更小的学生。这种方式适合教师模型太大、蒸馏成本高的情况。量化通常放在最后因为量化后的模型很难再做结构上的修改。如果先量化再剪枝剪枝操作在低位表示上进行精度损失会叠加很难控制。6.3 压缩效果的评估与验收标准压缩做完怎么判断合不合格我通常看四个指标精度损失压缩后模型在测试集上的精度和原始模型的差距。一般要求在一个点以内严格场景要求半个点以内。压缩比模型文件大小或参数量的下降比例。这个指标要和精度一起看单独看没有意义。推理速度在目标硬件上的实际推理时间。注意要在真实硬件上测不能只看理论计算量。内存占用推理时的峰值内存。这个指标在移动端和嵌入式场景特别重要。验收时一定要在目标部署环境上测不能在训练环境上测完就下结论。我见过在服务器上量化后速度提升明显到了移动端因为硬件不支持某些量化指令速度反而下降的情况。7. 我在实际项目中积累的几条经验第一条经验是不要追求单次压缩到位。模型压缩是个迭代过程先小幅度压缩验证精度和速度再决定下一步。一次性压太狠出了问题很难定位是哪个环节导致的。第二条经验是保留原始模型和中间产物。剪枝前的模型、量化前的模型、蒸馏用的教师模型都要保存好。压缩过程中经常需要回退到某一步重新调整没有中间产物就得从头再来。第三条经验是精度评估要用真实数据分布。有些项目用验证集评估压缩效果很好上线后精度掉得厉害原因是验证集和线上数据分布不一致。压缩会放大这种分布差异所以评估时要用能代表线上分布的数据。第四条经验是关注推理框架的兼容性。训练框架支持的压缩操作推理框架不一定支持。比如某些框架不支持动态量化某些硬件不支持非对称量化。选压缩方案前先确认目标推理框架的能力边界。第五条经验是压缩不是免费的。剪枝需要微调量化需要校准蒸馏需要重新训练AutoML需要搜索每一种方法都有时间成本。项目排期时要把这些成本算进去不要以为压缩就是跑个脚本的事。最后说一个我踩过的坑有一次做量化训练框架里模拟精度只掉了零点三个点我觉得没问题就直接部署了结果实际推理精度掉了五个点。后来排查发现是推理框架的量化实现和训练框架的模拟方式不一致激活值的截断策略不同。从那以后我养成了习惯任何压缩方案都要在目标推理框架上完整测一遍精度模拟结果只能作为参考。这个习惯帮我避免了好几次线上事故。