2w字解析量化技术,全网最全的大模型量化技术解析

# 2w字解析量化技术,全网最全的大模型量化技术解析 📖阅读时长:50分钟 🕙发布时间:2025-01-31 > 这篇网页文章主要围绕机器学习中的量化技术展开,详细介绍了其在大语言模型中的应用、基础概念、技术方法及不同模型的量化策略。 量化是机器学习领域的一项关键优化技术,它能把高精度数值转化为低精度格式。在大型语言模型(LLM)的世界里,量化可以将32位浮点参数,巧妙地变成8位或4位整数这种更紧凑的形式,这可太厉害了,能让模型在资源有限的环境中轻松实现高效部署。 ![](https://upload-images.jianshu.io/upload_images/17294212-31cbdea4bc407472.png) ## 一、量化带来的诸多优势 - **降低内存占用**:就像给模型做了一次“瘦身”,让它占用的内存空间大幅减少。 - **加快推理速度**:模型推理时就像装上了“小马达”,速度更快了,能迅速给出结果。 - **减少能源消耗**:变得更节能了,在运行时消耗的能源大大降低。 - **提升部署灵活性**:不管是在什么样的设备上,都能更灵活地进行部署。 ## 二、大语言模型的规模挑战 如今,现代大语言模型规模大得超乎想象!像Claude、Gemini、GPT和Llama系列这些模型,个个都包含了几十亿个参数。如此庞大的规模,对内存提出了超高要求。大部分硬件加速器,比如CPU、GPU和TPU,处理整数运算的速度比浮点运算更快,而且还更节能。要是把模型量化成8位、4位,甚至1位整数,推理速度会加快,耗电量也会降低,在移动设备和边缘设备上,响应速度更快,电池续航时间也更长。在计算中使用浮点数时,位宽(所用的位数)在平衡精度和内存使用方面起着关键作用。 ### (一)32位浮点(FP32):高精度的代表 ![](https://upload-images.jianshu.io/upload_images/17294212-77a7a96cc33def43.png) 32位浮点格式(也就是FP32),每个数字都用32位来表示。这种格式把这些位分成三个部分:符号位、指数位和尾数(小数部分)。FP32能提供高精度的数值表示,因为它分配了更多的位来精确捕捉数字的值。就拿圆周率π来说,FP32会把它存储为3.1415927410125732,和真实值非常接近。不过,每个数字都用32位来存储,这在处理大量数据时,内存占用就成了问题。 ![](https://upload-images.jianshu.io/upload_images/17294212-a5f6dcd0019d4b98.png) ### (二)16位浮点(FP16):在精度和内存间权衡 相比之下,16位浮点格式(FP16)就只用16位,这意味着尾数和指数位的位数都变少了。精度自然就降低了,还是以π为例,在FP16里它被存储为3.140625,虽然很接近,但确实没有FP32那么精确。不过,FP16的优势也很明显,它占用的内存只有FP32的一半。对于大规模数据集或模型来说,内存使用量能大幅减少,所以很适合那些硬件容量有限的设备,或者是对精度要求没那么高、更看重效率的应用场景。 虽说减少位大小有这些好处,可量化过程会引入近似误差,这就可能影响模型的准确性。最大的挑战就在于,要在享受减少内存占用和加快计算速度这些好处的同时,把误差降到最低。 ## 三、量化的基础 ### (一)IEEE-754浮点标准 1. **单精度(FP32)** - **符号位**:1位 - **指数位**:8位 - **尾数位**:23位 - **总范围**:±3.4×1⁰³⁸ 2. **半精度(FP16)** - **符号位**:1位 - **指数位**:5位 - **尾数位**:10位 - **总范围**:±65,504 3. **Bfloat16(BF16)** - **符号位**:1位 - **指数位**:8位 - **尾数位**:7位 - **总范围**:±3.4×10³⁸,和FP32差不多。 Bfloat16在训练和推理中经常用到,尤其是在像TPU这样的硬件中,它既有和FP32相似的大范围表示能力,又有FP16低内存占用的优点。 ### (二)整数格式 1. **INT8(8位整数)** - **总位数**:8位 - **符号位(有符号INT8)**:1位 - **数值位(有符号INT8)**:7位 - **或者数值位(无符号INT8)**:8位 - **范围**: - **有符号**:-128到 +127 - **无符号**:0到255 2. **INT4(4位整数)** - **总位数**:4位 - **符号位(有符号INT4)**:1位 - **数值位(有符号INT4)**:3位 - **或者数值位(无符号INT4)**:4位 - **范围**: - **有符号**:-8到 +7 - **无符号**:0到15 ![](https://upload-images.jianshu.io/upload_images/17294212-d66ad135745f346d.png) ### (三)量化过程 1. **确定数值的动态范围**:要搞清楚数据中数值的变化范围。 2. **选择缩放因子(Δ)**:这个因子很关键,会影响量化的效果。 3. **将浮点值映射为整数**:按照规则把浮点形式的数字变成整数。 4. **存储缩放因子用于反量化**:方便之后把量化后的整数再变回浮点值。 ### (四)量化类型 1. **对称量化**:对称量化是用一个缩放因子把浮点值转化为整数的方法,量化后的值以零为中心对称分布。也就是说,量化值的范围在正数和负数之间是平衡的,从(-α)到(α)。 ![](https://upload-images.jianshu.io/upload_images/17294212-c4b296a7140e068e.png) 比如说,有这么一组FP32值: ``` 4.72, 2.96, -6.48 0, -3.34, -5.26 8.58, 2.19, -3.67 ``` **计算缩放因子**:在8位量化中,我们用的范围是 -127到127。根据最大绝对值来确定缩放因子。这里最大绝对值α = 8.58,量化位数(b)是8位,所以对称整数范围就是 -127到127。 ![](https://upload-images.jianshu.io/upload_images/17294212-e6606247fbd093b4.png) **量化数值**:用缩放因子,把每个FP32值除以缩放因子再四舍五入取整,就得到量化后的INT8值。 ``` 70, 44, -96 0, -49, -78 127, 32, -54 ``` ![](https://upload-images.jianshu.io/upload_images/17294212-327acfce28167639.png) **反量化**:要变回FP32值,就把每个量化后的整数乘以缩放因子。这个过程中会发现,有些值比如 -3.34和2.96,量化后再反量化回FP32格式时,会损失一些精度,和原来的值不完全一样。这个差值就是量化误差,通过计算原始FP32值和反量化值的差得到。一般来说,量化用的位数越少,量化误差就越大,因为位数少,能表示的值范围有限,近似的情况就更多,精度也就更低。 ![](https://upload-images.jianshu.io/upload_images/17294212-e851c63321129122.png) 2. **非对称量化**:非对称量化不是以零为中心对称的。它把浮点范围的最小值(β)和最大值(α),映射到量化范围的最小值和最大值。还是用刚才那组FP32值来举例: ![](https://upload-images.jianshu.io/upload_images/17294212-d3a70ef01a547f51.png) ``` 4.72, 2.96, -6.48 0, -3.34, -5.26 8.58, 2.19, -3.67 ``` **计算缩放因子和零点**:先找出最小值β = -6.48和最大值α = 8.58,然后计算缩放因子和零点。 **量化每个值**:用缩放因子和零点,对每个值进行量化,得到下面这些量化后的INT8值: ``` 190, 160, 0 110, 53, 20 255, 147, 47 ``` **反量化**:要变回FP32值,就用相应的反量化公式计算。同样也可以计算非对称量化的误差,下面的表格能清晰对比两种量化方式。 ![](https://upload-images.jianshu.io/upload_images/17294212-f19f533713b14ad5.png) ![](https://upload-images.jianshu.io/upload_images/17294212-e6f47a1169bb9eaa.png) ![](https://upload-images.jianshu.io/upload_images/17294212-61b0d6587818e8ea.png) ### (五)特定任务的量化建议 1. **自然语言处理任务(NLP)**:训练时用BF16,推理时用INT8。 2. **图像处理任务**:训练时用FP16,推理时用INT8或INT4。 3. **Transformer模型**:注意力层可以混合使用INT8和INT4。 ### (六)裁剪 在量化过程中,有一种常用方法是把向量值的范围映射到低比特表示。这样能以压缩格式捕捉向量所有的值,但遇到比其他数据大很多或者小很多的异常值时,就出问题了。想象有这么一个向量:[0.5, 1.2, -0.7, 2.0, 0.9, 10.5],这里10.5就是个异常值,比其他值大太多。要是把这个向量的整个范围映射到低比特格式(比如INT8),其他小的值最后可能都被压缩成相同或者相似的低比特表示,它们之间的差异信息就没了。这就是绝对最大(absmax)方法的特点,它是根据数据的最大绝对值来设置范围的。 #### 1. 用裁剪处理异常值 为了减少异常值的影响,可以采用裁剪的方法,也就是定义一个自定义的动态范围,把极端值排除在外。比如说,手动把动态范围设为[-5, 5],那么任何超出这个范围的值都会被“裁剪”,不管它实际有多大,都被映射到目标范围的最大值或最小值。在这个例子里,10.5在INT8中会被映射为127,而在[-5, 5]范围内的值能保留更多精度和差异细节。裁剪的好处是,对于选定范围内(非异常值)的值,量化误差能大幅降低,不过异常值的量化误差会变高。在一些场景中,如果少数极端值会主导量化尺度,导致大部分数据精度损失,那这种技术就特别有用。 ![](https://upload-images.jianshu.io/upload_images/17294212-f16cf5a435900f3c.png) #### 2. 校准 上面例子里,[-5, 5]这个动态范围是随便选的,只是为了展示裁剪。但实际上,选择一个最优范围的过程,也就是校准,对有效的量化至关重要。校准的目的是找到一个能包含尽可能多的值,同时又能最小化量化误差的范围。在量化机器学习模型时,这一点尤为重要,因为选了错误的范围会严重影响模型的准确性。 #### 3. 不同类型参数的校准技术 不同类型的参数,校准要求也不一样: - **权重(和偏差)**:在大语言模型(LLMs)里,权重和偏差可以看作是静态值,在模型部署前就确定了。权重是量化的主要关注点,因为它们占了模型大小的绝大部分(常常有几十亿个参数),而偏差数量相对较少,有时候会用更高的精度(比如INT16)来保存。权重的校准技术通常有: - **基于百分位数的裁剪**:设定一个范围,排除一定比例的极端值,重点关注数据点的中间百分位数范围。 - **均方误差(MSE)最小化**:这种方法能最小化原始权重和量化后权重之间的均方误差,有助于保持模型的准确性。 - **最小化KL散度(熵)**:目的是最小化原始值和量化值之间的分布差异(KL散度)。 ![](https://upload-images.jianshu.io/upload_images/17294212-263e31485b350b43.png) 比如说,用基于百分位数的方法,会产生和前面讨论的裁剪类似的效果,把异常值排除掉,更好地表示数据的中心范围。 - **激活值**:激活值就不一样了,它是动态变化的,会随着模型的每次输入而改变。激活值在每个隐藏层都要经过激活函数(比如sigmoid或ReLU),这就使得它们的值取决于当时正在处理的具体数据。这种可变性让应用单一的量化方案变得很困难,因为激活值会根据输入有很大的差异。激活值的校准一般有两种主要方法: - **训练后量化(PTQ)**:在模型训练完成后进行量化,通常在一个有代表性的数据集上进行。 - **量化感知训练(QAT)**:在训练过程中就应用量化,让模型在量化值的约束下进行调整和学习,这样能提高模型的准确性。 ## 四、量化技术 ### (一)训练后量化(PTQ) 训练后量化(PTQ)是一种应用非常广泛的技术,在模型训练完成后,用它来量化模型的参数(权重和激活值)。在PTQ中,权重和激活值可以调整为低精度,而且不需要额外的训练或微调。 1. **权重的量化**:权重可以用对称量化或者非对称量化。如果数据是以零为中心分布的,一般用对称量化;要是数据有偏差,非对称量化能更有效地表示不同的数据范围,就更合适。 2. **激活值的量化**:量化激活值比量化权重要复杂,因为激活值会随着输入和层的不同而变化。要想准确量化激活值,就得知道它们可能的范围,这只能通过让数据在模型中运行(推理)来确定。在PTQ中,激活值量化主要有两种方法:动态量化和静态量化。 3. **动态量化** ![](https://upload-images.jianshu.io/upload_images/17294212-09c749969569fa15.png) 在动态量化过程中,当数据流经每个隐藏层时,会收集并分析激活值。具体过程如下: 1. **激活值收集**:数据通过隐藏层后,记录激活值的分布情况。 2. **计算量化参数**:根据这个分布,计算零点($z$)和缩放因子($s$),用这些参数把激活值映射到低精度格式。每次数据流经一个层,这个过程都会重复,也就是说每个层都有自己的$z$和$s$值,不同层的量化方案也不一样。 ![](https://upload-images.jianshu.io/upload_images/17294212-a833c1b48bc21f21.png) 3. **优势**:动态量化更准确,因为$z$和$s$值是在推理时针对每个层确定的,能适应实际流经模型的数据。 4. **缺点**:不过,在每个层都重新计算这些值,会增加推理时的计算量,可能导致推理过程变慢。 下面这段代码展示了如何用PyTorch对预训练的ResNet18模型应用动态量化。动态量化只应用于特定的层(比如线性层),而且不需要校准数据集。 ```python import torch import torchvision model = torchvision.models.resnet18(pretrained=True) model.eval() ``` 这段代码从`torchvision`加载了一个预训练的ResNet18模型,并把它设置为评估模式(`model.eval()`),这样能确保在推理时批归一化和随机失活层正常工作。 ```python model_quantized = torch.quantization.quantize_dynamic( model, {torch.nn.Linear}, dtype=torch.qint8 ) ``` `torch.quantization.quantize_dynamic`函数动态地对特定层进行量化,具体说明如下: 1. **模型**:`model`参数指定了要量化的模型。 2. **要量化的层**:`{torch.nn.Linear}`表示只对线性(全连接)层进行量化。动态量化通常应用于像线性层和LSTM层这样,大部分计算是矩阵乘法的层,因为这样可以减少内存占用,加快计算速度。 3. **量化类型**:`dtype=torch.qint8`指定在量化过程中,模型的参数会被转换为8位整数(INT8)。在动态量化中,权重在加载时就被量化为INT8,而激活值在推理时动态(实时)量化。这使得动态量化比全精度模型更快,占用内存更少,还不需要校准数据集。 ```python torch.save(model_quantized.state_dict(), 'dynamic_quantized_model.pth') ``` 最后,把量化后模型的状态字典保存到`dynamic_quantized_model.pth`文件里,之后加载这个文件就能进行高效推理了。 4. **静态量化** 另一方面,静态量化在推理前就确定了$z$和$s$值。这涉及到: 1. **校准数据集**:用一个有代表性的数据集(校准数据集)在模型中运行,收集激活值的分布情况。 2. **计算量化参数**:根据这个分布,计算并存储$z$和$s$值。在推理时,这些值会在所有层和激活值中统一使用。 3. **优势**:静态量化通常更快,因为在推理时不用重新计算$z$和$s$值,依靠预先计算好的值,计算效率更高。 4. **缺点**:静态量化和动态量化比起来可能没那么准确,因为它在校准过程中只用了一组$z$和$s$值。如果在实际推理时激活值的分布变化很大,就可能导致更高的量化误差。 ```python import torch import torchvision import torch.quantization as quant model = torchvision.models.resnet18(pretrained=True) model.eval() ``` 这段代码加载了有预训练权重的ResNet18模型,并设置为评估模式(`model.eval()`),这是推理和量化的必要步骤。 ```python model.qconfig = torch.quantization.get_default_qconfig("fbgemm") ``` 用`torch.quantization.get_default_qconfig("fbgemm")`设置量化配置。FBGEMM后端针对x86 CPU进行了优化,通常使用8位整数(INT8)量化,能实现更快、更节省内存的推理。 ```python model_prepared = torch.quantization.prepare(model, inplace=False) ``` `prepare`函数会在模型的层中插入量化观察器,收集静态量化所需的激活统计信息。设置`inplace=False`会创建模型的修改副本。 ```python for _ in range(20): input_tensor = torch.randn(1, 3, 224, 224) model_prepared(input_tensor) ``` 在校准过程中,样本数据(形状为`(1, 3, 224, 224)`的随机张量,代表批量大小为1、分辨率为224x224的RGB图像)会通过模型。这些运行过程会收集激活统计信息,用于确定量化的缩放因子和零点。 **输入形状说明**:`(1, 3, 224, 224)`是ResNet18期望的输入形状。在这个例子中,你可以自由调整批量大小。例如,将输入形状设置为`(32, 3, 224, 224)`,将一次性处理32张图像,如果硬件允许,这可以提高推理时的吞吐量。不过,通道数(RGB图像为3)和分辨率(224x224)应保持不变,以与ResNet18兼容,因为它期望的图像具有这些维度。 ```python model_quantized = torch.quantization.convert(model_prepared, inplace=False) ``` `convert`函数应用收集到的量化参数(缩放因子和零点),创建量化版本的模型。这会用量化版本替换某些层,针对INT8操作进行优化。 ```python torch.save(model_quantized.state_dict(), "quantized_model.pth") ``` 最后,量化模型的状态字典(参数)被保存到文件中。之后加载这个文件,就能以量化形式进行高效推理。 ### 4位量化 将模型精度降低到4位(甚至更低)一直颇具挑战,因为随着比特精度的每一次降低,量化误差都会增加。低比特量化虽然效率很高,但如果处理不当,可能会降低模型精度。不过,随着量化技术的进步,现在模型能够在保持性能的同时达到4位精度。 #### 4位量化的方法 对于大型语言模型,4位量化通常采用两种主要方法: 1. **GPTQ**:主要针对GPU进行优化,并使用加权量化误差校正。 2. **GGML和GGUF**:这些技术旨在支持混合精度和CPU卸载,其中GGUF在GGML的基础上进行了改进,克服了其一些局限性。 3. **AWQ**:专为高效4位量化而设计,采用激活感知方法,无需重新训练数据即可最小化精度损失,适用于在资源受限环境中的CPU和GPU上进行部署。 ![](https://upload-images.jianshu.io/upload_images/17294212-b00a82a89be091e6.png) 在实际场景中,这些方法适用于4位精度,但如果再降低精度(例如到3位或2位精度),可能会引入过多量化误差,在不显著降低模型精度的情况下很难维持其准确性。 #### GPTQ GPTQ是在高性能模型中实现4位量化的常用选择。GPTQ采用非对称量化方法,一次对一层进行量化。通过独立处理每一层,GPTQ确保在进入下一层之前,每一层都能得到专门的处理。 ![](https://upload-images.jianshu.io/upload_images/17294212-f617bf9a9d0098db.png) 以下是GPTQ处理量化的详细步骤: 1. **独立层量化**:GPTQ按顺序对每一层进行量化,为每一层应用独特的设置。首先使用逆海森矩阵对权重进行变换,这一过程可以表明每个权重对模型输出变化的敏感程度。 - **量化中的海森矩阵**:在量化的背景下,尤其是对于神经网络,逆海森矩阵(模型损失函数的二阶导数)有助于我们了解模型输出对每个权重变化的敏感程度。逆海森值较低的权重更敏感,意味着这些权重的微小变化可能会对模型输出产生显著影响。在量化过程中,逆海森矩阵有助于对这些敏感权重进行优先级排序,以便更精细地分配精度,减少量化误差并保持模型精度。 2. **基于逆海森敏感性的量化**:计算完逆海森矩阵后,GPTQ对层内的每个权重进行量化,然后再反量化。这使得该方法能够计算量化误差($q$),捕捉将权重转换为低比特格式时损失的精度。 ![](https://upload-images.jianshu.io/upload_images/17294212-013eb29e51d1fa03.png) 3. **加权量化误差调整**:GPTQ通过将量化误差与逆海森敏感性值($h$)进行权衡,进一步优化量化误差。这一调整过程会优先考虑对精度至关重要的权重,有效地生成加权量化误差,从而保留更重要的细节。其中,$q$是量化误差。 ![](https://files.mdnice.com/user/13819/22e93173-1649-43a6-9d49-43ce519b2025.png) ![](https://files.mdnice.com/user/13819/377d7996-7737-4095-8479-5c449b91a791.png) 4. **权重间的误差重新分配**:GPTQ不会让量化误差孤立地存在于单个权重上,而是将误差在层内相关权重之间重新分配。这种方法确保即使在精度降低的情况下,模型的功能仍能保持一致。例如,权重$x_2$的误差为$0.3$,可以通过应用按$h_2$($x_2$的敏感性)缩放的$q$来平衡。 ![](https://upload-images.jianshu.io/upload_images/17294212-503e52fa33dae338.png) ![](https://upload-images.jianshu.io/upload_images/17294212-18d3c6ebde5d43ba.png) 5. **迭代优化**:GPTQ对层内的每个权重迭代应用这一过程,使相关权重能够“分担”量化误差,直到所有值都以平衡精度和功能的方式完成量化。最终得到的层,其权重经过更新,能更好地适应4位量化的限制。 #### GPTQ敏感性感知方法的优势 GPTQ对权重敏感性的关注使其即使在较低精度下也能保持准确性。通过在相互关联的权重之间重新分配量化误差,它确保了模型性能的稳健性。这种方法特别有效,因为层内的权重通常具有复杂的关系,保留这些连接有助于保持模型的整体完整性。 #### GPTQ中的其他优化技巧 为了进一步提高4位量化的效率,GPTQ融入了一些专门的优化技术: 1. **阻尼因子**:降低逆海森矩阵中高敏感性的影响,防止某些权重变得过于不稳定。 2. **延迟批处理**:以计算高效的方式对更新进行分组,最小化处理开销。 3. **乔列斯基分解**:预先计算逆海森矩阵,以便更快地进行量化,利用数学分解技术实现更流畅的执行。 #### 神经网络中的涌现特征 1. **定义**:涌现特征是在大型神经网络中观察到的一种现象,不同层在识别和标记数据中的特定特征时趋于一致。这种一致性表明数据的某些方面被有效地捕捉到了,它可以被视为网络所学“知识”的一种体现。 2. **特征**: - **大权重**:涌现特征通常表现为权重明显大于网络中平均权重。例如,如果网络中的平均权重约为$0.5$,涌现特征可能由$10.0$或$-8.5$这样的权重表示。这表明这些权重在模型的决策过程中起着至关重要的作用。 - **信息集中**:这些大权重有助于网络处理和解释输入数据,有效地充当模型已学会识别的特征的指示符。 3. **示例**:考虑神经网络中的以下权重矩阵: - 在这个矩阵中,权重$-10.0$、$8.5$和$-15.0$可以被视为涌现特征。它们的量级比矩阵中的其他权重明显更大。 - 这些权重对模型的输出至关重要,表明它们代表了模型进行预测所依赖的重要特征。 4. **在量化中的重要性**:在量化方面,涌现特征至关重要。代表涌现特征的权重通常保持较高精度,不进行量化。做出这一决策是为了保持模型的性能和准确性。通过以原始精度保留这些权重,网络可以保留其所学知识,并有效地响应输入数据,确保在量化过程中保留关键特征。 ### GGUF GGUF是一种先进的量化方法,当GPU内存(VRAM)不足时,它能够将大型语言模型(LLM)的层卸载到CPU上。这种灵活性使模型能够高效利用CPU和GPU资源,便于在各种硬件配置上进行部署。 ![](https://upload-images.jianshu.io/upload_images/17294212-176192790aa0592c.png) #### GGUF详细步骤解析 1. **块结构**:在GGUF中,每一层的权重被组织成层次化的块结构。 - **超级块**:这些是较大的段,包含多个子块,为量化提供整体上下文和尺度。 - **子块**:这些是超级块内的较小单元,其中的权重会被单独进行量化处理。 - **示例**:假设有一个LLM层的权重如下。在这个例子中,我们可以定义一个包含三个子块的超级块。每个子块可能包含一行权重,权重划分如下: - **超级块1**: - **子块1**:[0.5, 0.3, -0.1] - **子块2**:[-0.7, 0.2, -0.6] - **子块3**:[0.8, 0.4, -0.1] 2. **缩放因子提取**:从这些块中提取两个关键组件: - **缩放因子($s$)**:用于对子块中的权重进行量化的乘数。 - **Alpha($\alpha$)**:表示每个子块内的最大绝对权重值。 - **示例**:对于子块1,$\alpha = \max(|0.5|, |0.3|, |-0.1|) = 0.5$,子块的缩放因子$s$可以根据其值计算得出。 3. **量化过程**:为了量化一个“子”块,应用绝对最大(absmax)量化:量化后的权重 = $s$×权重。假设子块1的$s = 0.5$,每个权重的量化过程如下: - 对于$0.5$:量化后的权重 = $0.5×0.5 = 0.25$ - 对于$0.3$:量化后的权重 = $0.5×0.3 = 0.15$ - 对于$-0.1$:量化后的权重 = $0.5× -0.1 = -0.05$ 4. **逐块量化**:在量化过程中,超级块的缩放因子($s_{\text{super}}$)用于指导每个子块缩放因子($s_{\text{sub}}$)的量化。这种方法考虑到超级块提供的更广泛上下文,使得量化过程更加准确。例如,如果超级块的缩放因子$s_{\text{super}} = 1.0$,它可以用于调整子块的量化级别。 ![](https://upload-images.jianshu.io/upload_images/17294212-13f7cbe2b8af8182.png) 5. **零点调整**:在应用量化时,可能需要一个额外的最小值($m$)来调整量化的零点。这有助于保持模型输出的完整性,处理方式与缩放因子类似。 #### 量化级别 GGUF具有通用性,能够适应各种量化级别(主要是4位)。每个级别可能涉及不同的量化策略,以平衡精度和资源效率。 GGUF是一种强大的量化方法,它使大型语言模型能够高效利用CPU和GPU资源。通过采用层次化块结构并利用缩放因子,GGUF即使在较低精度的约束下也能保持模型性能。这种在管理硬件资源方面的灵活性,使GGUF成为在不同环境中部署LLM的有吸引力的选择。 ### AWQ(激活感知权重量化) AWQ是一种针对大型语言模型(LLMs)的训练后量化(PTQ)方法,专注于4位仅权重量化,旨在最小化推理成本的同时保持模型精度。与量化感知训练(QAT)方法不同,AWQ无需反向传播或重新训练,因此适用于大型模型的扩展。这种技术特别适合像边缘设备这样资源受限的硬件,通过有策略地保护对精度至关重要的权重来实现高效推理。 #### AWQ的关键组件 1. **激活感知权重量化**:AWQ识别并保护每一层中最重要的权重,这些权重对于维持模型性能至关重要。通过关注与高激活特征对应的权重,AWQ最小化了可能导致显著精度下降的量化误差。权重$w$的量化函数$Q(w)$定义为: $$Q(w)=\text{clip}(\lfloor\frac{w}{\Delta}\rceil,\ -2^{N - 1},\ 2^{N - 1}-1)\times\Delta$$ 其中,$\Delta$是由权重的最大绝对值确定的量化尺度,$N$是比特精度(例如,4位量化时$N = 4$)。 2. **显著权重保护**:AWQ根据激活幅度对1%最重要的权重进行选择性缩放,而不是对所有权重进行统一量化。这种策略通过防止高影响力权重的退化,保留了大型语言模型中的关键知识。与可能对校准集过拟合的GPTQ不同,AWQ的激活感知方法避免了过拟合,使其在不同任务和数据集上具有通用性。对于显著权重,AWQ使用缩放量化方法: $$Q_{\text{salient}}(w)=s\times\text{clip}(\lfloor\frac{w}{\Delta}\rceil,\ -2^{N - 1},\ 2^{N - 1}-1)\times\Delta$$ 其中$s>1$是用于保护关键权重的缩放因子,$x$代表与权重相关的激活。这通过对激活进行反向缩放来减少最重要权重的量化误差。 3. **通过缩放最小化误差**:AWQ按通道调整重要权重的缩放因子,在不使用额外训练数据的情况下降低量化误差。通过逐通道缩放,AWQ对量化过程进行微调,平衡显著权重和非显著权重之间的误差,以最小化总体损失。这种方法显著降低了量化误差并提高了性能,特别是在低比特设置下,如4位甚至3位组量化设置。缩放后显著权重的误差可以表示为: $$\text{Error}_{\text{scaled}}=\sum_{i = 1}^{n}(w_i - Q_{\text{salient}}(w_i))^2$$ 其中,显著权重的相对误差被最小化,使AWQ在保持关键模型精度方面更加稳健。 4. **无数据优化**:与一些可能对特定校准分布过拟合的PTQ方法不同,AWQ不需要大型校准集。通过仅分析每个通道的平均激活幅度,AWQ保持了稳定性,并能更好地泛化到不同的数据分布,确保LLMs在不同任务和领域中保持广泛的泛化能力。每一层的最优缩放因子可以通过优化得到: $$L(s)$$ 其中$L(s)$是表示量化误差的目标函数,逐通道缩放用于根据输入激活幅度调整权重。 5. **层间灵活性**:AWQ可以根据模型推理路径中不同层的相对重要性,对不同层应用不同的量化尺度。这种层间灵活性使AWQ能够避免在关键层进行过于激进的量化,确保即使在激进量化的情况下,整体精度也能得到保留。 6. **部署优势**:AWQ能够在CPU和GPU硬件上高效部署高性能的4位量化模型,降低内存和计算需求。对于资源受限的边缘和移动环境中的LLMs来说,AWQ是理想选择,因为它在性能与低内存和计算开销之间取得了平衡。AWQ的选择性权重缩放方法实现的效果可与混合精度技术(例如,将1%的权重保持为FP16)相媲美,但对于低功耗部署来说,它对硬件更加友好。 ### B. 量化感知训练(QAT) 量化感知训练(QAT)是一种在量化过程中用于提高神经网络准确性的技术。与训练后量化(PTQ)不同,PTQ是在模型训练完成后进行量化,而QAT则将量化直接融入训练过程中。这种整合使模型能够适应量化带来的变化,从而获得更好的性能。 ![](https://upload-images.jianshu.io/upload_images/17294212-e661327cfee20ad9.png) #### QAT的工作原理 1. **伪量化**:在训练阶段,引入“伪”量化。这涉及将权重量化为较低精度(例如INT4),然后立即将它们反量化回浮点表示(例如FP32)。这使模型能够在仍以高精度进行训练的同时,模拟量化对权重的影响。 ![](https://upload-images.jianshu.io/upload_images/17294212-9898c26909d462d2.png) 2. **损失计算**:模型在损失计算过程中使用这些量化后的权重,从而了解量化如何影响输出。通过这样做,模型调整其权重更新,不仅最小化标准损失,还最小化潜在的量化误差。 3. **探索损失曲面**:QAT旨在在损失曲面中找到“宽”的最小值。宽最小值表示更稳定的解决方案,因为权重的小变化不会显著影响输出。相比之下,窄最小值可能会导致更大的量化误差,因为权重的小变化可能会导致模型性能的大幅波动。 4. **与PTQ的比较**:虽然PTQ在高精度(如FP32)下可能会产生较低的损失,但QAT在较低精度格式(如INT4)下实现较低的损失。这对于将以较低比特精度部署的模型是有益的,确保它们在量化后仍能保持性能。 #### 示例场景 假设有一个需要对图像进行分类的神经网络。在QAT过程中,如果模型学习到一个在FP32中能有效最小化损失,但在降低到INT4时会引入显著量化误差的权重,QAT会在整个训练过程中帮助调整该权重,以避免这个问题。这会产生一个即使在量化后也能有效运行的更新权重。 #### 损失曲面:“宽”与“窄”最小值 损失曲面代表了模型权重与损失函数之间的关系,在量化中起着关键作用。 1. **宽最小值**:损失曲面中的这些区域具有较浅的斜率,这意味着权重值的小变化(如量化引入的变化)只会导致损失的最小增加。宽最小值对量化更具弹性,从而产生较低的量化误差。 2. **窄最小值**:这些区域具有陡峭的斜率,即使是微小的权重变化也会导致损失的显著增加。窄最小值对量化更敏感,会导致更高的量化误差。 ![](https://upload-images.jianshu.io/upload_images/17294212-be4fcf4f5c7612ae.png) 量化感知训练(QAT)通过在反向传播过程中考虑量化效应,帮助模型找到这些宽最小值。相比之下,训练后量化(PTQ)在训练过程中不考虑量化,因此如果模型收敛在窄最小值处,可能会导致更高的量化误差。 ### BitNet:大语言模型1比特量化的时代 #### BitNet简介 超越常见的4比特量化,BitNet引入了极端量化,仅使用1比特值(即 -1和1)来表示权重。BitNet通过将量化直接集成到Transformer架构(大型语言模型(LLMs)的核心组件)中来实现这一点。这种方法显著降低了内存需求和计算开销,使得在资源受限的设备上大规模部署LLMs成为可能。 #### 标准Transformer架构 大多数LLMs都构建在Transformer架构之上,该架构在计算中严重依赖线性层。这些线性层通常以更高的精度(例如FP16)表示,模型的大部分权重都存在于此。BitNet对此进行了修改,引入了BitLinear层,用1比特值取代了FP16权重。 #### BitLinear层 BitLinear层的操作与传统线性层类似,但权重仅用1比特(-1或1)表示,激活值用INT8表示 。BitLinear在训练期间使用一种“伪”量化来评估权重和激活量化的效果,类似于量化感知训练(QAT)。 #### BitLinear组件分步解析 1. **权重量化**:在训练过程中,权重存储为INT8值,然后使用符号函数将其量化为1比特: 这个函数将权重分布移动到以零为中心,将零左侧的值赋值为 -1,右侧的值赋值为1。另外还会跟踪一个值β(权重的平均绝对值),稍后用于反量化。 ![](https://upload-images.jianshu.io/upload_images/17294212-30beef2ca1bfa5cf.png) 2. **激活量化**:BitLinear采用绝对最大(absmax)量化将FP16激活值转换为INT8,这确保了激活值在矩阵乘法中具有更高的精度。BitLinear还记录激活值的最高绝对值α,用于反量化步骤。 3. **反量化**:使用α和β,BitNet通过以下缩放因子将激活值反量化回FP16: 这一步将值重新调整回其原始比例,在保持计算效率的同时,实现更准确的激活值。 #### BitNet向1.58比特量化的转变 虽然最初的BitNet量化仅对权重使用 -1和1,但BitNet 1.58b版本引入了三进制表示:-1、0和1。这个小小的增加(允许权重也取0值)在计算效率方面带来了显著的改进。 #### 1.58比特量化中添加零的好处 1. **简化矩阵乘法**:在典型的矩阵乘法中,每个权重都与一个输入相乘,然后将结果相加。在1.58比特量化中,矩阵乘法中的权重可以表示特定的操作: - 1:加上相应的值 - 忽略该值 - -1:减去相应的值 通过消除不必要的乘法,三进制权重显著加快了计算速度,并实现了更高效的特征过滤。 2. **量化策略:绝对均值量化**:BitNet 1.58b使用绝对均值量化(absmax的一种变体),将权重分布压缩在绝对均值(α)附近,然后将权重量化为 -1、0或1: 与absmax不同,绝对均值量化确保在量化之前压缩权重分布,通过减少量化误差来提高性能。 #### 关键要点 1. **1比特量化**:BitNet的原始方法将权重简化为 -1和1,在内存使用和计算能力方面实现了高效的LLMs。 2. **带三进制权重的1.58比特量化**:BitNet 1.58b中零的加入使计算速度更快,因为模型可以完全跳过某些操作。 3. **缩放优势**:BitNet的效率随着模型规模的增长而提高,较大的模型(例如,超过300亿个参数)在1比特和FP16量化之间的性能差距更小。 这种新颖的方法使BitNet能够提供轻量级、延迟优化的LLMs。据作者称,一个130亿参数的1.58比特精度的BitNet模型在延迟、内存和能耗方面,比一个小得多的30亿参数的FP16模型更高效。 ## 本系列文章 >[1. LLM大模型架构专栏|| 从NLP基础谈起](https://mp.weixin.qq.com/s/MYx5V29WczQzxPybKBbT7Q?token=516670980&lang=zh_CN) [2.LLM大模型架构专栏|| 自然语言处理(NLP)之建模](https://mp.weixin.qq.com/s/Vdk4cmWSnyRhO9MHSotWFQ?token=516670980&lang=zh_CN) [3. LLM大模型架构之词嵌入(Part1)](https://mp.weixin.qq.com/s/V79xObji_6NHt7_CFOtT5A?token=516670980&lang=zh_CN) [4. LLM大模型架构之词嵌入(Part2)](https://mp.weixin.qq.com/s/FqHQN-SqKk2RPhh5CmPKBA?token=516670980&lang=zh_CN) [5. LLM大模型架构之词嵌入(Part3)](https://mp.weixin.qq.com/s/VAkj3UNEcxN3kMXN7xwnYQ?token=1160071256&lang=zh_CN) [6. LLM架构从基础到精通之循环神经网络(RNN)](https://mp.weixin.qq.com/s/AkQ9ZMmG5-ypY0fd-jEdPg?token=1869920405&lang=zh_CN) [7. LLM架构从基础到精通之LSTM](https://mp.weixin.qq.com/s/TkE9dF_4J7e6l1HMYjC0TQ?token=1869920405&lang=zh_CN) [8. LLM架构从基础到精通之门控循环单元(GRUs)](https://mp.weixin.qq.com/s/lfo9rLgvIBV-hjcv7lL0JQ?token=458235218&lang=zh_CN) [9. 20000字的注意力机制讲解,全网最全](https://mp.weixin.qq.com/s/zmHyJPVSZA2UcKBTbkpY9g?token=458235218&lang=zh_CN) [10. 深入探究编码器 - 解码器架构:从RNN到Transformer的自然语言处理模型](https://mp.weixin.qq.com/s/ou647Jo8RD6xb7EAoB-aIw?token=458235218&lang=zh_CN) [11. 2w8000字深度解析从RNN到Transformer:构建NLP应用的架构演进之路](https://mp.weixin.qq.com/s/9fSaTfrex01GmSfdy9v5_A?token=458235218&lang=zh_CN) 欢迎关注公众号 **柏企科技圈** 与**柏企阅文** 如果您有任何问题或建议,欢迎在评论区留言交流! 本文由[mdnice](https://mdnice.com/?platform=6)多平台发布
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,928评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,748评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,282评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,065评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,101评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,855评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,521评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,414评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,931评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,053评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,191评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,873评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,529评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,074评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,188评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,491评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,173评论 2 357

推荐阅读更多精彩内容