量化感知训练——LSQ算法原理详解
量化感知训练——LSQ算法原理详解
模型量化是深度学习领域中一个重要的优化技术,它通过将模型的浮点数参数转换为整数,从而在保持模型性能的同时,显著降低计算成本和存储需求。本文将详细介绍模型量化的概念、必要性以及一种经典的量化感知训练算法——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):在训练过程中模拟量化过程,通过更新参数使模型适应量化带来的误差。
量化感知训练的核心问题
- 如何模拟量化过程?
- 通过在训练中插入伪量化节点,对weight和激活值进行量化后再反量化,使用新的weight和激活值进行前向计算。
- 如何更新参数?
- 使用直通估计(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博客