LLM大模型4位量化实战【GPTQ】

权重量化方面的最新进展使我们能够在消费类硬件上运行大量大型语言模型,例如RTX3090GPU上的LLaMA-30B模型。这要归功于性能下降最小的新型4位量化技术,例如GPTQ、GGML和NF4。

在上一篇文章中,我们介绍了简单的8位量化技术和出色的()。在本文中,我们将探索流行的GPTQ算法,以了解其工作原理并使用AutoGPTQ库实现它。

你可以在GoogleColab和GitHub上找到代码。

1、最优大脑量化

让我们首先介绍我们要解决的问题。对于网络中的每一层ℓ,我们希望找到原始权重Wₗ的量化版本Ŵₗ。这称为分层压缩问题。更具体地说,为了最大限度地减少性能下降,我们希望这些新权重的输出(ŴᵨXᵨ)尽可能接近原始权重(WᵨXᵨ)。换句话说,我们想要找到:

人们提出了不同的方法来解决这个问题,但我们对这里的最优大脑量化器(OBQ:OptimalBrainQuantizer)框架感兴趣。

该方法的灵感来自于一种修剪(pruning)技术,该技术可以仔细地从经过充分训练的密集神经网络(最佳脑外科医生)中去除权重。它使用近似技术,并为要删除的最佳单个权重w和最佳更新δ提供显式公式,以调整剩余非量化权重F的集合以弥补删除:

其中quant(w)是量化给出的权重舍入,H是Hessian矩阵。

使用OBQ,我们可以首先量化最简单的权重,然后调整所有剩余的非量化权重以补偿这种精度损失。然后我们选择下一个要量化的权重,依此类推。

这种方法的一个潜在问题是当存在异常权重时,这可能会导致高量化误差。通常,当剩下很少的非量化权重可以调整以补偿大误差时,这些离群值将最后被量化。当一些权重因中间更新而被进一步推到网格之外时,这种效果可能会恶化。应用一个简单的启发式方法来防止这种情况:异常值一出现就被量化。

这个过程的计算量可能很大,尤其是对于KKM而言。为了解决这个问题,OBQ方法使用了一种技巧,可以避免每次简化权重时都重新进行整个计算。量化权重后,它通过删除与该权重关联的行和列(使用高斯消除)来调整计算中使用的矩阵(Hessian):

该方法还采用矢量化来一次处理多行权重矩阵。尽管其效率很高,但OBQ的计算时间随着权重矩阵大小的增加而显着增加。这种立方增长使得在具有数十亿参数的大型模型上使用OBQ变得困难。

2、GPTQ算法

由Frantar等人提出,GPTQ算法从OBQ方法中汲取灵感,但进行了重大改进,以将其扩展到(非常)大型语言模型。

第1步:任意排序洞察

OBQ方法按一定的顺序选择权重(模型中的参数)进行量化,所确定的权重将增加最少的附加误差。然而,GPTQ观察到,对于大型模型,以任何固定顺序量化权重都可以获得同样的效果。这是因为,即使某些权重可能会单独引入更多误差,但它们会在过程中稍后进行量化,因为此时几乎没有其他权重可能会增加误差。所以顺序并不像我们想象的那么重要。

基于这一见解,GPTQ旨在以相同的顺序量化矩阵所有行的所有权重。这使得过程更快,因为某些计算只需为每列执行一次,而不是为每个权重执行一次。

第2步:惰性批量更新

该方案不会很快,因为它需要更新一个巨大的矩阵,并且每个条目的计算量很少。此类操作无法充分利用GPU的计算能力,并且会因内存限制(内存吞吐量瓶颈)而减慢速度。

为了解决这个问题,GPTQ引入了“惰性批量”更新。事实证明,给定列的最终舍入决策仅受对该列执行的更新的影响,而不受后续列上执行的更新的影响。因此,GPTQ可以一次将该算法应用于一批列(例如128列),仅更新这些列和矩阵的相应块。完全处理一个块后,算法对整个矩阵执行全局更新。

步骤3:Cholesky重构

然而,还有一个问题需要解决。当算法扩展到非常大的模型时,数值不准确可能会成为一个问题。具体来说,重复应用某个运算可能会累积数值误差。

为了解决这个问题,GPTQ使用Cholesky分解,这是一种用于解决某些数学问题的数值稳定方法。它涉及使用Cholesky方法从矩阵中预先计算一些所需的信息。这种方法与轻微的“阻尼”(向矩阵的对角元素添加一个小常数)相结合,有助于算法避免数值问题。

完整的算法可以概括为以下几个步骤:

GPTQ算法从Hessian逆矩阵(帮助决定如何调整权重的矩阵)的Cholesky分解开始

然后它循环运行,一次处理一批列。

对于批次中的每一列,它都会量化权重,计算误差,并相应地更新块中的权重。

