深夜调一个要跑在移动端的小模型,风扇声比编译日志还密。卡住的不是训练,而是部署:内存放不下、带宽吃紧、延迟忽高忽低。这时候话题自然会转到模型压缩——听起来像把文件变小,实际做的却是决定哪些能力可以被放弃。
先把“压什么”说清楚
剪枝去掉贡献小的连接或整块结构,量化把高精度数字换成更省的表示,蒸馏则让小模型去拟合大模型的输出分布。三条路的动作不同,共同点是一致的:用“少一点”换“跑得动一点”。
但压在哪一层,结果差别很大。压权重,改动的是参数本身;压激活,动的是运行时数据;压结构,则是改变网络形状。前两者常常可以回退,第三个一旦落地,想恢复就得重新训练。所以很多团队的真实做法不是一上来就狠压,而是先压最容易回退的部分,看误差能不能被接受,再决定下一步。
压缩比的诱惑,以及它藏起来的代价
把位数降下去,模型文件立刻瘦一圈,推理也快。问题在于,评测集上的平均分数往往掉得不明显,真正出问题的是边角情况:少见的输入、长尾的表达、极端长度。平均值掩盖了这些地方,用户却总能碰上。
这也是模型压缩最容易被误读的地方。它看起来是个数值优化问题,实际上更像是产品问题——你必须先回答,哪些错误可以接受,哪些不能。一个离线批处理任务可以容忍几秒延迟,换成实时对话就不行;反过来,对话场景里偶尔一次答偏,可能比慢半拍更难解释。
- 约束先定:目标设备的内存上限、可接受的延迟区间、功耗预算。
- 策略再选:在约束之下挑压缩手段,而不是先选手段再找场景。
- 验证要真:拿真实流量回放,别只看离线指标那一行数字。
一个容易被忽略的环节
压缩之后,模型的行为会变,但变在哪里往往没人说得清。有经验的团队会保留一份压缩前后的对照输入,专门盯住那些“分数没掉、结果却不同”的样本。这类抽样不产生漂亮的报告,却能提前暴露问题。
还有一件事值得提:压缩不是一次性动作。数据分布会漂移,设备会换代,今天合适的压缩方案过几个月可能就不合适了。把压缩流程做成可重跑的,比一次性压到极限更实用。
回到那台嗡嗡响的机器。模型压缩真正解决的从来不是“能不能塞进去”,而是“塞进去之后,它还剩下多少可信的部分”。这个答案没法靠一个压缩比给出来,只能靠一次次对照去逼近。