问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

量化感知训练——LSQ算法原理详解

创作时间:
作者:
@小白创作中心

量化感知训练——LSQ算法原理详解

引用
CSDN
1.
https://blog.csdn.net/weixin_42841721/article/details/135878973

模型量化是深度学习领域中一个重要的优化技术,它通过将模型的浮点数参数转换为整数,从而在保持模型性能的同时,显著降低计算成本和存储需求。本文将详细介绍模型量化的概念、必要性以及一种经典的量化感知训练算法——LSQ(Learning Step Size Quantization)的原理。

1. 什么是模型量化

对浮点型(float)的模型参数(weight)和激活值(activation)通过某个映射,离散化成整型,如将float的参数通过一个线性映射变成int8的整型。这个线性映射可以表示为:

其中:

  • ( x ) 为float类型的参数,
  • ( scale ) 为缩放参数,
  • ( zero_point ) 为偏置,也称为零点值,即当 ( x ) 为0时对应的量化值,
  • ( y ) 为量化后的值。

2. 为什么要模型量化

模型量化的目的是将float类型的计算转换为整型计算。例如,PC端训练的模型参数通常是float32类型,位宽为32;而int8的位宽只有8。使用量化后的int8进行模型推理计算,然后再反量化得到最终输出,可以显著提升计算速度并减少内存占用。然而,这种转换会导致精度损失,因此模型量化需要解决的核心问题是保持推理准确率。

以一个具体的量化过程为例:

假设有一个tensor:

我们需要将其量化到uint8,即[0, 255]区间。根据量化公式:

计算得到:

量化前的tensor:

量化后的qtensor:

显然,量化前后存在误差,这种误差的积累会影响模型的推理结果。

3. 怎么进行量化

模型量化主要有两种方式:

  • 后训练量化(Post-training quantization, 简称PTQ):对训练后的模型参数,利用统计学方法找到合理的映射,将float型离散化为整型。
  • 量化感知训练(Quantization Aware Training, 简称QAT):在训练过程中模拟量化过程,通过更新参数使模型适应量化带来的误差。

量化感知训练的核心问题

  1. 如何模拟量化过程?
  • 通过在训练中插入伪量化节点,对weight和激活值进行量化后再反量化,使用新的weight和激活值进行前向计算。
  1. 如何更新参数?
  • 使用直通估计(Straight Through Estimator, 简称STE):在反向传播中,跳过伪量化过程的导数为零的问题,直接对伪量化之前的参数进行更新。

4. QAT算法——LSQ算法原理介绍

LSQ(Learning Step Size Quantization)是一种经典的QAT算法,其主要思想是通过插入伪量化节点,学习并更新量化参数scale,以适应量化误差。与传统的QAT算法不同,LSQ不仅调整weight以适应量化误差,还通过学习scale(以及可选的偏移offset)来进一步优化量化效果。

核心问题:如何更新量化参数scale?

LSQ算法的伪量化前向计算过程如下:

具体公式表示为:

其中:

  • ( clip ) 代表截断操作,
  • ( round ) 代表取整操作,
  • ( x ) 是float输入,
  • ( y ) 是量化后的数据(使用float存储但数值为整数),
  • ( z ) 是反量化结果,
  • ( min ) 和 ( max ) 是量化数值的最小值和最大值,
  • ( s ) 是量化参数。

合并上述公式得到:

对 ( s ) 求导得到:

其中:

通过上述推导,我们得到了插入伪量化节点后被量化参数对scale参数的偏导,这为通过训练学习scale提供了理论基础。

算法参数初始化和s的梯度调整

  • 每一层的权重(weight)或激活值(activation)都有对应的scale参数 ( s ),一般可以初始化为 ( s = \frac{max - min}{2^b - 1} )(其中 ( b ) 是量化位数)。
  • 量化训练的权重初始化可由预训练好的float模型的权重得到,激活值的初始化可由一些代表性的数据进行推理计算得到。
  • 为了在训练中更好地收敛,对scale参数的梯度进行调整,用scale乘以一个gradient scale,记作 ( g )。对于权重,( g = \frac{1}{N} )(其中 ( N ) 是每一层中权重的个数);对于激活值,( g = \frac{1}{M} )(其中 ( M ) 是每层激活值中特征的个数)。

本文原文来自CSDN博客

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号