LLM大模型量化原理

大型语言模型(LLM)可以用于文本生成、翻译、问答任务等。但是,LLM 也非常大(显然,大型语言模型)并且需要大量内存。 这对于手机和平板电脑等小型设备来说可能具有挑战性。

可以将参数乘以所选的精度大小以确定模型大小(以字节为单位)。 假设我们选择的精度是 float16(16 位 = 2 字节)。 假设我们想使用 BLOOM-176B 模型。 我们需要 1760 亿个参数 * 2 字节 = 352GB 来加载模型!

在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 

换句话说,要加载所有参数权重,我们需要 12 x 32GB 显存的机器! 如果我们想让LLM具有可移植性,这就太过分了。 减少LLM内存占用的技术就是为了克服这一难题而开发的。 最流行的技术包括:

  • 量化(quantization),涉及将 LLM 的权重转换为较低精度的格式,从而减少存储它们所需的内存。
  • 知识蒸馏(knowledge distillation),涉及训练较小的LLM来模仿较大的LLM的行为。 这可以通过将知识从较大的LLM转移到较小的LLM来完成。

这些技术使得LLM能够适应小内存。 这为在各种设备上使用LLM开辟了新的可能性。 今天我们来聊聊量化(敬请关注知识蒸馏)。

1、量化简介

让我们从一个简单的例子开始。 我们需要将 2023 转换为二进制:

如你所见,该过程相对简单。 为了存储数字 2023,我们需要 12位(1 位用于 + 或 - 符号)。 对于数字,我们可以使用 int16 类型。

将 int 存储为二进制和将 float 存储为二进制之间存在很大差异。 让我们尝试将 20.23 转换为二进制:

可以看到,浮点部分(尾数:mantissa)是按 1/2^n 的组合计算的,即使有 10 位专用于浮点部分,也无法非常精确地计算。 指数部分(指数:exponent)设置为 5 位,涵盖 32 以内的所有数字。总的来说,我们使用 16 位 (FP16) 来存储最接近 20.23 的值,但这是否是保持最接近 20.23 的最有效方法? 漂浮? 如果整个数字更大(例如 202.3)怎么办?

如果我们查看标准浮点类型,我们会注意到要存储 202.3,我们需要使用 FP32,从计算角度来看,这远远不合理。 相反,我们可以使用 bfloat16 将范围(指数)保存为 8 位,将精度(尾数)保存为 7 位。 这使我们能够扩大可能的小数范围,而不会损失太多精度。

需要明确的是,在进行训练时,我们需要尽可能达到的精度。 但是,将速度和大小优先于小数点后第六位对于推理来说是有意义的。

我们可以将内存使用量从 bfloat16 减少到 int8 吗?

2、零点量化和绝对最大量化

事实上,我们可以,并且有几种量化方法:

零点量化(zero-point quantization)通过将定点范围 (-1, 1) 转换为 int8 (-127, 127),然后将 int8 转换回 bfloat16 来节省一半的内存。

绝对最大量化(abs-max quantization)与零点量化类似,但我们没有设置自定义范围 (-1,1),而是将其设置为 (-abs(max), abs(max))。

让我们看一下这些量化如何在矩阵乘法的示例中使用,注意结果矩阵中数值的损失。首先看下未量化的精确矩阵乘法:

零点量化后的矩阵乘法:

绝对最大量化后的矩阵乘法:

3、异常数值分离计算

可以注意到,计算结果中较大的数值如 [-1579, -1780],量化后计算的损失比较大(零点量化后得到 [-1579, -1752],绝对最大量化后得到 [-1565,-1786])。 为了克服这些问题,我们可以单独处理离群的异常值:

正如你所看到的,结果更接近真实值。

4、量化到4个比特

但有没有一种方法可以在不损失太多质量的情况下使用更少的空间呢?

