QLoRa:利用GPU微调大型语言模型 译文 精选

2023-06-09
关注

点击参加51CTO网站内容调查问卷

译者 | 崔皓

审校 | 重楼

摘要

文章介绍了QLoRa(Quantized LLMs with Low-Rank Adapters),一种在消费者级别的硬件上微调大型语言模型(LLM)的新方法。QLoRa通过引入4位量化、双重量化和利用nVidia统一内存进行分页,大大减少了微调所需的内存,同时保持了与标准微调相当的性能。文章还提供了如何使用QLoRa微调一个拥有200亿参数的GPT模型的详细步骤,包括硬件和软件的要求,以及如何准备数据集和进行微调。

开篇

微调具有数十亿参数的模型现在可以在消费者硬件上实现。大多数大型语言模型(LLM)过于庞大,无法在消费者硬件上进行微调。例如,要微调一个拥有650亿参数的模型,我们需要超过780 Gb的GPU内存。这相当于十个A100 80 Gb的GPU。换句话说,您需要云计算来微调您的模型。现在,有了QLoRa,只需要一个A100就可以做到。

在这篇博客文章中,将介绍QLoRa的工作原理,同时会描述如何使用QLoRa在GPU上微调一个拥有200亿参数的GPT模型。

注意:我使用我自己的nVidia RTX 3060 12 Gb来运行这篇文章中的所有命令。您也可以使用Google Colab的免费实例来达到相同的效果。如果你想使用一个内存更小的GPU,就必须选择更小的LLM。

QLoRa:使用低秩适配器的量化LLM

2021年6月,Hu等人(2021)在一篇论文中提出这样一个概念,就是为LLM引入低秩适配器(Low-Rank Adapters)。

【编者:低秩low rank是指一个矩阵的秩(rank)比较低,也就是说,这个矩阵中的行向量或列向量之间存在一定的线性相关性,可以用更少的向量来表示整个矩阵。在某些应用中,低秩的矩阵可以帮助我们更好地理解数据的结构和特征,例如在降维、数据压缩、图像处理等领域中都有广泛的应用。】

LoRa为LLM的每一层添加了微小量的可训练参数,即适配器,并冻结所有原始参数。对于微调,我们只需要更新适配器权重,这大大减少了内存占用。

QLoRa通过引入4位量化、双重量化和利用nVidia统一内存进行分页。

下面简单描述,其工作原理:

  • 4位NormalFloat量化:这是一种改进量化的方法。它确保每个量化箱中的值数量相等。这避免了计算问题和异常值的错误。
  • 双重量化:QLoRa的作者将其定义为:“对量化常数进行量化以节省更多内存的过程。”
  • 使用统一内存进行分页:它依赖于NVIDIA统一内存功能,并自动处理CPU和GPU之间的页到页传输。它确保GPU处理无误,特别是在GPU可能内存不足的情况下。

所有这些步骤都大大减少了微调所需的内存,同时几乎与标准微调的性能相当。

使用QLoRa微调GPT模型

QLoRa的硬件要求:

  • GPU:以下演示适用于拥有12 Gb VRAM的GPU,对于参数少于200亿的模型,例如GPT-J。我用我的RTX 3060 12 Gb运行了它。如果你有一个更大的卡,拥有24 Gb的VRAM,你可以用一个200亿参数的模型,例如GPT-NeoX-20b。
  • RAM:我建议最少6 Gb。大多数最新的计算机都有足够的RAM。
  • 硬盘:GPT-J和GPT-NeoX-20b都是非常大的模型。我建议至少有80 Gb的可用空间。

如果你的机器不满足这些要求,Google Colab的免费实例将足够。

【编者:Google Colab是一种云端的Jupyter Notebook环境,由Google提供,用户可以在其中编写和运行Python代码。它提供了免费的GPU和TPU资源,使得用户可以在云端进行机器学习和深度学习的实验,而无需购买昂贵的硬件设备。同时,Google Colab还与Google Drive集成,用户可以将Notebook存储在自己的Google Drive中,并与其他人共享。】

QLoRa的软件要求:

我们需要CUDA。确保它已经安装在你的机器上。

