欢迎光临
我们一直在努力

量化基础面试题:均匀量化与非均匀量化的区别,如何计算 Scale 与 Zero Point?

模型量化是将模型权重和激活值从高精度浮点数(如FP32)转换为低精度定点整数(如INT8)的过程,以减少模型大小和计算延迟。在面试中,理解均匀量化(Uniform Quantization)的基础知识,特别是如何计算 Scale ($S$) 和 Zero Point ($Z$) 是必备技能。

1. 均匀量化 (Uniform Quantization)

均匀量化是最主流的量化方式,它使用一个固定的比例因子 Scale ($S$) 和一个零点 Zero Point ($Z$) 来在浮点数 $r$(Real Value)和定点整数 $q$(Quantized Value)之间建立线性映射关系。

核心思想是:浮点数的范围 $[r_{min}, r_{max}]$ 线性地映射到整数的范围 $[q_{min}, q_{max}]$。

关系公式:
$$r \approx S(q – Z)$$

其中:
* $r$ 是原始浮点数。
* $q$ 是量化后的整数。
* $S$ 是比例因子(Scale),代表每个整数步长对应的浮点数值。
* $Z$ 是零点(Zero Point),表示浮点数 $0.0$ 映射到的整数值。

2. 如何计算 Scale ($S$) 和 Zero Point ($Z$)

计算 $S$ 和 $Z$ 的目标是确保浮点数的最小值 $r_{min}$ 映射到整数的最小值 $q_{min}$,以及 $r_{max}$ 映射到 $q_{max}$。我们以 8-bit 无符号量化($q_{min}=0, q_{max}=255$)为例进行推导。

步骤 1: 计算 Scale ($S$)

Scale $S$ 代表了量化范围的总长度比上整数范围的总长度:

$$S = \frac{r_{max} – r_{min}}{q_{max} – q_{min}}$$

步骤 2: 计算 Zero Point ($Z$)

Zero Point $Z$ 确保浮点数 $r=0$ 映射到的整数 $q$ 是 $Z$。我们可以利用 $r_{min}$ 和 $q_{min}$ 的关系来求解 $Z$。

从公式 $r = S(q – Z)$ 可得 $Z = q – r/S$。

将端点值代入:$r_{min} = S(q_{min} – Z)$,得到:

$$Z = q_{min} – \frac{r_{min}}{S}$$

由于 $Z$ 必须是整数,且必须落在整数范围 $[q_{min}, q_{max}]$ 内,我们需要进行四舍五入和截断(Clamping):

$$Z = \text{max}(q_{min}, \text{min}(q_{max}, \text{round}(q_{min} – \frac{r_{min}}{S})))$$

Python 示例:计算 S 和 Z

以下代码展示了如何使用 NumPy 计算 S 和 Z,并进行量化和反量化:

import numpy as np

def calculate_scale_and_zero_point(r_min, r_max, q_min, q_max):
    # 1. 计算 Scale
    S = (r_max - r_min) / (q_max - q_min)

    # 2. 计算未截断的 Zero Point (基于 r_min)
    Z_raw = q_min - (r_min / S)

    # 3. 四舍五入到最近的整数
    Z = int(np.round(Z_raw))

    # 4. 截断 Zero Point 到合法范围 [q_min, q_max]
    Z = np.clip(Z, q_min, q_max)

    return S, Z

# 8-bit Unsigned Quantization Example (q_min=0, q_max=255)
r_min = -1.5
r_max = 2.5
q_min = 0
q_max = 255

S, Z = calculate_scale_and_zero_point(r_min, r_max, q_min, q_max)
print(f"Scale (S): {S:.6f}")
print(f"Zero Point (Z): {Z}")

# 验证量化与反量化
def quantize(r, S, Z):
    q = np.round(r / S) + Z
    return np.clip(q, q_min, q_max).astype(np.int32)

def dequantize(q, S, Z):
    return S * (q - Z)

r_value = 0.5
q_value = quantize(r_value, S, Z)
r_reconstructed = dequantize(q_value, S, Z)

print(f"Original r: {r_value}")
print(f"Quantized q: {q_value}")
print(f"Reconstructed r: {r_reconstructed:.6f}")
# 输出: Scale (S): 0.015686, Zero Point (Z): 96

3. 均匀量化与非均匀量化的区别

特性 均匀量化 (Uniform Quantization) 非均匀量化 (Non-Uniform Quantization)
映射方式 线性映射 非线性映射 (通常基于对数或聚类)
量化步长 恒定 ($S$) 不恒定,步长随数值大小变化
计算复杂度 低,硬件友好 高,需要查表或复杂计算
零点 必须精确映射浮点数 0 通常不保证 0 的精确映射
适用场景 绝大多数主流硬件加速器和深度学习框架 (如TFLite, ONNX Runtime) 需要更高精度或对权重分布有特殊要求的研究场景 (如VQ, Log Quantization)

总结: 均匀量化由于其硬件实现的简易性,是目前工业界端侧部署模型量化的标准选择。非均匀量化理论上可以提供更好的精度,尤其对于那些服从长尾分布(heavy-tailed distribution)的权重,但实现和部署难度更高。

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » 量化基础面试题:均匀量化与非均匀量化的区别,如何计算 Scale 与 Zero Point?
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址