令我惊讶的是,有办法! 如果我们不是独立地将每个数字转换为较低类型,而是考虑错误并将其用于调整,会怎么样? 这种技术称为 GPTQ

与之前的量化一样,我们尽可能找到最接近的小数匹配,使总转换误差尽可能接近于零。

下面是GPTQ近似的第一步:

我们以这种方式逐行填充矩阵:

结果与异常值分离计算相结合,提供了相当不错的结果:

5、量化方法比较

我们现在可以比较各种量化方法:

LLM.int8() 方法表现得非常好! GPTQ 方法会损失质量,但允许使用两倍于 int8 方法的 GPU 内存。

6、BitsAndBytes量化参数

在代码中,你可能会发现类似于以下内容:

from transformers import BitsAndBytesConfig

# Configure BitsAndBytesConfig for 4-bit quantization
bnb_config = BitsAndBytesConfig(
 load_in_4bit=True,
 bnb_4bit_use_double_quant=True,
 bnb_4bit_quant_type="nf4",
 bnb_4bit_compute_dtype=torch.bfloat16,
)
# Loading model in pre-set configuration
pretrained_model = AutoModelForCausalLM.from_pretrained(
 model_id,
 quantization_config=bnb_config,
)

参数说明如下:

  • load_in_4bit 标志指定模型应以 4 位精度加载。  
  • bnb_4bit_use_double_quant 标志指定应使用双量化。
  • bnb_4bit_quant_type 标志指定量化类型。
  • bnb_4bit_compute_dtype 标志指定计算数据类型。

7、结束语

总而言之,我们了解了小数如何存储在内存中、如何通过一些精度损失来减少内存占用,以及如何通过 4 位量化运行选定的模型。


原文链接:LLM的量化 - BimAnt

### 模型量化的工作原理 模型量化是指将浮点数表示的神经网络参数转换成低精度整数的过程,从而减少内存占用并加速推理过程。这一过程中,主要目标是在尽可能减小性能损失的前提下实现上述优化。 #### 浮点到定点的映射 在量化过程中,原始浮点数值通过线性变换被映射至较低位宽的整数空间。具体来说,对于给定的一组浮点数 \(f\) ,其对应的量化整数 \(q\) 可以按照下述公式计算得出: \[ q = round\left(\frac{f}{s} + z \right)\] 其中\( s \)(scale factor) 是缩放因子,用于调整量化范围;\(z\)(zero point) 则是零点偏移量,用来确保量化后的分布能够较好地匹配原数据分布[^1]。 #### 对称与非对称量化 根据是否考虑负值的存在,可以分为两种常见的量化形式——对称量化和非对称量化。前者通常采用 int8 类型来表达,后者则倾向于使用 uint8 。选择何种方式取决于实际应用场景中的需求以及硬件支持情况[^5]。 #### 训练后量化(Post-training Quantization) 训练后量化是一种无需额外训练即可应用于已有的预训练模型的技术手段。该方法通过对现有模型结构不做任何改动,在部署阶段直接实施量化处理。尽管简单易行,但在某些情况下可能会引起一定程度上的准确性下降。因此,在实践中往往还需要配合其他策略如敏感度分析或混合精度方案共同作用以达到更好的平衡。 #### 大型语言模型(LLM) 的特殊考量 针对大型语言模型而言,由于这类模型具有极其庞大的参数规模,所以对其施加有效的量化措施显得尤为重要。除了常规的量化流程外,还需特别关注如何维持较高的预测质量。为此,研究者们提出了诸如 SmoothQuant 等专门面向 LLM 的高效量化算法,旨在解决因高维稀疏特征带来的挑战[^3]。 ```python import torch.nn as nn class Model(nn.Module): def __init__(self): super(Model, self).__init__() # 假设这是某个简单的卷积层定义 conv_layer = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=(3, 3)) # 应用PTQ技术对该层进行量化前准备 quantized_conv_layer = torch.quantization.QuantWrapper(conv_layer) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值