人工智能学习

小规模语言模型的量化技术及混合模式应用

本文主要是介绍小规模语言模型的量化技术及混合模式应用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

这是阿德里安·萨德与埃里克·索里亚诺两位写的

大型语言模型(LLM)在许多行业中具有越来越重要的作用,但其庞大的规模——以一些最知名的例子为例,参数量从数百亿到数万亿——使得大多数公司无法在其本地IT基础设施内以成本效益的方式部署这些模型。许多公司正在积极开发小型语言模型(SLM),以满足更具体的需求。SLM专注于特定领域的知识,而不是试图捕获所有人类知识,从而保持了它们在商业应用中的价值,同时大大降低了计算、存储、能源和碳排放的需求。

除了减小模型的规模之外,还有其他各种技术可以使商用应用更具实际性。一些技术专注于使SLM架构更高效,还有些技术则侧重于硬件优化。

量化是一种已经被广泛研究的技术。尽管它仍然是一个活跃的研究领域,但已经实现了高精度的同时大幅减少内存需求和推理时间,并且已经在工业界得到了广泛的应用和测试。

这样的行为是由输出的每个词背后的数十亿的参数和数万亿次的计算所促成的。一个主要问题是将所有这些参数映射至内存系统的最高效区域。这就是量化技术发挥作用的地方。

量化减少了参数和计算的精度,但保持了足够的准确性,确保模型可以产生有用的结果。它使我们能够将相同的数据存储在更小的存储空间中。通常,量化会将浮点数映射到使用较少位的整数。

了解量化

我们先来了解一下量化是什么以及它是如何工作的。首先,我们需要快速回顾一下SLM是如何工作的。当有人用自然语言向AI模型提问时,这个问题会被转换成数字并输入模型中,模型会对这些数字进行一系列计算,然后输出另一组数字,这些数字再被转换回自然语言。如果模型被正确设计和训练,它应该会给出一个有用的回答。

这种行为是由输出每个词所需的数十亿个参数和数万亿次的计算所驱动的。一个主要问题是如何把这些参数有效地分配到内存系统的高效区域。这时,量化就起作用了。

量化减少了参数和计算的精度,从而保留了足够的准确性,确保模型可以产生有用的结果。使我们能在更小的内存空间中存储同样的数值。通常,量化会将一个浮点数映射成一个整数,使用较少的位数来存储。

图1:各种数据类型所用的位

量化可以应用于SLM(某种技术的简称)管道的不同环节。在这篇文章中,我们主要讨论最常用的一种量化权重的方法,这些权重是用来衡量每个参数在模型最终输出中重要程度的系数。在进行计算前,我们会先将权重去量化以提高计算精度,计算完成后,再重新量化。

图2:量化和去量化的例子。需要注意的是,通常会有一些误差被引入。来源:https://huggingface.co/blog/hf-bitsandbytes-integration

这个去量化和再量化过程会带来一些开销,但大多数框架主要受限于内存而不是计算。换句话说,是数字在不同内存位置间移动,而不是数学运算,影响了模型的整体性能。与通过增加带宽(即每秒传输的权重数量)获得的收益相比,这种开销显得很小。

量化可以即使精度从16位浮点数降低到8位、6位、4位,甚至有时降到2位整数表示时仍然保持有用的精度。因此,你可以有效地将模型的大小减少到原来的1/2到1/8。需要注意的是,由于这些整数表示的动态范围较小,通常无法使用它们进行训练(梯度计算会失效),因此,量化主要用于推理阶段。

一个常用的方法列表

量化的基本思想可以总结为将浮点数空间映射到n位整数空间。最简单的方法是在调整权重后使用四舍五入函数——对于比如一组参数X,这会是这样的形式。

这是一个用于计算Q(X)的公式,它首先计算了2的(n-1)次方减1的值,然后乘以X,最后除以X的绝对值最大值。

Q(X) = RTN((2**(n-1) - 1) * X / absmax(X))

其中n是...,absmax(X)表示X的绝对值最大值。

其中 RTN 是最近舍入函数,其中 n 表示选择的位数。其他方法根据张量的统计信息以不同的方式对权重进行量化(例如零点量化法)。

然而,这些基于统计的方法往往会累积量化误差(与原始浮点参数的差异),导致不良输出结果。为了对抗这个问题,开发出了更复杂的算法来解决这个问题,通常基于最小化这种误差的优化方法,并包括少量的训练或校准数据。下面我们将介绍一些常用量化框架。

