模型量化基础:量化的定义与动机、浮点与定点表示、精度与性能权衡
各位同学,咱们今天聊聊模型量化。说实话,这可能是整个端侧AI ISP部署里,最“值钱”的一环。为什么这么说?因为量化直接决定了你的模型能不能在手机、摄像头、IoT设备上跑起来,以及跑得有多快。
我刚开始做AI芯片部署那会儿,踩过一个坑。当时有个降噪模型,在GPU上跑得飞起,PSNR指标漂亮得很。结果一放到手机芯片上,帧率直接掉到个位数。后来一查,模型参数全是FP32,芯片的NPU根本不支持。那怎么办?只能量化。从那以后,我养成了一个习惯:做任何端侧部署,第一件事就是看量化方案。
核心观点:量化不是“不得已而为之”,而是端侧AI ISP的“必由之路”。它用精度换效率,但好的量化方案能把精度损失降到几乎不可感知。
1. 量化的定义:到底在做什么?
量化,说白了就是把模型里那些“高精度”的数字,用“低精度”的数字来表示。比如,原本一个权重是3.14159265(FP32),量化之后可能就变成了3.14(INT8)。
你想想看,一个FP32的数值占32个bit,一个INT8只占8个bit。内存占用直接降到1/4,计算速度却能翻好几倍。这就是量化的核心动机——用更少的比特,做更多的事。
我个人习惯把量化分成两类:
- 权重量化:只量化模型的权重参数。模型体积变小,但推理时中间结果还是浮点。
- 全量化:权重和激活值都量化。这才是真正的“端侧友好”,计算全部走定点。
嗯,这里要注意:全量化难度更大,但收益也最大。我在项目中遇到过,有些ISP模型只做权重量化,推理速度提升有限,一上全量化,帧率直接翻倍。
2. 浮点与定点表示:两种世界观
咱们得先搞清楚,计算机里数字是怎么存的。这直接决定了量化怎么做。
浮点表示(FP32 / FP16)
浮点数,就是带小数点的数,比如3.14、-0.001。FP32用1位符号位、8位指数位、23位尾数位来表示。它能表示的范围极大,精度也高。
但问题来了:浮点运算电路面积大、功耗高。在端侧芯片上,浮点运算单元(FPU)是奢侈品。你想想看,一个手机芯片里,NPU的面积就那么点,全做浮点,那其他模块还放不放了?
定点表示(INT8 / INT4)
定点数,就是小数点位置固定的数。比如,我们约定小数点后面有2位,那3.14就存成314,再除以100。定点运算只需要整数加减乘除,电路简单、速度快、功耗低。
我举个例子,你马上就能明白:
// 浮点乘法
float a = 3.14;
float b = 2.71;
float c = a * b; // 需要浮点乘法器
// 定点乘法(假设Q8.8格式,即8位整数+8位小数)
int16_t a_q = (int16_t)(3.14 * 256); // 804
int16_t b_q = (int16_t)(2.71 * 256); // 694
int32_t c_q = (int32_t)a_q * b_q; // 557,976
int16_t c_q_scaled = c_q >> 8; // 2179
float c = c_q_scaled / 256.0f; // 8.51(近似值)
看到了吗?定点乘法就是整数乘法加移位。在硬件上,这比浮点乘法快得多。
个人经验:我建议你在做量化方案时,优先考虑对称量化(symmetric quantization)。它把浮点范围映射到[-127, 127](INT8),零点就是0。这样计算时少一次减法,硬件实现更简单。我在一个去噪项目里试过,对称量化比非对称量化快约15%。
3. 量化带来的精度与性能权衡
这是量化里最核心的问题。没有免费的午餐,量化一定会损失精度。但关键是:损失多少?能不能接受?
我画了一张图,帮你理解这个权衡:
从这张图你能看到,量化不是非黑即白的选择。它是一道光谱,从FP32到INT8,甚至到INT4、INT2,每一步都有不同的精度和性能表现。
精度损失从哪来?
量化本质上是“有损压缩”。你把一个连续的值域映射到离散的整数点上,必然会有信息丢失。具体来说:
- 截断误差:超出量化范围的值被直接截断。比如,INT8的范围是[-128, 127],如果某个权重是200,那它就被截成127。
- 舍入误差:量化步长(scale)决定了精度。步长越大,舍入误差越大。比如,步长为0.1时,3.14被量化为31(3.1),误差0.04;步长为0.5时,3.14被量化为6(3.0),误差0.14。
避坑指南:我曾经在一个HDR融合模型上做量化,结果发现暗部区域出现了明显的色块。查了半天,原来是激活值的分布太宽,量化步长太大,导致暗部细节被“抹平”了。后来我用了逐通道量化(per-channel quantization),每个通道单独算scale,问题就解决了。记住:分布不均匀的特征图,一定要用逐通道量化。
性能提升有多大?
咱们用数据说话。假设一个ISP模型,在某个端侧NPU上:
| 量化方案 | 模型体积 | 推理速度 | PSNR损失 |
|---|---|---|---|
| FP32(基线) | 100 MB | 30 FPS | 0 dB |
| FP16 | 50 MB | 45 FPS | ~0.05 dB |
| INT8(全量化) | 25 MB | 90 FPS | ~0.3 dB |
| INT4(混合精度) | 12.5 MB | 120 FPS | ~0.8 dB |
你看,从FP32到INT8,模型体积缩到1/4,速度提升3倍,PSNR只掉了0.3dB。对于大多数ISP应用来说,这个损失肉眼几乎看不出来。这就是量化的魅力——用几乎不可感知的精度损失,换来巨大的性能提升。
4. 量化方法的选择:PTQ vs QAT
说到具体怎么做量化,主要有两条路:
- 训练后量化(PTQ, Post-Training Quantization):模型训练完,直接拿权重和激活值的统计信息来算量化参数。简单、快速,但精度损失可能较大。
- 量化感知训练(QAT, Quantization-Aware Training):在训练过程中模拟量化误差,让模型自己去适应。精度更高,但需要重新训练,成本也高。
我个人习惯是:先做PTQ试试水。如果精度损失在可接受范围内,那就直接用PTQ,省时省力。如果损失太大,再上QAT。我在一个夜景增强模型上就是这么干的——PTQ掉了0.6dB,QAT只掉了0.15dB,但训练时间多了3天。值不值?看项目需求。
小技巧:做PTQ时,校准数据集(calibration dataset)的选择很关键。我建议你用100~500张有代表性的图像,覆盖各种光照条件和场景。千万别只用实验室的测试图,否则量化后的模型在真实场景下会“翻车”。
5. 量化对ISP模型的特殊挑战
ISP模型和普通的分类、检测模型不太一样。它处理的是图像信号,对精度极其敏感。我总结了几点:
- 低比特量化容易丢细节:特别是暗部区域的纹理和颜色。INT4量化时,暗部细节可能直接被“抹掉”。
- 激活值分布不均匀:ISP模型的中间特征图,往往有大量接近0的值和少量很大的值。这种“长尾分布”对量化很不友好。
- 多任务联合量化:一个ISP模型可能同时做去噪、HDR、色彩校正。每个任务的量化敏感度不同,需要分别调优。
嗯,这里要特别提醒:千万别把量化当成一个“一键搞定”的步骤。它需要你深入理解模型的结构、数据的分布、硬件的特性。我见过太多人,量化完模型直接部署,结果图像质量惨不忍睹。然后回过头来骂量化“垃圾”。其实不是量化垃圾,是你没用好。
好了,这一章的内容就到这。量化是门手艺活,多练、多试、多总结,你也能成为高手。