模型压缩“三驾马车”:如何用蒸馏、量化、剪枝将大模型“瘦身”10倍,推理速度飙升4.5倍? 目录模型压缩与加速概述知识蒸馏:大模型教小模型模型量化:FP16 到 INT4模型剪枝:去除冗余参数压缩方法的协同:组合策略压缩效果评估实践建议与最佳实践摘要模型压缩与加速通过知识蒸馏、量化和剪枝的协同,同时压低模型体积、推理延迟与显存占用。以 7B 模型为基准,蒸馏到 3B 再叠加 INT4 量化与 20% 结构化剪枝,权重体积从 14GB 降至约 1.2GB,吞吐从 20 tokens/s 升至 90 tokens/s,MMLU 精度从 63.2% 回落至 61.6%。不同方法的执行顺序决定最终精度损失落在 2% 还是 5%,本文给出可复现的组合策略与评估方法。1. 模型压缩与加速概述模型压缩与加速的核心目标是让同样的模型跑在更小的内存、更快的延迟和更低的成本上。三种主要手段各有分工:知识蒸馏改变模型结构,量化改变数值表示,剪枝去除冗余权重。本节先回答三个问题:为什么必须压缩、压缩要付什么代价、以及有哪些方法可以选。交付目标达成压缩手段选择部署约束识别FP16 放不下需要 2 倍以上加速算子不允许量化压缩到 1/8训练预算充足校准数据 128 条配合微调恢复通过精度不足速度不达标显存预算 8GB单请求延迟目标 200ms功耗上限 15W知识蒸馏模型量化模型剪枝体积缩小 8 倍吞吐提升 4 倍精度损失低于 5%验收判定上线部署1.1 压缩的必要性部署一个未压缩的 7B 模型,权重本身在 FP16 下占 14GB,加上激活和 KV 缓存,单实例实测峰值在 17-19GB。一张 80GB 的 A100 只能同时驻留 4 个实例;换到 32GB 显存的 V100,权重加运行时开销已经逼近上限,批处理大小被压到 1。边缘设备(8GB 内存)和移动端(6GB)则完全无法加载未压缩权重,这类设备只能跑 3B 以下且经过压缩的模型。延迟和成本是第二重约束。7B FP16 模型在 A100 上单条请求的生成速度约 20 tokens/s,用户可感知的流畅线通常在 40 tokens/s 以上。处理 4096 token 的长上下文时,预填充阶段的首 token 延迟达到300-500ms,交互式体验已经出现明显停顿。按当前云 GPU 时租价格折算,支撑 100 路并发需要约 25 张 A100;压缩到 INT4 后单卡并发翻倍,需要的卡数降到 5 张以内,月度成本差距在 5 倍左右。三类约束驱动的压缩需求可以归纳如下:内存约束:权重、激活、KV 缓存三者叠加超出显存预算,只能降精度或减参数量延迟约束:交互式场景要求首 token 低于 200ms、生成速率不低于 40 tokens/s,需降低计算量成本约束:按吞吐计价,单位 token 成本与占用 GPU 数量和时长成正比,需提高单卡利用率不同精度下同一个模型的存储占用,按 0.5 字节每参数(INT4)到4 字节每参数(FP32)计算:模型参数量FP32FP16INT8INT47B7e928GB14GB7GB3.5GB13B1.3e1052GB26GB13GB6.5GB70B7e10280GB140GB70GB35GB从表格可以看出,INT4 相对 FP16 体积减小 75%,这是把 70B 模型压进 4 卡 80GB 显存的唯一路径。压缩还有额外收益:权重减少意味着显存带宽占用下降,而 LLM 生成阶段是带宽受限的,体积缩小通常直接换算成吞吐提升,两者近似线性关系。实测案例给出数量级参考。某推理服务把 13B FP16 压到 INT4 后,单卡并发从 8 路升到 32 路,单位 token 成本下降 72%。另一个边缘盒子的案例是蒸馏加 INT8 的 3B 模型,从完全无法运行变成24ms 内响应,整机功耗控制在 15W 以内。这两个案例说明压缩的收益同时落在成本和时延两条线上。边界同样存在:压缩解决显存与吞吐,但不改变模型本身的能力上限。对 GSM8K 这类多步推理任务,量化后的精度损失会被放大,压缩前的任务难度决定压缩后的损失上界。任务越难、越依赖长链路推理,压缩比例就越要保守。压缩是部署优化手段,不是能力增强手段,两者的边界在立项时就要写清楚。# 来源:自实现 / memory_footprint.pyfromdataclassesimportdataclass@dataclassclassModelFootprint:"""按精度计算模型权重存储开销,单位字节每参数。"""num_params:intbytes_per_weight={"fp32":4,"fp16":2,"int8":1,"int4":0.5}defsize_gb(self,dtype:str)-float:ifdtypenotinself.bytes_per_weight:raiseValueError(f"不支持的精度{dtype}")returnself.num_params*self.bytes_per_weight[dtype]/1024**3defshrink(self,base:str,target:str)-float:"""返回目标精度相对基准精度的体积缩减比例。"""return1.0-self.size_gb(target)/self.size_gb(base)if__name__=="__main__":m=ModelFootprint(num_params=7_000_000_000)fp16=m.size_gb("fp16")int4=m.size_gb("int4")print(f"7B FP16 占用{fp16:.1f}GB,INT4 占用{int4:.1f}GB")print(f"INT4 相对 FP16 体积减小{m.shrink('fp16','int4')*100:.0f}%")1.2 压缩的权衡压缩是在体积、速度、精度三个目标之间寻找可行域,三种方法在三个维度上的代价分布并不相同。下表给出典型区间,数据来自公开实现和常见部署报告,具体值随模型规模与硬件上下浮动:方法体积缩减速度提升精度损失额外成本知识蒸馏2-10 倍1.5-3 倍1-3%需重新训练,成本高INT8 量化2 倍1.5-2 倍小于 0.5%校准数据,分钟级INT4 量化4 倍2-3 倍1-2%需校准与算子支持结构化剪枝 20%1.25 倍1.5-2 倍3-5%需微调恢复精度权衡的本质是不同应用对三个目标的权重不同。交互式对话场景把首token 延迟当作硬约束,量化是首选,因为它在不动网络结构的前提下把计算压下来,工程量最小。离线批处理场景优先看吞吐和单位成本,可以接受 3-5% 的精度损失换取更高的压缩比,剪枝在这个场景下更常用。医疗和法务场景对精度敏感,损失超过 2% 就不可接受,只能选择蒸馏加 INT8 的组合,并放弃 INT4。架构层面的权衡在于改动范围。量化改动的是数值表示,影响全部算子,必须配套推理内核才能兑现加速,否则只省显存不省时间,吞吐反而因反量化开销下降。蒸馏改动的是模型结构,小模型是全新网络,需要完整训练流程,模型体积的收益来自结构而不是数值。剪枝改动的是张量形状,结构化剪枝让矩阵变窄,任何推理框架都能直接受益,非结构化剪枝则依赖稀疏算子库,收益受硬件支持制约。方法之间并不独立,这一点常被忽略。蒸馏得到的更小模型权重分布更规整,后续量化的精度损失通常更小,两项叠加优于单独使用之和。先量化再剪枝时,量化噪声和剪枝误差会叠加,精度损失可能超过单独使用之和。这解释了为什么第 5 章要把执行顺序纳入决策,而不是简单地叠加三种方法。精度损失的阈值选择有实测依据。量化精度损失在 1-2% 区间时,人工对比评测基本无感知;超过 3% 后,长文本生成的连贯性和代码任务的编译通过率会出现可观察的质量回落。多步推理任务的阈值要更严,GSM8K 类任务建议把回落上限设在 2%。权衡的产出是一份决策表:每个候选方案对应体积、速度、精度三列数字,上线时直接对照阈值勾选。# 来源:自实现 / tradeoff.pyfromcollectionsimportnamedtuple Tradeoff=namedtuple("Tradeoff",["name","size_ratio","speedup","acc_drop"])CANDIDATES=[Tradeoff("fp16 基线",1.0,1.0,0.0),Tradeoff("int8 量化",0.5,1.8,0.5),Tradeoff("int4 量化",0.25,2.6,1.5),Tradeoff("蒸馏到 3B",0.43,1.7,1.0),Tradeoff("三管齐下",0.09,4.5,3.5),]defrank_tradeoffs(w_size:float,w_speed:float,w_acc:float):"""按加权代价排序,权重越大代表该维度越重要。"""scored=[]forcinCANDIDATES:cost=w_size*c.size_ratio+w_speed/c.speedup+w_acc*c.acc_drop scored.append((cost,c.name))scored.sort()returnscoredif__name__=="__main__":# 边缘部署场景:体积权重 0.6,速度 0.3,精度 0.1forcost,nameinrank_tradeoffs(0.6,0.3,0.1):print(f"{name}: 综合代价{cost:.3f}")1.3 压缩方法的分类压缩方法按两个维度分类:是否需要训练、是否改变模型结构。训练时压缩把压缩目标纳入损失函数,典型代表是知识蒸馏、量化感知训练(QAT)、剪枝加微调;训练后压缩直接处理已训练权重,典型代表是训练后量化(PTQ)和一次性剪枝。结构级压缩改变网络形状,数值级压缩只改变数值表示,两者的推理框架要求完全不同。类别代表方法是否需要重训是否改变结构是否需要数据训练时压缩蒸馏、QAT、剪枝加微调是是需要完整数据集训练后压缩PTQ、SparseGPT、GPTQ否部分少量校准数据混合流程蒸馏后量化、量化后剪枝部分是各阶段分开配给分类的意义在于决定压缩流程放在模型生命周期的哪个阶段。训练后压缩可以直接复用已经训练好的权重和验证结论,PTQ 在单卡上几分钟完成,SparseGPT 剪掉 50% 权重也只需约 5 分钟,代价是精度损失受权重分布限制。训练时压缩把精度损失写进优化目标,效果更好,但需要 GPU 训练预算:7B 模型在 8 卡 A100 上完成一次完整训练的成本量级在数万美元,多数团队先走训练后压缩,精度不达标再升级到训练时方案。方法间还有隐含的依赖关系。量化感知训练本身需要完整的训练管线;蒸馏后的学生模型是全新权重,需要从头走训练流程;剪枝加微调需要保留原始训练数据,数据缺失时只能退化为一次性剪枝。因此分类表同时是资源需求表,选择方法之前先核对数据可得性和算力预算,这两项往往是压缩项目的真正瓶颈。演进趋势是把更多工作移到训练后阶段。GPTQ 用 128 条校准数据完成 7B 模型的 INT4 量化,AWQ 用激活统计挑选敏感通道,SparseGPT无需微调完成 50% 稀疏化。训练后压缩成本低、可重复、可自动化,是当前压缩工具链的主线。分类边界也在变模糊,LoRA 低秩适配本质上也是一种参数压缩,只是把压缩目标从模型本身移到了适配器上,这说明分类是分析工具,不是固定标签。边界分析指出一个常见误区:把方法分类当作能力等级排序。训练时压缩并不总是优于训练后压缩,小规模模型上 PTQ 的精度损失接近QAT 的一半水平,而成本低两个数量级。正确的做法是按目标压缩比分层尝试:4 倍以内用训练后压缩,8 倍以上再引入训练时方法,每次切换都以实测数据为准。# 来源:自实现 / classify.pyMETHOD_TABLE=[{"name":"知识蒸馏","phase":"训练时","structure":True,"retrain":True},{"name":"量化感知训练","phase":"训练时","structure":False,"retrain":True},{"name":"训练后量化","phase":"训练后","structure":False,"retrain":False},{"name":"结构化剪枝加微调","phase":"训练时","structure":True,"retrain":True},{"name":"SparseGPT 剪枝","phase":"训练后","structure":True,"retrain":False},]defclassify_methods():"""按训练阶段分组,并统计各组的结构改动占比。"""groups={}forrowinMETHOD_TABLE:groups.setdefault(row["phase"],[]).append(row)returngroupsif__name__=="__main__":forphase,rowsinsorted(classify_methods().items()):names=[r["name"]forrinrows]structure=sum(1forrinrowsifr["structure"])print(f"{phase}({len(rows)}种,结构改动{structure}种):{'、'.join(names)}")2. 知识蒸馏:大模型教小模型知识蒸馏用大模型(教师)的输出分布去指导小模型(学生)的训练,让学生在不改变推理结构的前提下继承教师的能力。对 70B 到 7B 的蒸馏,学生能达到教师 90-95% 的基准分数,而推理成本按参数量比例下降约 10 倍。本节拆解蒸馏原理、黑盒与白盒两种路径,以及效果随教师学生差距变化的规律。学生模型 7B教师模型 70B温度 T 缩放KL 散度对齐交叉熵反向传播迭代训练训练完成精度不达标前向传播软标签分布