BitsAndBytes 4位精度(低位增强版LoRA)

BitsAndBytes 的 4 位量化实现了 QLoRA 论文在 2023 年 5 月提出的方法。这种方法借鉴了分位数量化,以权重分布为基础将权重划分为相同大小的集合。每个权重都与其集合的索引关联起来。QLoRA 的作者进一步假设在 SLM 中,权重大致呈正态分布,这使得它们可以被有效量化。这种数据类型包含 16 个值,这些值代表正态分布的 1/16 分位数。

在这个量化过程中,既没有校准也没有训练,权重只是简单地映射到这些值上,因此这种量化过程非常快。此外,该算法已完全集成到广受好评的开源框架HuggingFace中——开发人员只需用transformers库中的几行代码就能对任何SLM进行量化,因此这种方法非常受欢迎。

从transformers库导入AutoModelForCausalLM模型  
model = AutoModelForCausalLM.from_pretrained('mistralai/Mistral-7B-v0.3', load_in_4bit=True, device='cuda')
GPTQ模型

GPTQ方法在2022年底被提出,它为量化SLM权重提出了一种更先进和更复杂的算法。该方法基于优化,力求减少量化误差:

argmin_W̃ (||WX - W̃X||)

寻找W̃ 使得||WX - W̃X||最小

解释:找到W̃使得||WX - W̃X||最小。

其中 W 是权重集合,$\hat{W}$(量化后的权重),X 是输入,$||.||$ 是范数度量。这一过程逐层进行,确保模型的整体性能得以保留,并通过海森矩阵计算来指导优化。一个重要的发现是,对于大型模型而言,权重的量化顺序并不重要,这使得 GPTQ 可以将权重分块处理,大大加快了处理速度。此外,GPTQ 采用称为 Cholesky 分解的技术来处理数值不准确性,使其即使在参数量达到数十亿的模型中也能保持稳定。

GPTQ 可以非常有效地将模型量化到 4 比特:在 1xA100 设备上,将一个 7B 模型量化到 INT4 只需要不到半小时。另一个好处是,它在优化量化误差的同时,不作任何关于量化网格的假设,因此量化网格可以以任何最优的方式进行选择。需要注意的是,该方法需要少量的训练数据来执行优化(上面的“X”),而且所需的数据量非常少(几百个例子就足够了),对于基础模型来说,任何预训练数据都适用(如 RedPajama-2、The Pile、C4 等)。

AWQ

AWQ(激活感知的权重量化)源自2023年中期,提出了一种新的量化方法。作者发现,网络中的所有权重并非同等重要,量化通常对所有权重进行相同的转换,使一些量化误差比其他误差更突出。为了应对这一问题,他们建议保护负责异常激活的权重(他们称之为“显著”权重)。如果他们最初考虑过将这些权重保持在更高精度,很快就放弃了这个想法,因为这会引入混合精度矩阵乘法的低级别硬件复杂性问题。相反,他们决定通过在量化前按因子s缩放显著权重(量化后还原缩放),来保护这些权重。这一技巧将量化误差减少了因子s,成功限制了对显著权重的误差。

图3:_AWQ缩放法。来自:https://arxiv.org/pdf/2306.00978

该算法利用一个小的校准数据集(来自预训练数据集的几百个样本)来识别重要的权重,并为每个量化块选择最优的s因子(通过解决一个最小化问题来完成)。重要权重的数量是一个需要选定的超参数(通常在0.1%到1%范围内)。

AWQ 在 INT4 量化方面提供了出色的结果,并且可以进一步拓展。它也相对较快,只需不到半小时就能用单个 A100 GPU 将一个 7B 模型量化为 INT4。此外,我们并没有定义任何特定的量化方案,即 AWQ 实际上是一个量化的附加组件,可以与任何实际的量化方法结合使用,比如与 GPTQ 结合使用时,它可以有效地将模型量化到 2 位。

GGUF (llama.cpp)

GGUF 量化格式起源于开源项目 llama.cpp,该项目是一个用纯 C++ 编写的 GitHub 仓库。该项目旨在高效地在 CPU 上本地运行 SLM。现在它还支持 GPU,并集成了各种前沿技术,使其运行速度非常快且内存使用效率高。尤其是,GGUF 格式支持将任何 SLM 量化为较低的位深度。

