我们下一步是解读QLoRA这种微调技术。与LoRA、AdaLoRA不同,理解QLoRA还需要对模型量化技术有一定的了解。因此,本专栏将通过后续3~4篇文章来详细理解一下QLoRA。今天我先简单地介绍一下模型量化技术。

1.模型量化技术概览

1.1.模型参数与显存占用计算方法

在模型训练、模型推理的过程中,需要考虑GPU的显存是否满足要求,那么模型参数与GPU显存具体怎么估算呢?

  • 总参数量:已Qwen2-7B-Instruct为例,7B就是参数量为7Billion,即70亿参数。
  • 每个参数的显存占用:假设Qwen2-7B-Instruct的dtype选择为Float16,那么每个参数占2个字节,即16bit。
  • 总显存量总参数量 = 每个参数的显存占用 * 总参数量,因此:
    • QWen2-7B-Instruct总显存占用量 = 2字节 * 70亿 = 140亿字节 = 14 * 109字节
  • 总显存量换算1GB = 230B ≈ 109字节,因此:
    • Qwen2-7B-Instruct总显存占用量 = 14GB

我们将Qwen2-7B-Instruct以Float16加载到GPU中,观察一下GPU的显存占用大致也是14GB。

根据上述原理,我们可以提出一个问题:如果降低每个参数的显存占用,是不是就可以降低GPU的总显存量?

1.2.模型量化解决的问题及关键要素

模型量化(Model Quantization),就是聚焦于用更少位数的信息表示法,降低模型每个参数的显存占用量,进而降低模型的总显存占用量。

  • 如:模型权重以Float32存储(即每个参数的显存占用量为32bit),假设总显存占用量M。
  • 如果将每个参数量化为Float16(即每个参数的显存占用量为16bit),则只需要二分之一的总显存占用量M。
  • 如果将每个参数量化为Int8(即每个参数的显存占用量为8bit),则只需要四分之一的总显存占用量M。
  • 如果将每个参数量话为NF4(即每个菜单树的显存占用量为4bit),则只需要八分之一的总显存占用量M。

因此,我们可以很自然地想到模型量化技术的关键要素之一——量化精度

  • 用更少位数表示更高位数的数字,精度不会丢失吗?丢失的精度会给模型训练和模型推理带来多少误差?
  • 简单地将模型的参数向量的每个元素认为是一个用32bit表达的小数转为用4bit表达,直觉上就会带来极大地误差。

另外,还有其它2个关键要素:

  • 模型架构
  • 硬件设备:GPU、NPU、TPU等

image-20240723154227521

2.量化三步曲

量化过程包括:向量量化、算子量化、模型量化

image-20240723160736130

2.1.向量量化

向量量化是所有量化的基础,量化过程包括量化函数反量化函数

  • 假设量化函数为:X表示原始向量,INT8表示量化后向量

image-20240723162534164

  • 假设反量化函数为:INT8表示量化后向量QX表示通过量化后向量,还原的还原向量

image-20240723162633015

  • 假设误差函数为:原始向量X还原向量QX可能存在误差,误差当然越小越好,衡量这个误差的函数就是误差函数。

image-20240723162954824

(1)INT4

INT4的向量量化过程为例:

  • 假设向量系数为:

image-20240723165432046

  • 假设原始向量为:

image-20240723165524411

  • 原始向量进行计算:
    • 求每个分量的绝对值的最大值,结果为1.52。
    • 将每个分量除以1.52,得到过程向量[0.18, 0.38, -0.49, 1.00]。

image-20240723165559900

  • 过程向量进行计算:
    • 在量化系数中,找到最近的值,得到最近值向量

image-20240723165922698

  • 最近值向量进行计算,得到最终的量化后向量
    • 将最近值向量的每个分量用量化系数的索引进行替换,得到最终的量化后向量[9, 10, 4, 15]。

image-20240723170126385

再来看看INT4的向量反量化过程:

  • 量化后向量,根据索引还原为过程向量

image-20240723170439886

  • 过程向量乘以稀疏1.52,得到还原向量
    • 还原向量为[0.304, 0.5016, -0.7144, 1.52]。

image-20240723170605292

  • 我们可以看到,原始向量还原向量存在一定的误差

image-20240723170731983

从数据分布上看,INT4量化方法更适合如下数据分布特征(中段数据过于一致,此量化方法有局限性):