处理完该批次后,它会根据块的错误更新所有剩余的权重。

GPTQ算法在各种语言生成任务上进行了测试。它与其他量化方法进行了比较,例如将所有权重四舍五入到最接近的量化值(RTN)。GPTQ与BLOOM(176B参数)和OPT(175B参数)模型系列一起使用,并使用单个NVIDIAA100GPU对模型进行量化。

3、使用AutoGPTQ量化LLM

GPTQ在创建可在GPU上高效运行的4位精度模型方面非常流行。你可以在HuggingFaceHub上找到许多示例,尤其是来自TheBloke的示例。如果你正在寻找一种对CPU更友好的方法,GGML目前是你的最佳选择。最后,带有bitsandbytes的Transformer库允许你在使用load_in_4bit=true参数加载模型时对其进行量化,这需要下载完整模型并将其存储在RAM中。

让我们使用AutoGPTQ库实现GPTQ算法并量化GPT-2模型。这需要GPU,但GoogleColab上的免费T4就可以了。我们首先加载库并定义我们想要量化的模型(在本例中为GPT-2)。

!BUILD_CUDA_EXT=0pipinstall-qauto-gptqtransformers
importrandomfromauto_gptqimportAutoGPTQForCausalLM,BaseQuantizeConfigfromdatasetsimportload_datasetimporttorchfromtransformersimportAutoTokenizerLoadquantizeconfig,modelandtokenizerquantize_config=BaseQuantizeConfig(bits=4,group_size=128,damp_percent=0.01,desc_act=False,)model=_pretrained(model_id,quantize_config)tokenizer=_pretrained(model_id)

量化过程很大程度上依赖于样本来评估和提高量化质量。它们提供了一种比较原始模型和新量化模型产生的输出的方法。提供的样本数量越多,进行更准确和有效比较的潜力就越大,从而提高量化质量。

在本文中,我们利用C4(ColossalCleanCrawledCorpus)数据集来生成样本。C4数据集是从CommonCrawl项目收集的大规模、多语言的网络文本集合。这个庞大的数据集经过专门清理和准备,用于训练大规模语言模型,使其成为此类任务的重要资源。维基文本数据集是另一个流行的选择。

在下面的代码块中,我们从C4数据集中加载1024个样本,对它们进行标记并格式化。

Formattokenizedexamplesexamples_ids=[]for_inrange(n_samples):i=(0,tokenized__[1]-_max_length-1)j=i+_max_lengthinput_ids=tokenized__ids[:,i:j]attention_mask=_like(input_ids)examples_({'input_ids':input_ids,'attention_mask':attention_mask})

现在数据集已准备就绪,我们可以开始批大小为1的量化过程。我们还可以选择使用OpenAITriton(CUDA的替代方案)与GPU进行通信。完成此操作后,我们将分词器和模型保存为安全张量格式。

_quantized(out_dir,use_safetensors=True)_pretrained(out_dir)

像往常一样,然后可以使用AutoGPTQForCausalLM和AutoTokenizer类从输出目录加载模型和标记生成器。

device="cuda:0"_available()else"cpu"#Reloadmodelandtokenizermodel=_quantized(out_dir,device=device,use_triton=True,use_safetensors=True,)tokenizer=_pretrained(out_dir)

让我们检查一下模型是否正常工作。AutoGPTQ模型(大部分)作为普通transformer模型工作,这使得它与推理管道兼容,如以下示例所示:

fromtransformersimportpipelinegenerator=pipeline('text-generation',model=model,tokenizer=tokenizer)result=generator("Ihaveadream",do_sample=True,max_length=50)[0]['generated_text']print(result)
Ihaveadream,"shetoldCNNlastweek.",totellthatforthefirsttime,nowthatI'mseeingmymothernow,justknowinghowwonderfulitisthat

我们成功地从量化的GPT-2模型中获得了令人信服的完成结果。更深入的评估需要测量量化模型与原始模型的复杂度。但是,我们将其排除在本文的讨论范围之外。

4、结束语

在本文中,我们介绍了GPTQ算法,这是一种在消费级硬件上运行LLM的最先进的量化技术。我们展示了它如何基于具有任意顺序洞察、惰性批量更新和Cholesky重构的改进OBS技术来解决分层压缩问题。这种新颖的方法显着降低了内存和计算需求,使LLM可供更广泛的受众使用。

此外,我们在免费的T4GPU上量化了我们自己的LLM模型,并运行它来生成文本。你可以在HuggingFaceHub上推送自己的GPTQ4位量化模型版本。正如简介中提到的,GPTQ并不是唯一的4位量化算法:GGML和NF4都是优秀的替代方案,但范围略有不同。我鼓励你更多地了解它们并尝试一下!

原文链接:GPTQ4位量化实战-BimAnt

发布于 2025-06-05
138
目录

    推荐阅读