AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


手把手GPTQ量化llama3大模型!有什么区别?优势在哪?跑起来,附代码!day4
发布日期:2024-05-11 07:27:06 浏览次数: 2366


hi~

上一篇,跟着雄哥做了int8量化!

今天,我们继续用GPTQ来做4位量化!后面,跟着雄哥再用GGML、EXL2技术量化大模型!

也得因为量化技术发展,大模型的部署成本,有望降低!

雄哥在公园,整理了几个热门量化工具的代码,全免费资源,在colab/阿里云上,全部跑通,整个内容是这样的!

day3:手把手量化大模型!有什么方法?什么是量化?【点击学习】

day4:手把手GPTQ量化大模型!有什么区别?优势?【本篇】

day5:手把手GGML量化大模型!与llama.cpp异曲同工?

day6:手把手使用ExLlamaV2量化!精炼后的GPTQ?

如果你跟着雄哥之前的教程,抢到了阿里云的免费算力,可以用医疗组伙伴共享的方法,改为国内源下载并量化模型!非常棒!

import os
# 设置环境变量HF_ENDPOINTos.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'

人的专注力只有10分钟,那!话不多说!

① 量化技术的困难背景!

② 什么是GPTQ量化?背后算法是?

③ 动起手来,跑一个实例!边跑边聊细节!


第一部分:量化技术的困难背景!


说到量化,不得不说一直以来“修剪”的技术,稍后你可以去看一下!

https://arxiv.org/abs/2208.11580

最佳脑压缩:用于准确训练后量化和修剪的框架

埃利亚斯·弗兰塔尔、西达克·帕尔·辛格、丹·阿里斯塔

我们考虑了深度神经网络 (DNN) 在具有挑战性的单次/训练后环境中的模型压缩问题,在这种环境中,我们得到了一个精确的训练模型,并且必须仅基于少量校准输入数据进行压缩,而无需任何重新训练。鉴于新兴的软件和硬件支持通过修剪和/或加速量化来执行压缩的模型,这个问题已经变得流行,并且已经为这两种压缩方法独立提出了性能良好的解决方案。在本文中,我们引入了一种新的压缩框架,该框架在统一的设置中涵盖了权重修剪和量化,既省时又省空间,并大大提高了现有训练后方法的实际性能。在技术层面上,我们的方法基于经典最佳脑外科医生 (OBS) 框架的精确和有效实现 [LeCun, Denker, and Solla, 1990] 扩展到也涵盖了现代 DNN 规模的权重量化。从实践的角度来看,我们的实验结果表明,它可以显著提高现有训练后方法的压缩精度权衡,并且能够在训练后环境中实现修剪和量化的准确复合应用。

方法灵感来自修剪技术,从经过充分训练的密集神经网络(Optimal Brain Surgeon)中去除权重!

使用近似技术,为要删除的最佳单个权重w_q和最佳更新提供明确的公式,以调整剩余的非量化权重 F 集以弥补删除:

定义一个与该优化过程相关的变量:

使用 OBQ,我们可以先简单量化权重,有损失!

然后,调整所有剩余的非量化权重,来补偿精度损失!

然后,我们选择下一个权重进行量化,依此类推!

发现没?

这种方法的一个潜在问题是:当存在异常值权重时,有超高量化误差!

通常,这些异常值将最后量化,此时几乎没有剩余的非量化权重可以调整以补偿大误差。

当一些权重被中间更新推到网格之外时,这种影响可能会恶化。应用了一个简单的启发式方法来防止这种情况:异常值一出现就被量化。

这个过程的计算量可能很大!

为了解决这个问题,OBQ 方法使用了一个技巧,可以避免每次简化权重时重做整个计算。量化权重后,它通过删除与该权重关联的行和列(使用高斯消元法)来调整计算中使用的矩阵(Hessian):

公众号的文稿格式很差,我让最新千问2.5来生成!

该方法,采用矢量化来一次处理权重矩阵的多行!效率很高,但权重矩阵增加后,OBQ 的计算时间也直接起飞!

OBQ,不适合现在千亿参数的超大型模型上!


第二部分:什么是GPTQ?底层算法?