image-20240724095119629

(2)FP4

FP4的计算过程不赘述,可参考:

https://huggingface.co/blog/4bit-transformers-bitsandbytes#fp4-precision-in-a-few-words

image-20240920110352774

(3)NF4

NF4 Quant是QLoRA提出的一种新的数据类型(4-bit NormalFloat),量化过程中保留了零点,使用2k位表示k位数据类型。

NF4通过估计两个范围的分位数qi,创建了一个非对称的数据类型。第一个范围表示负数部分[-1, 0]的2k-1,第二个范围表示正数部分[0, 1]的2k-1+1.

这种量化方法在每个量化bin中都具备相等的期望值数量,这种以零为中心的正态分布数据在信息论中是最优的。

上述数学方法到底解决什么问题呢?预训练的权重通常具有以零为中心的正态分布(标准差为σ),缩放σ可以使得权重分布适应NF的范围,量化时的数据类型和神经网络权重的分位数最终都会被归一化到[-1, 1]的范围内。计算分位数的公式:

image-20240920112507633

更详细的代码参考:

https://github.com/bitsandbytes-foundation/bitsandbytes/blob/main/csrc/kernels.cu

1
__device__ static float nf4_data[16] = {-1.0, -0.6961928009986877, -0.5250730514526367, -0.39491748809814453, -0.28444138169288635, -0.18477343022823334, -0.09105003625154495, 0.0, 0.07958029955625534, 0.16093020141124725, 0.24611230194568634, 0.33791524171829224, 0.44070982933044434, 0.5626170039176941, 0.7229568362236023, 1.0};

2.2.算子量化

在数学领域,一个函数空间到函数空间上的映射O:X→Y,称为算子。广义上,对任何函数进行某一项操作都是一个算子:

  • 如:微分算子
  • 如:不定积分算子

在深度学习中,各种网络结构,都是由若干的计算单元组成,这些计算单元就是算子(Operator)。

  • 如:卷积层(Convolution Layer)是一个算子
  • 如:全连接层(Fully-connected Layer, FC layer)中的权值求和过程,也是一个算子。

如下图所示,Conv1、Pool1、Conv2都是网络中的算子,Conv1和Conv2都是做卷积运算的算子(Convolution)。

image-20240920133118786

参考:https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/80RC2alpha002/devguide/opdevg/tbeaicpudevg/atlasopdev_10_0006.html

算子量化如何开展呢?我们可以看到算子的前端有输入,算子的后端有输出。因此,算子量化就是将输入向量进行量化,对输出向量进行量化,而不修改算子的逻辑。但算子量化也有一些特殊情况:有的算子不能量化输入,有的算子不能量化输出。

2.3.网络量化

  • 关闭冗余量化信息

    • 在量化神经网络过程中,需要有量化控制信息向量TQC。

    • 在神经网络中,算子Conv连接到算子Reshape上,那么就会出现两个一模一样的TQC。

    • 这种量化控制信息就是多余的,我们就需要消除掉Reshape侧的量化控制信息。

image-20240920134759671

  • 图融合
    • 本质是将N个标准的小算子进行融合,如:对Conv后的激活函数进行算子融合。
    • 算子融合后得到了一个新的非标的大算子,进而减少了量化控制信息。
    • 如下图:为了实现FlashAttention,将图中的MatMul算子(Cube)、Scale算子(Vector)、Mask算子(Vector)、SoftMax算子(Vector)融合为一个大的算子Flash Attention。

image-20240920135602648

参考:https://www.hiascend.com/doc_center/source/zh/canncommercial/80RC2/developmentguide/opdevg/Ascendcopdevg/atlas_ascendc_10_0041.html

3.总结

为了解读QLoRA的原理,我们简要地介绍了模型量化技术的概念和基本原理:

  • 模型量化的第一层是向量量化,即针对向量量化,有量化函数和反量化函数。
  • 模型量化的第二层是算子量化,即针对算子的输入向量和输出向量进行量化。
  • 模型量化的第三层是网络量化,即针对网络去除冗余的量化控制信息、将小算子融合为大算子进行整体量化处理。

有了本文的模型量化基础知识,我们就可以进一步阅读QLoRA的论文了。

论文链接:https://arxiv.org/pdf/2303.10512