模型大小与推理速度:一个老工程师的直觉
做模型优化这些年,我见过太多人一上来就问:「怎么让模型跑得更快?」
其实这个问题背后,藏着三个关键变量:模型大小、推理速度、还有精度。这三者就像跷跷板,你压下去一头,另一头就会翘起来。
我个人习惯,拿到一个模型先看它的存储体积。你想想看,一个 500MB 的 YOLOv5 模型,跟一个 50MB 的剪枝版本,部署到 Jetson Nano 上的体验能一样吗?前者加载就要好几秒,后者几乎秒开。
核心结论:模型大小直接影响显存占用和带宽消耗。模型越大,推理时从显存搬运数据的开销就越大,延迟自然就上去了。
但这里有个坑——模型大小 ≠ 推理速度。我在项目中遇到过,一个参数量更小的模型,因为结构设计不合理(比如过多的分组卷积),实际跑起来反而比大模型还慢。所以,光看文件大小是不够的。
参数量与计算量:FLOPs 到底在算什么?
先说参数量(Params)。说白了,就是模型里所有可学习参数的总数。每个卷积核的权重、每个 BN 层的 gamma 和 beta,都算进去。
举个例子,一个标准的 3x3 卷积,输入通道 64,输出通道 128:
参数量 = 3 × 3 × 64 × 128 + 128(偏置) = 73,856
嗯,就这么简单。但要注意,参数量只决定模型能「记住」多少信息,并不直接决定它跑得快不快。
真正影响推理速度的,是计算量(FLOPs)——浮点运算次数。还是上面那个卷积,它处理一张 224x224 的图:
FLOPs = 2 × 3 × 3 × 64 × 128 × 224 × 224 ≈ 17.6 G
为什么乘 2?因为一次乘法和一次加法算两次运算。这个细节,我刚开始也经常搞混。
我的经验:参数量决定「存储成本」,FLOPs 决定「计算成本」。剪枝主要砍参数量,量化主要降 FLOPs 的位宽开销。两者配合,效果最好。
模型冗余的本质:为什么能剪掉一半还不掉点?
你可能会问:好好的模型,为什么会有冗余?
其实,深度学习模型天生就是过参数化的。我打个比方,你让 10 个人去搬一张桌子,其实 5 个人就够了,剩下 5 个人在「摸鱼」。模型里的很多神经元,权重接近零,或者输出高度相关,它们对最终结果贡献很小。
冗余的来源主要有三种:
- 权重冗余:大量权重值接近 0,对输出影响微乎其微
- 通道冗余:某些特征图之间高度相似,保留一个就够了
- 结构冗余:某些层或分支在特定任务上是多余的
我记得有一次,对一个 YOLOv5s 做通道剪枝,剪掉 40% 的通道后,mAP 只掉了 0.3%。我当时还不太信,反复验证了好几遍。后来想通了——模型在训练时,为了拟合数据,会「过度学习」很多噪声模式。剪枝相当于帮它做了一次「断舍离」。
避坑指南:我曾经以为冗余越多越好剪,结果在一个轻量级模型(MobileNetV3)上翻车了。轻量模型本身冗余就少,强行剪枝会导致精度断崖式下跌。所以,大模型适合剪枝,小模型更适合量化。
一张表看懂三者的关系
| 指标 | 定义 | 对推理速度的影响 | 优化手段 |
|---|---|---|---|
| 模型大小 | 存储体积(MB/GB) | 影响加载时间和显存占用 | 量化、权重共享 |
| 参数量 | 可学习参数总数 | 间接影响(通过 FLOPs) | 结构剪枝、低秩分解 |
| FLOPs | 浮点运算次数 | 直接影响延迟 | 通道剪枝、稀疏化 |
你看,这三者虽然相关,但优化时得对症下药。我见过有人花大力气把参数量砍了一半,结果 FLOPs 没怎么变,推理速度纹丝不动——这就是没搞清楚目标。
我的优化原则
做了几年模型优化,我总结了几条原则,分享给你:
- 先分析,再动手:用 profile 工具跑一遍,看瓶颈在哪。是计算密集还是访存密集?
- 剪枝和量化要分步走:先剪枝再量化,顺序别搞反。量化后的模型再做剪枝,精度很难恢复。
- 保留关键通道:剪枝时别只看权重大小,还要看通道对最终输出的贡献。我习惯用 BN 层的 gamma 值作为重要性指标。
- 验证要彻底:剪完一个层,马上跑一遍验证集。别等到全剪完了才发现精度崩了。
最后说一句:模型优化不是玄学,是工程。你理解得越深,踩的坑就越少。下一章,我会带你手撸一个简单的剪枝工具,到时候你就知道这些概念怎么落地了。