GPTQ 算法由 Frantar 等人 (2023) 引入,灵感来自 OBQ 方法,重写!把他扩展到超大参数语言模型上!论文在这,之后可以自己去看!

https://arxiv.org/abs/2210.17323

他是这样做的!

步骤 1:任意顺序的洞察

OBQ 方法按照特定顺序选择权重(模型中的参数)进行量化,顺序取决于哪些权重会增加最少的额外误差!

然而,GPTQ 发现对于大型模型而言,以任何固定的顺序量化权重都能表现出色!

因为尽管某些权重单独来看可能会引入更多误差,但在量化过程后期,当剩余可增加误差的权重不多时,这些权重才会被量化。因此,顺序的重要性并不像我们原先想象的那么大。

基于这一洞察,GPTQ 旨在对矩阵的所有行按照相同的顺序量化所有权重。这样做能够加快处理速度,因为某些计算只需为每一列执行一次,而不是为每个权重单独执行一次!

步骤 2:惰性批次更新

此方案不会很快,因为它要求用极少的计算来更新一个巨大的矩阵中的每个条目。这类操作无法充分利用GPU的全部计算能力,并且会受到内存限制(内存吞吐量瓶颈)的影响而减速。

为解决问题,GPTQ 引入了“惰性批次”更新的概念!给定列的最终舍入决策仅受该列上执行的更新影响,而不受后续列的影响。

因此,GPTQ 可以一次对一批列(比如128列)应用算法,仅更新这些列以及矩阵中的相应块。在处理完一个块后,算法再对整个矩阵执行全局更新。

这种方法提高效率,减少了内存访问频率,通过批量处理列来更有效地利用GPU的并行计算能力,减少全局更新次数来减轻内存带宽瓶颈!

步骤 3:Cholesky 重述

当算法扩展到超大模型时,数值不精确性,成为问题!具体来说,重复应用某个特定操作可能会累积数值误差!

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

完整的算法是这样的:

1. **Cholesky 分解开始**:GPTQ 算法首先对 Hessian 逆矩阵(一个帮助决定如何调整权重的矩阵)进行 Cholesky 分解。

2. **循环处理**:然后,它以循环的方式运行,每次处理一批列。

3. **按批次处理列**:对于批次中的每一列,它量化权重,计算误差,并相应地更新块中的权重。

4. **基于块错误更新**:处理完批次后,根据该块的误差更新所有剩余的权重。

**GPTQ 算法测试**:

GPTQ 算法在多种语言生成任务上进行了测试。与其他量化方法比较,如将所有权重四舍五入到最近的量化值(RTN)。GPTQ 与 BLOOM(1760亿参数)和 OPT(1750亿参数)模型系列一起使用,并且模型使用单个 NVIDIA A100 GPU 进行量化。GPTQ 在保持模型性能的同时显著降低内存花销的!


第三部分:跑起来!边跑边聊细节!


所有的代码,雄哥都上传到会员盘了!仅意友圈成员专享!目前420+付费成员!

获取知识星球优惠,或遇到问题需解答!或加群?末尾找技术助手小胖!

如果你还未加入,在这里备注申请!

一样!你打开雄哥上传的代码,无论在本地、阿里云、colab均可!

推荐colab,免费,无需理会环境!

GPTQ技术很火!可以在Hugging Face找到许多示例!

如果你用纯CPU,GGML是最适合的,下篇雄哥就更新!

上传好之后,开始跑!

定义模型!

只要你有足够资源,你可以改任何模型,你只需要把下方的model_id后的模型名称改为hf上的模型路径!

import random
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfigfrom datasets import load_datasetimport torchfrom transformers import AutoTokenizer
model_id = "gpt2"out_dir = model_id + "-GPTQ"

把上方的路径换进去!例如你要量化llama3!

model_id = "meta-llama/Meta-Llama-3-8B"

他会自动去hf下载模型!

加载模型和分词器!

quantize_config = BaseQuantizeConfig(    bits=4,    group_size=128,    damp_percent=0.01,    desc_act=False,)model = AutoGPTQForCausalLM.from_pretrained(model_id, quantize_config)tokenizer = AutoTokenizer.from_pretrained(model_id)