【编者:CUDA (Compute Unified Device Architecture) 是由 NVIDIA 开发的一种并行计算平台和编程模型,它允许开发人员使用 C/C++、Fortran 等高级语言编写并行计算程序,利用 NVIDIA GPU 的并行计算能力加速计算。CUDA 可以在多种操作系统上运行,包括 Windows、Linux 和 macOS。它被广泛应用于科学计算、机器学习、深度学习、图像处理、计算机视觉等领域。】

与此同时还需要如下依赖项:

  • bitsandbytes:一个包含我们需要量化LLM所需的所有内容的库。
  • Hugging Face Transformers和Accelerate:这些是用于有效训练Hugging Face Hub模型的标准库。
  • PEFT:一个提供各种方法实现只微调少量(额外)模型参数的库。我们需要它来进行LoRa。
  • Datasets:并不是必选项。我们只会用它来获取一个用于微调的数据集。当然,你也可以提供你自己的数据集。

我们可以使用PIP获取所有这些:

pip install -q -U bitsandbytes
pip install -q -U git+https://github.com/huggingface/transformers.git 
pip install -q -U git+https://github.com/huggingface/peft.git
pip install -q -U git+https://github.com/huggingface/accelerate.git
pip install -q datasets

接下来,我们可以开始编写Python脚本。

加载和量化GPT模型

我们需要以下导入来加载和量化LLM。

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig

对于这个演示,我们将微调EleutherAI预训练的GPT NeoX模型。这是一个拥有200亿参数的模型。注意:GPT NeoX有一个宽松的许可证(Apache 2.0)允许商业使用。

我们可以从Hugging Face Hub获取这个模型和相关的tokenizer:

model_name = "EleutherAI/gpt-neox-20b"
#Tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name)

然后,我们需要详细描述量化器的配置,如下:

quant_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16)

  • load_in_4bit:模型将以4位精度加载到内存中。
  • bnb_4bit_use_double_quant:我们将进行QLoRa提出的双重量化。
  • bnb_4bit_quant_type:这是量化的类型。“nf4”代表4位NormalFloat。
  • bnb_4bit_compute_dtype:虽然我们以4位加载和存储模型,但我们在需要时会部分地反量化它,并以16位精度(bfloat16)进行所有的计算。

所以,现在我们可以以4位加载模型:

model = AutoModelForCausalLM.from_pretrained(model_name, quantization_config=quant_config, device_map={"":0})

然后,我们启用梯度检查点:

model.gradient_checkpointing_enable()

为LoRa预处理GPT模型

这是我们使用PEFT的地方。我们为LoRa准备模型,为每一层添加可训练的适配器。

【编者:PEFT(参数高效微调)库是一个由HuggingFace支持的库,它支持LoRa(低秩适应)】

from peft import prepare_model_for_kbit_training, LoraConfig, get_peft_model
model = prepare_model_for_kbit_training(model)
config = LoraConfig(
    r=8, 
    lora_alpha=32, 
    target_modules=["query_key_value"], 
    lora_dropout=0.05, 
    bias="none", 
    task_type="CAUSAL_LM")
model = get_peft_model(model, config)

在LoraConfig中,你可以调整r、alpha和dropout以在你的任务上获得更好的结果。你可以在PEFT仓库中找到更多的选项和细节。

使用LoRa,我们只添加了800万参数。我们将只训练这些参数并冻结其他所有内容。微调应该很快。

准备你的数据集

对于这个演示,我使用了“english_quotes”数据集。这是一个由著名引语组成的数据集,根据CC BY 4.0许可分发。

markdown
from datasets import load_dataset
data = load_dataset("Abirate/english_quotes")
data = data.map(lambda samples: tokenizer(samples["quote"]), batched=True)

使用QLoRa微调GPT-NeoX-20B

最后,使用Hugging Face Transformers进行微调非常标准。

import transformers
tokenizer.pad_token = tokenizer.eos_token
trainer = transformers.Trainer(
    model=model,
    train_dataset=data["train"],
    args=transformers.TrainingArguments(
        per_device_train_batch_size=1,
        gradient_accumulation_steps=8,
        warmup_steps=2,
        max_steps=20,
        learning_rate=2e-4,
        fp16=True,
        logging_steps=1,
        output_dir="outputs",
        optim="paged_adamw_8bit"
    ),
    data_collator=transformers.DataCollatorForLanguageModeling(tokenizer, mlm=False),
)
trainer.train()

