22 对称量化与非对称量化——INT8的两种尺度计算方式

发布时间:2026/7/29 15:02:17
22 对称量化与非对称量化——INT8的两种尺度计算方式 对称量化与非对称量化——INT8的两种尺度计算方式一句话总结对称量化让 0 永远映射到 0反量化简单非对称量化利用全部 256 个值但需要额外的 zero_point 偏移。前言在 INT8 量化中如何将 FP32 的浮点数映射到 [-128, 127] 的整数范围核心就是确定scale量化尺度。而 scale 的计算方式有两种主流方案对称量化和非对称量化。两者的核心区别在于——0 是否映射到 0以及是否利用全部的 256 个整数值。本文从公式推导、手算示例、代码演示三个维度详细拆解这两种量化方式并给出实际部署中的选择建议。提示发布时请在 CSDN 编辑器中点击「插入目录」自动生成目录本文手动目录仅供参考。前置知识INT8 能表示多少个数INT8 有符号: [-128, -127, ..., 0, ..., 126, 127] → 256 个值 INT8 无符号: [0, 1, ..., 254, 255] → 256 个值 通常量化使用有符号 INT8范围 [-128, 127]。第一部分对称量化公式scale max(|data|) / 127 量化: q round(x / scale) 反量化: x q × scale核心特征0 映射到 0不用加偏移量。手算示例数据: [3.0, 2.8, 0.1, 0.05, -0.5, -1.2] max_abs max(|3.0|, |2.8|, ..., |-1.2|) 3.0 scale 3.0 / 127 ≈ 0.02362 量化: 3.0 / 0.02362 127.0 → round(127.0) 127 2.8 / 0.02362 118.5 → round(118.5) 119 0.0 / 0.02362 0.0 → round(0.0) 0 ← 0 永远映射到 0 -1.2 / 0.02362 -50.8 → round(-50.8) -51 反量化: 127 × 0.02362 3.0 119 × 0.02362 2.81 0 × 0.02362 0.0 -51 × 0.02362 -1.2特点优点: ✓ 0 → 0反量化只需 x q × scale简单 ✓ 卷积计算中zero_point 为 0计算量最小 ✓ 权重天然对称分布均值约 0最适合 缺点: ✗ 浪费了 [-128] 这个值负方向只有 127 个值正方向有 128 个 ✗ 如果数据不是对称分布如全是正数一半范围被浪费第二部分非对称量化公式scale (max - min) / 255 zero_point round(-min / scale) ← 这就是非对称的关键 量化: q round(x / scale) zero_point 反量化: x (q - zero_point) × scale核心特征用全部 256 个值0 不一定映射到 0。手算示例数据: [3.0, 2.8, 0.1, 0.05, -0.5, -1.2] min -1.2, max 3.0 scale (3.0 - (-1.2)) / 255 4.2 / 255 ≈ 0.01647 zero_point round(-(-1.2) / 0.01647) round(72.86) 73 量化: 3.0 / 0.01647 73 182.1 73 255.1 → round(255.1) 255 2.8 / 0.01647 73 170.0 73 243.0 → round(243.0) 243 0.0 / 0.01647 73 0.0 73 73.0 → round(73.0) 73 ← 0 映射到 73! -1.2 / 0.01647 73 -72.9 73 0.1 → round(0.1) 0 反量化: (255 - 73) × 0.01647 182 × 0.01647 3.00 (243 - 73) × 0.01647 170 × 0.01647 2.80 (73 - 73) × 0.01647 0 × 0.01647 0.00 (0 - 73) × 0.01647 -73 × 0.01647 -1.20特点优点: ✓ 利用全部 256 个值精度更高 ✓ 适合数据分布不对称的情况如 ReLU 输出的全是正数 缺点: ✗ 反量化需要 x (q - zp) × scale多一次减法 ✗ 卷积计算需要额外处理 zero_point 项更复杂 ✗ 0 不映射到 0稀疏计算如 ReLU 的 0 值会变复杂第三部分两者对比对称量化非对称量化公式max_abs / 127(max-min) / 255量化范围[-127, 127][0, 255]偏移后0 映射到0zero_point不一定是 0反量化x q × scalex (q - zp) × scale计算量低高多一次 zp 减法表示能力254 个有效值256 个有效值适用数据对称分布权重非对称分布ReLU 激活第四部分代码演示importnumpyasnp# # 对称量化# defsymmetric_quantize(x): 对称量化scale max(|x|) / 127 0 → 0反量化只需 x q × scale max_absnp.max(np.abs(x))scalemax_abs/127qnp.round(x/scale)x_hatq*scalereturnq,scale,x_hat# # 非对称量化# defasymmetric_quantize(x): 非对称量化scale (max - min) / 255 0 不一定映射到 0反量化需要 x (q - zp) × scale x_minnp.min(x)x_maxnp.max(x)scale(x_max-x_min)/255zero_pointnp.round(-x_min/scale)qnp.round(x/scale)zero_point x_hat(q-zero_point)*scalereturnq,scale,zero_point,x_hat# # 测试数据# # 场景1对称分布的数据像权重data_symmetricnp.array([0.5,-0.3,0.1,-0.8,0.0,0.6,-0.2])# 场景2非对称分布的数据像 ReLU 后的激活值data_asymmetricnp.array([3.0,2.8,0.1,0.05,0.0,0.0,0.0])# # 场景1对称数据# print(*60)print(场景1对称分布的数据均值≈0正负各半)print(*60)print(f原始数据:{data_symmetric})q_sym,s_sym,r_symsymmetric_quantize(data_symmetric)q_asym,s_asym,zp_asym,r_asymasymmetric_quantize(data_symmetric)print(f\n对称量化:)print(f scale max(|x|)/127 {np.max(np.abs(data_symmetric)):.4f}/ 127 {s_sym:.6f})print(f q {q_sym})print(f 反量化 {r_sym})print(f 误差 {np.max(np.abs(r_sym-data_symmetric)):.6f})print(f\n非对称量化:)print(f scale (max-min)/255 ({np.max(data_symmetric):.4f}- ({np.min(data_symmetric):.4f})) / 255 {s_asym:.6f})print(f zero_point {zp_asym})print(f q {q_asym})print(f 反量化 {r_asym})print(f 误差 {np.max(np.abs(r_asym-data_symmetric)):.6f})# # 场景2非对称数据# print(\n*60)print(场景2非对称分布的数据全是正数像 ReLU 输出)print(*60)print(f原始数据:{data_asymmetric})q_sym,s_sym,r_symsymmetric_quantize(data_asymmetric)q_asym,s_asym,zp_asym,r_asymasymmetric_quantize(data_asymmetric)print(f\n对称量化:)print(f scale max(|x|)/127 {np.max(np.abs(data_asymmetric)):.4f}/ 127 {s_sym:.6f})print(f q {q_sym})print(f 反量化 {r_sym})print(f 误差 {np.max(np.abs(r_sym-data_asymmetric)):.6f})print(f 注意: 负方向 [-127, 0) 的 127 个值全部浪费了)print(f\n非对称量化:)print(f scale (max-min)/255 ({np.max(data_asymmetric):.4f}- ({np.min(data_asymmetric):.4f})) / 255 {s_asym:.6f})print(f zero_point {zp_asym})print(f q {q_asym})print(f 反量化 {r_asym})print(f 误差 {np.max(np.abs(r_asym-data_asymmetric)):.6f})print(f 注意: 全部 256 个值都被利用0 映射到{zp_asym})# # 对比scale 精度差异# print(\n*60)print(关键对比scale 精度差异)print(*60)# 对称量化s_symnp.max(np.abs(data_asymmetric))/127# 非对称量化s_asym(np.max(data_asymmetric)-np.min(data_asymmetric))/255print(f对称: scale {s_sym:.6f}(量化台阶{s_sym:.6f}))print(f非对称: scale {s_asym:.6f}(量化台阶{s_asym:.6f}))print(f非对称的 scale 更小 量化更精细 精度更高)print(f但反量化需要 zero_point 偏移计算更复杂)# 预期输出仅供参考实际结果因环境略有差异# # 场景1对称分布的数据均值≈0正负各半# # 原始数据: [ 0.5 -0.3 0.1 -0.8 0. 0.6 -0.2]## 对称量化:# scale 0.8000 / 127 0.006299# q [ 79. -48. 16. -127. 0. 95. -32.]# 反量化 [ 0.498 -0.302 0.101 -0.800 0.000 0.598 -0.202]# 误差 0.001575## 非对称量化:# scale (0.60 - (-0.80)) / 255 0.005490# zero_point 146.0# q [237. 91. 164. 0. 146. 255. 110.]# 反量化 [ 0.500 -0.302 0.099 -0.802 0.000 0.598 -0.198]# 误差 0.002745# # 场景2非对称分布的数据全是正数像 ReLU 输出# # 原始数据: [3. 2.8 0.1 0.05 0. 0. 0. ]## 对称量化:# scale 3.0000 / 127 0.023622# q [127. 119. 4. 2. 0. 0. 0.]# 反量化 [3. 2.811 0.094 0.047 0. 0. 0. ]# 误差 0.011811# 注意: 负方向 [-127, 0) 的 127 个值全部浪费了## 非对称量化:# scale (3.00 - 0.00) / 255 0.011765# zero_point 0.0# q [255. 238. 9. 4. 0. 0. 0.]# 反量化 [3. 2.8 0.106 0.047 0. 0. 0. ]# 误差 0.005882# 注意: 全部 256 个值都被利用0 映射到 0.0第五部分使用场景┌─────────────────────────────────────────────────────────┐ │ 模型部署中的选择 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 权重 (Weights): │ │ → 对称量化 ✓ │ │ 原因: 权重天然对称分布均值≈0对称量化最合适 │ │ 反量化: x q × scale简单 │ │ │ │ 激活值 (Activations): │ │ → 看情况 │ │ - ReLU 后面: 全是正数 → 非对称量化更好 │ │ - 没有 ReLU: 正负都有 → 对称量化更简单 │ │ │ │ 实际工程中: │ │ 大部分框架如 TensorRT默认对权重用对称量化 │ │ 对激活值可以根据校准数据分析选对称还是非对称 │ │ │ └─────────────────────────────────────────────────────────┘总结对称量化 简单但浪费一点精度 scale max(|x|) / 127 0 → 0反量化: x q × scale 非对称量化 复杂但精度稍高 scale (max - min) / 255 0 → zero_point反量化: x (q - zp) × scale 选择原则: - 权重 → 对称量化自然对称分布 - ReLU 激活 → 非对称量化全是正数 - 追求简单 → 对称量化够用自测Q1对称量化为什么只用到 [-127, 127]而不是 [-128, 127]点击查看答案对称量化用 [-127, 127] 是为了让 0 映射到 0。如果用了 [-128, 127]正方向有 128 个值含 0负方向有 128 个值-1 到 -128但 0 在正方向导致正负不对称。所以实际只用 [-127, 127]牺牲一个值交换 0 对齐的便利。Q2什么情况下非对称量化比对称量化好点击查看答案当数据分布不对称时如 ReLU 输出全是正数范围 [0, 3.0]。对称量化会浪费 [-127, 0) 的 127 个值而非对称量化利用全部 256 个值精度更高。Q3为什么权重通常用对称量化点击查看答案权重天然对称分布均值约 0对称量化不浪费范围反量化简单x’ q × scale卷积计算不需要处理 zero_point所有主流框架默认对权重使用对称量化一句话记住对称量化 0 对齐简单非对称量化 全范围利用复杂。权重用对称ReLU 激活用非对称。