分词器是使用库中的经典类加载的。另一方面,我们需要传递一个特定的配置来加载模型

此配置,我们指定要量化的位数和组大小(惰性批处理的大小)!

注意,此组大小是可选的:我们还可以对整个权重矩阵使用一组参数。在实践中,这些组通常以非常低的成本(尤其是 )提高量化的质量。该值在这里帮助 Cholesky 重新制定,不要更改!

加载数据!

n_samples = 1024data = load_dataset("allenai/c4", data_files="en/c4-train.00001-of-01024.json.gz", split=f"train[:{n_samples*5}]")tokenized_data = tokenizer("\n\n".join(data['text']), return_tensors='pt')
examples_ids = []for _ in range(n_samples): i = random.randint(0, tokenized_data.input_ids.shape[1] - tokenizer.model_max_length - 1) j = i + tokenizer.model_max_length input_ids = tokenized_data.input_ids[:, i:j] attention_mask = torch.ones_like(input_ids) examples_ids.append({'input_ids': input_ids, 'attention_mask': attention_mask})

这段代码执行以下任务:

1. **数据加载**:首先,它设置了`n_samples = 1024`,指定了要处理的数据样本数量。然后使用`load_dataset`函数从AllenAI的C4数据集中加载数据。具体加载的是英文数据部分("en/c4-train.00001-of-01024.json.gz"),并限制加载的数据范围为前`n_samples * 5`个样本作为训练数据。

2. **文本预处理**:加载的数据通过一个名为`tokenizer`的函数进行预处理,该函数将文本数据转换成模型可以理解的token(词或子词)形式。这里,所有文本样本通过`\n\n`连接起来作为一个长字符串传递给tokenizer,并要求返回的张量格式为'pt'(PyTorch张量)。

3. **生成示例**:之后,代码进入一个循环,目的是从tokenized的数据中创建用于模型输入的示例。对于每个样本(总共`n_samples`个):

   - 随机选择一个起始点`i`,确保在选取的序列长度(`tokenizer.model_max_length`)不会超出tokenized数据的最大边界。

   - 计算结束点`j`,等于`i`加上模型允许的最大长度。

   - 从`tokenized_data.input_ids`中提取从`i`到`j`的序列,作为模型的`input_ids`。

   - 创建一个与`input_ids`形状相同的全1张量`attention_mask`,用于指示模型哪些token应当被关注(在Transformer模型中用于处理序列中的padding部分)。

   - 将`input_ids`和`attention_mask`作为字典添加到`examples_ids`列表中,形成最终的训练示例。

开始量化!

%%time
model.quantize( examples_ids, batch_size=1, use_triton=True,)
model.save_quantized(out_dir, use_safetensors=True)tokenizer.save_pretrained(out_dir)

搞好了,你可以下载到本地!

在本文中,雄哥介绍了 GPTQ 算法,这是一种最先进的量化技术,用于在消费级硬件上运行 LLM。

我们展示它如何解决逐层压缩问题,该技术基于改进的 OBS 技术,具有任意顺序洞察、延迟批处理更新和 Cholesky 重新表述。这种新颖的方法大大降低了内存和计算要求,使 LLM 可供更广泛的受众使用。

此外,我们在免费的 T4 GPU 上量化了我们自己的 LLM 模型,并运行它来生成文本。您可以在 Hugging Face Hub 上推送您自己的 GPTQ 4 位量化模型版本。正如介绍中提到的,GPTQ 并不是唯一的 4 位量化算法:GGML 和 NF4 都不错!

下一篇雄哥会详细聊!

每天时间!真的!不够用!能做的事,对于AI来说,太有限!

技术发展飞快,如何从小!短频快的节奏中!快速上线!

快速收钱!

这是雄哥搞AI产品,最佳状态!

我们在年后,给不少公司做了技术团队的技能集训,让你的团队瞬间拥有开发技能,感兴趣可以联系雄哥或工作人员!

期待与你展开愉快的技术交流和合作!

进群、知识星球优惠,联系雄哥技术助手-小胖!


53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询