不要忘记optim=”paged_adamw_8bit”。它激活了分页以更好地管理内存。没有它,程序会报内存不足的错误。

运行这个微调应该只需要在Google Colab上花费5分钟。

VRAM消耗应该在15 Gb达到峰值。

就这样,我们免费微调了一个LLM!

使用QLoRa的GPT推理

我们微调的QLoRa模型可以直接使用标准的Hugging Face Transformers进行推理,如下:

text = "Ask not what your country
device = "cuda:0"
inputs = tokenizer(text, return_tensors="pt").to(device)
outputs = model.generate(**inputs, max_new_tokens=20)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

你应该得到这样的输出:

Ask not what your country can do for you, ask what you can do for your country.”– John F.

输出翻译:“不要问你的国家能为你做什么,问你能为你的国家做什么。”– 约翰·F。

我们得到了预期的结果。对于5分钟的微调来说,已经不错了!

结论

在大型语言模型变得更大的同时我们找到了响应的微调工具,QLoRa可以在消费者硬件上对模型进行微调和推理。有了QLoRa的帮助,我们可以在不依赖云计算的情况下,微调数十亿参数的模型,根据QLoRa的相关论文描述,微调并没有带来性能的显著下降。

译者介绍

陈峻(Julian Chen),51CTO社区编辑,具有十多年的IT项目实施经验,善于对内外部资源与风险实施管控,专注传播网络与信息安全知识与经验。

原文标题:QLoRa: Fine-Tune a Large Language Model on Your GPU,作者:Benjamin Marie

您觉得本篇内容如何
评分

相关产品

Honeywell 霍尼韦尔智能工业 在线/便携烟气分析仪专用传感器 气体传感器

CO 传感器;SO2传感器;NO2 传感器;NO传感器;氧气传感器

微著科技 高性能传感器ASIC解决方案 MEMS传感器

微著科技是国内为数不多能够给传感器厂商提供定制高性能传感器解决方案的团队,目前已为国内众多院所及知名传感器公司提供了十余个传感器解决方案并已经实现量产。微著传感器ASIC方案的特点:成熟的仪表信号模块IP易于快速搭建;系统方案超低噪声;成熟的24ADC可同时实现模拟数字传感器方案设计;高效率及丰富的方案设计经验。

南方泰科 TGM 压力传感器

TGM是一款SOP8封装的压阻式MEMS压力传感器,其压力传感器芯片封装在 SOP8 塑封壳内。在传感器压力量程内,当用固定电压供电时,传感器产生毫伏输出电压,正比于输入压力。压力传感器芯片为绝压,可提供不同的压力量程的SOP8 压力传感器。

鑫精诚传感器 XJC-T001 压力传感器

◆传感器激光焊接密封,环境适应性较强 ◆球形联接件,始终保持模块的垂直称重状态 ◆支撑螺栓,防止设备倾覆且方便维护 ◆接地装置,保护传感器免受电源浪涌冲击 ◆过载保护装置,保护传感器免受冲击力

Huba Control 富巴 525系列 压力传感器

525系列压力传感器采用集公司20多年研发经验的陶瓷压力传感器芯片技术。该系列压力传感器可选压力范围大,电气连接形式多。最小量程为50mbar。大批量使用具有很好的性价比。

佰测传感 MS71 传感器

MS71差压传感器

Cubic 四方光电 PM3009BP 室外粉尘传感器

PM3009BP是一款专门针对餐饮油烟监测的油烟传感器,其采用旁流采样方式,自带除水雾装置,结合智能颗粒物识别算法,确保传感器能够快速准确的检测油烟浓度的变化,同时创新的镜头自清洁技术的应用,能够长效防护传感器油烟污染,大幅度延长传感器的使用寿命。

评论

您需要登录才可以回复|注册

提交评论

广告
提取码
复制提取码
点击跳转至百度网盘