3、量化基础回顾:对称量化与非对称量化、量化粒度(per-tensor vs per-channel)
好,咱们进入第三章。说实话,量化这个主题,很多同学一听就觉得头大。我当年刚接触的时候也一样,觉得不就是把 FP32 变成 INT8 嘛,有什么难的?结果第一次在低功耗芯片上跑模型,精度直接崩了……嗯,从那以后,我再也不敢小看量化了。
这一节,咱们把量化最核心的两个概念讲透:对称 vs 非对称,以及量化粒度。这两个东西,说白了就是决定你量化后模型精度和性能的“命门”。
3.1 量化到底在做什么?
先问个问题:为什么我们要量化?
因为低功耗场景下,芯片的算力和带宽都有限。FP32 的模型跑起来,功耗高、速度慢。量化成 INT8,计算量能降 4 倍,模型体积能缩 4 倍,功耗更是直线下降。代价呢?精度损失。我们的任务就是让这个损失尽可能小。
量化的数学本质很简单:
Q = round( (R - zero_point) / scale )
其中 R 是原始浮点数,Q 是量化后的整数,scale 是缩放因子,zero_point 是零点偏移。就这么一个公式,但不同的选择,结果天差地别。
3.2 对称量化 vs 非对称量化
对称量化
对称量化,顾名思义,就是量化后的整数范围关于 0 对称。比如 INT8 的范围是 [-128, 127],对称量化会让浮点数的 0 对应整数的 0。
公式简化成:
Q = round( R / scale )
这里 zero_point = 0。好处是什么?计算简单,硬件实现快。我在项目中遇到过,很多 NPU 和 DSP 对对称量化的支持特别好,几乎零开销。
但有个坑:如果你的数据分布不是对称的,比如全是正数,那对称量化会浪费一半的表示范围。举个例子,ReLU 的输出全是非负的,你用对称量化,负半轴的 [-128, -1] 全浪费了,精度自然受影响。
非对称量化
非对称量化允许 zero_point 不为 0。这样,浮点数的 0 可以映射到整数范围内的任意位置。公式就是最前面那个:
Q = round( (R - zero_point) / scale )
好处很明显:能充分利用整个整数表示范围。对于 ReLU 这种输出全为正的激活函数,非对称量化可以把 [0, max] 映射到 [0, 255],一个比特都不浪费。
代价呢?计算稍微复杂一点,硬件上需要多一个减法操作。不过现在大部分芯片都支持,性能影响不大。
| 对比项 | 对称量化 | 非对称量化 |
|---|---|---|
| zero_point | 固定为 0 | 可调节 |
| 计算复杂度 | 低 | 中 |
| 硬件友好度 | 高 | 中 |
| 数据分布适配 | 仅适合对称分布 | 适合任意分布 |
| 典型应用 | 权重、LayerNorm | 激活值、偏置 |
我个人习惯是:权重用对称量化,激活用非对称量化。为什么?权重分布通常比较对称,而且对称量化在硬件上更快。激活值分布千奇百怪,非对称量化更灵活。
3.3 量化粒度:per-tensor vs per-channel
量化粒度,说白了就是“多少个参数共享同一个 scale 和 zero_point”。
Per-tensor 量化
整个张量(比如一个卷积层的权重)只用一个 scale 和一个 zero_point。实现最简单,计算量最小。但问题也很明显:如果张量内部不同通道的数值范围差异很大,那精度损失会很大。
举个例子,一个卷积层有 64 个输出通道,其中 63 个通道的权重范围是 [-1, 1],但第 64 个通道的范围是 [-10, 10]。per-tensor 量化会取全局最大值 10,导致前 63 个通道的量化精度严重不足。
Per-channel 量化
每个通道独立计算 scale 和 zero_point。比如一个卷积层有 64 个输出通道,那就需要 64 组量化参数。精度更高,但计算量和存储量也更大。
我在项目中遇到过,per-channel 量化通常能让精度提升 0.5~1 个点,尤其是在深度可分离卷积中。MobileNet 系列模型,如果不做 per-channel 量化,精度掉得惨不忍睹。
| 对比项 | Per-tensor | Per-channel |
|---|---|---|
| 量化参数数量 | 1 组 | 通道数 组 |
| 计算开销 | 低 | 中 |
| 存储开销 | 低 | 中 |
| 精度 | 一般 | 高 |
| 适用场景 | 小模型、资源极度受限 | 大模型、精度敏感场景 |
你想想看,低功耗场景下,我们通常选哪个?我个人建议:权重用 per-channel,激活用 per-tensor。因为激活值的分布通常比较稳定,per-tensor 就够了。而权重的分布差异大,per-channel 能保住精度。
3.4 知识体系总览
为了让你更直观地理解,我画了一张图。这张图把量化最核心的两个维度——量化方法和量化粒度——组合起来,形成了四种常见策略。你在实际项目中,可以根据芯片能力和精度要求,在这四个象限里选一个。
这张图你看懂了吗?横轴是量化粒度,纵轴是量化方法。左下角(对称+per-tensor)计算最快但精度最低,右上角(非对称+per-channel)精度最高但计算最复杂。低功耗场景下,我们通常选左下或左上,具体看芯片能力。
3.5 实战建议
好了,理论讲完了,说点实际的。如果你现在要量化一个 SwiGLU 激活的模型,我的建议是:
- 权重用对称 + per-channel。SwiGLU 的权重分布通常比较对称,per-channel 能保住精度。
- 激活用非对称 + per-tensor。SwiGLU 的输出是门控机制的结果,分布偏正,非对称更合适。per-tensor 够用,别浪费资源。
- 先跑一遍校准集。看看每层的数值范围,如果某层分布特别异常,再单独调整。
嗯,量化基础就讲到这里。记住,没有银弹。不同的模型、不同的芯片,最佳策略都不一样。多试、多调,才能找到最适合你的方案。
公众号:蓝海资料掘金营,微信deep3321