模型量化的目的是通过将浮点运算转换为定点运算,以减少模型大小、内存和存储需求,同时加快推理速度,降低计算功耗,使得模型在低算力设备上运行更加高效,特别适用于嵌入式设备或移动端场景。
不同数据类型(FP32、BF16、FP16、INT8)在动态范围和精度上的差异。FP32具有最广的动态范围,同时精度最高。图中两个相邻值之间的距离较小,意味着它能够在很大范围内精确地表示数值,是深度学习模型的常见选择,尤其在精度要求高的场景中。
BF16保持了与FP32类似的动态范围,但牺牲了一部分精度。虽然它能够处理与FP32相同范围的数值,但相邻值之间的距离较大,因此精度较低。这种格式在需要节省内存的情况下仍然能提供足够大的动态范围,常用于加速模型训练而不显著影响性能。
FP16的动态范围比BF16略小,数值范围从 -65504 到 65504,精度也比FP32低,相邻值之间的距离比FP32和BF16更大。FP16常用于在精度损失可接受的情况下减少模型的计算和存储资源。
INT8是一种8位整数类型,具有非常有限的动态范围。由于它只能表示离散的整数值,其动态范围和精度都明显低于浮点数类型。但由于其低存储需求和高计算效率,INT8非常适合于资源受限设备的模型推理,特别是在内存和功耗有限的场景中。
把普通图片用8位颜色表示:
实际操作
以下是一段简单的代码表示张量 x 从 fp32 量化到 int8 整型,再反量化回 fp32 的示例:
x->x{int}->x_hat 的过程的一个示例如下:
量化前 x:
量化后 x_hat:
工业界的应用
大型语言模型的量化也能让模型“瘦身”,让它能更高效地运行。原本这些模型用的是很高精度的数据类型来保存参数,这样虽然精确,但代价就是占用大量内存,而且运算也非常耗费资源。一台普通的设备根本跑不动这样的庞然大物,用量化技术把这些参数从高精度的格式变成低精度的格式,比如把32位的浮点数变成8位的整数,这样不仅减少了模型的大小,也加快了计算速度。特别是在手机或者嵌入式设备上,量化能让模型跑得又快又省电。量化就成了大型语言模型落地应用的重要一步,让它们不再只是实验室里的庞然大物,而是可以实际用起来,服务更多场景。
GPTQ 是最早被工程化部署所接受的量化方案,W8A16 或 W4A16 的量化效果在多数场景中都有与原模型较为接近的表现,而且其量化过程非常快。
参考文献
- https://tech.dewu.com/article?id=112
- https://www.datawhale.cn/learn/content/68/963
- https://blog.csdn.net/penriver/article/details/136411485
- https://piprogramming.org/articles/Simple-and-Foolproof-ways-to-Shrink-Compress-and-Accelerate-your-Deep-Learning-Neural-Network-etc-Artificial-Intelligence-Models-0000000015.html
- https://newsletter.maartengrootendorst.com/p/a-visual-guide-to-quantization
- https://xie.infoq.cn/article/01daa1c8fdd58f2d07af448ab?utm_campaign=geektime_search&utm_content=geektime_search&utm_medium=geektime_search&utm_source=geektime_search&utm_term=geektime_search