尽管很难详尽列出他们的技巧和量化技术(遗憾的是这方面的文档不够充分),我们仍然可以指出他们提供了多种量化精度(8位、6位、4位、2位,甚至连续插值)。我们注意到他们的全局量化流程非常复杂,并采用了多种优化策略,特别是可以提到两种非常有用的技巧:在整个网络中,某些核心层故意保持在较高精度,以维持较高准确性,而且他们使用校准数据集来尽量减少量化误差,就像前述方法一样。

llama.cpp 框架使得任何拥有强大 CPU 的人都能轻松访问和可靠使用 SLM,这也正是它在社区中广受欢迎的原因。

一评估

在埃斯珀朗托,我们决定自行评估上述方法,以创建我们自己的管道并选择最高效的框架。我们选择了 Mistral-7B-Instruct-v0.2(最著名且准确的 SLM 之一)进行了实验。我们在 Wikitext-2 的子集上评估了困惑度,这个数值越低越好。实验是在配备 1xA100 80GB HBM 的环境下进行的。

请注意,所有方法都有其特定性和超参数,可以调整以达到最优结果。这里展示了我们获得的最优结果,并提到了所使用的参数——但请记住,进一步调整后,这些结果可能还会有所提升。

图4:世界语评价

我们的基准测试引导我们选择了AWQ量化,主要用于ET-SoC-1的集成工作,因为它的准确度最高,并且它提供了一个易于使用、灵活且直接与transformers库集成的框架。值得一提的是,GGUF提供了最佳的原始性能,但其文档不清晰和与其它开源框架(如transformers)集成较弱,这使得它很难使用。

将模型转换为ONNX格式以与ET-SoC-1集成

让我们来总结一下量化的优点:

如前所述,大型语言模型(LLM)是高度依赖内存的问题,这意味着在进行推理时,更多的时间和能量被用来移动数据(特别是权重)到计算结果的位置,而不是实际的计算上。量化因此变得很有意义,因为如果我们将权重量化到int4,例如,相对于fp16表示,内存占用减少到四分之一,数据移动也会相应减少。

当然这会带来一些成本:首先,会增加计算时间,因为我们现在的权重需要在进行实际计算前转换回 fp16 精度(半精度浮点数);其次是由于权重精度的损失,模型的准确性会受到影响。

幸运的是,执行这些转换并不会降低推理速度,因为我们仍然受内存限制的影响。因此,总体而言,推理速度更快。第二个问题可以通过采用先进的量化技术来缓解,这些技术专门用于减少大型语言模型中的精度损失。

正如我们之前提到的,我们在Esperanto上专注于AWQ方法(尽管这个流程也已被用于GPTQ的测试)。首先,我们需要一个已经用AWQ量化过的模型,例如可以在Hugging Face上找到的那些(比如The Bloke或TechxGenus),或者我们可以自己量化一个fp16模型,这要感谢AutoAWQ包(该包是AutoGPTQ包的一部分)。

一旦模型被量化,我们就可以将其转换成ONNX格式。通常我们会使用一个名为QLLM的外部工具来自动进行模型的转换和测试。

这个模型的格式并不是我们想要的(我们对用于ONNX的模型而言),所以我们采用与fp16模型相同的优化措施(在这篇博客文章中有详细描述如下)。

  • 添加键值缓存
  • 调整旋转嵌入
  • 添加上下文以扩展我们生成的 token 范围
  • 等等。
结尾

量化是一种非常有用的方法,可以利用大规模语言模型的记忆限制特性来加速推断过程。通过使用这些复杂的量化技术,如GPTQ、AWQ或GGUF,可以减少量化的误差。

在Esperanto,我们特别感兴趣于AWQ技术,并以支持这些量化后的SLM,我们已将它们转换为ONNX,在我们ET-SoC-1芯片上运行了各种这些模型。通过AWQ方法,Esperanto已将基础SLM转换为int4精度的ONNX模型,这些转换后的模型可以在我们HuggingFace页面上找到。

参考资料

LLM.int8(): https://arxiv.org/pdf/2208.07339 请注意,LLM.int8() 是一个特定的技术术语或操作,具体含义可能需要参照相关文献或上下文进一步了解。

QLoRA: 你可以在这里查看论文 https://arxiv.org/pdf/2305.14314

GPTQ: https://arxiv.org/pdf/2210.17323 (GPTQ论文)

AWQ: https://arxiv.org/pdf/2306.00978 (这是一个相关的研究链接)

llama.cpp: GitHub — ggerganov/llama.cpp: C/C++ 大型语言模型的推理

这篇关于小规模语言模型的量化技术及混合模式应用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!