2. 模型量化基础

量化,说白了就是把模型从高精度“压缩”到低精度。

我刚开始接触量化时,总觉得这玩意儿有点玄乎。明明FP32跑得好好的,干嘛非要折腾成INT8?后来在部署一个BERT模型到边缘设备时,内存直接爆了,我才意识到——不量化,很多场景根本跑不起来。

今天咱们就聊聊量化的核心原理。FP16、INT8、INT4这些精度到底怎么选?对称量化和非对称量化有啥区别?量化误差又从哪来?

一句话总结:量化就是用更少的比特数表示浮点数,换来更快的推理速度和更小的模型体积。

1. 量化到底在做什么?

先看一个最简单的例子。

假设我有一个权重值:3.1415926。在FP32里,它占4个字节。如果我要把它存成INT8,就只能用0~255之间的整数来表示。那怎么办?

做个映射呗。

比如我把[-10.0, 10.0]这个范围映射到[0, 255]。那么3.1415926对应的整数就是:

scale = (10.0 - (-10.0)) / 255 = 0.0784
zero_point = 0 - (-10.0 / 0.0784) ≈ 128
quantized_value = round(3.1415926 / 0.0784 + 128) = round(168.1) = 168

推理时再反量化回来:

dequantized = (168 - 128) * 0.0784 = 3.136

你看,3.1416变成了3.136。误差就这么产生了。

我的经验:量化误差不可避免,但我们可以控制它。关键就在于——选对量化范围,选对量化方式。

2. FP16、INT8、INT4,到底差在哪?

这三种精度,我按使用频率排个序:

精度类型 比特数 表示范围 精度损失 加速比(约)
FP16 16 ±65504 几乎无感 1.5x - 2x
INT8 8 0~255 或 -128~127 可接受 2x - 4x
INT4 4 0~15 或 -8~7 明显 4x - 8x

FP16——我习惯叫它“半精度”。说白了就是FP32砍掉一半的比特。指数位从8位减到5位,尾数位从23位减到10位。效果呢?大部分模型精度几乎不掉。我在项目中用FP16跑过BERT、GPT-2,准确率差异在0.1%以内。适合GPU训练和推理。

INT8——这是目前工业界的主流选择。8比特整数,范围有限,但配合好的量化策略,精度损失可以控制在1%以内。我去年部署一个图像分类模型,INT8量化后准确率从92.3%掉到91.8%,完全能接受。但推理速度翻了3倍。

INT4——这个就有点“激进”了。4比特,只有16个取值。说实话,我一般只在极端场景用——比如内存实在不够,或者模型本身很大(像LLaMA-65B这种)。精度损失通常在3%~5%,需要配合量化感知训练才能稳住。

注意:INT4量化后,模型精度可能会“崩”。我曾经在一个NLP任务上试过,直接掉7个点。后来加了量化感知训练才拉回来。所以——先评估,再动手。

3. 对称量化 vs 非对称量化

这两个概念,我当年学的时候绕了半天。其实很简单。

对称量化——量化范围关于0对称。比如[-128, 127]映射到[-1.0, 1.0]。0在浮点域和整数域都是0。

公式:

scale = max(|x_min|, |x_max|) / 127
quantized = round(x / scale)

好处是计算简单,硬件友好。坏处是——如果数据分布不对称,比如全是正数,那负数那半边就浪费了。

非对称量化——量化范围可以不对称。比如[0, 255]映射到[0.2, 0.8]。0在浮点域和整数域不一定对应。

公式:

scale = (x_max - x_min) / 255
zero_point = round(-x_min / scale)
quantized = round(x / scale + zero_point)

好处是能充分利用量化范围。坏处是计算多了一步zero_point的偏移,硬件实现稍复杂。

对比项 对称量化 非对称量化
适用场景 权重(通常对称分布) 激活值(通常不对称)
硬件友好度 高 中
精度损失 数据不对称时较大 更小
实现复杂度 低 中

我的习惯:权重用对称量化,激活值用非对称量化。这是业界最常用的组合。你想想看,权重经过训练后通常接近正态分布,对称量化正合适。而激活值经过ReLU后全是非负的,非对称量化能更好地利用量化范围。

4. 量化误差从哪来?

量化误差,说白了就是“信息丢失”。我总结了三个主要来源:

  1. 截断误差——超出量化范围的值被强行截断。比如INT8范围是[-128, 127],如果有个权重是200,那就只能变成127。这损失最大。
  2. 舍入误差——浮点数映射到整数时的四舍五入。比如3.1416变成3,0.1416就丢了。单个误差小,但累积起来不可忽视。
  3. 粒度误差——量化粒度越粗,误差越大。比如整个张量用一个scale,和每个通道用一个scale,后者误差小得多。

我曾经在一个项目中,因为量化粒度太粗(整个模型用一个scale),导致精度掉了8个点。后来改成per-channel量化,误差降到1.5%。

避坑指南:量化误差分析时,别只看最终精度。我建议你同时看每个层的输出差异——用余弦相似度或者信噪比(SNR)。这样能快速定位“问题层”,然后针对性地调整量化策略。

5. 知识体系总览

下面这张图,是我自己整理的量化知识体系。你看一眼,心里就有谱了。

模型量化知识体系 模型量化 量化精度类型 FP16(半精度) INT8(主流) INT4(激进) 量化方式 对称量化 范围关于0对称,硬件友好 非对称量化 范围可偏移,精度更高 量化误差分析 截断误差 舍入误差 粒度误差

这张图把量化拆成了三个维度:精度类型、量化方式、误差分析。你顺着这个结构学,思路会清晰很多。

6. 一点个人感悟

量化这件事,说难不难,说简单也不简单。我见过有人随便一量化就上线,结果模型崩了。也见过有人花两周调量化参数,最后精度几乎无损。

关键就三点:

  • 选对精度——FP16保底,INT8主流,INT4慎用
  • 选对方式——权重对称,激活非对称
  • 分析误差——别只看最终精度,要看每层输出

嗯,今天就聊到这儿。量化是个大话题,后面咱们还会深入聊量化感知训练、混合精度量化这些实战技巧。

一句话记住:量化不是玄学,是工程。理解原理,动手实践,你也能成为量化高手。