关于人工智能:QLoRa在消费级GPU上微调大型语言模型

8次阅读

共计 4008 个字符,预计需要花费 11 分钟才能阅读完成。

大多数大型语言模型 (LLM) 都无奈在消费者硬件上进行微调。例如,650 亿个参数模型须要超过 780 Gb 的 GPU 内存。这相当于 10 个 A100 80gb 的 gpu。就算咱们应用云服务器,破费的开销也不是所有人都可能承当的。

而 QLoRa (Dettmers et al.,2023),只需应用一个 A100 即可实现此操作。

在这篇文章中将介绍 QLoRa。包含形容它是如何工作的,以及如何应用它在 GPU 上微调具备 200 亿个参数的 GPT 模型。

为了进行演示,本文应用 nVidia RTX 3060 12 GB 来运行本文中的所有命令。这样能够保障小显存的要求,并且也保障能够应用收费的 Google Colab 实例来实现雷同的后果。然而,如果你只有较小内存的 GPU,则必须应用较小的 LLM。

QLoRa: Quantized LLMs with Low-Rank Adapters

2021 年 6 月,公布的 LoRa 让咱们的微调变得简略,我也在以前的文章中也有过介绍。

LoRa 为 LLM 的每一层增加了大量的可训练参数(适配器),并解冻了所有原始参数。这样对于微调,只须要更新适配器权重,这能够显著缩小内存占用。

而 QLoRa 更进一步,引入了 4 位量化、双量化和利用 nVidia 对立内存进行分页。

简而言之,QLoRa 工作原理如下:

  • 4 位 NormalFloat 量化: 这是一种改良量化的办法。它确保每个量化仓中有雷同数量的值。这防止了计算问题和异样值的谬误。
  • 双量化:QLoRa 的作者将其定义如下“对量化常量再次量化以节俭额定内存的过程。”
  • 对立内存分页: 它依赖于 NVIDIA 对立内存治理,主动解决 CPU 和 GPU 之间的页到页传输。它能够保障 GPU 解决无错,特地是在 GPU 可能耗尽内存的状况下。

所有这些步骤都大大减少了微调所需的内存,同时性能简直与规范微调相当。

应用 QLoRa 对 GPT 模型进行微调

硬件要求:

上面的演示工作在具备 12gb VRAM 的 GPU 上,用于参数少于 200 亿个模型,例如 GPT-J。

如果你有一个更大的卡,比方 24gb 的 VRAM,则能够用一个 200 亿个参数的模型,例如 GPT-NeoX-20b。

内存倡议至多 6 Gb,这个条件当初都能满足对吧

GPT- J 和 GPT-NeoX-20b 都是十分大的模型。所以硬盘议至多有 100gb 的可用空间。

如果你的机器不满足这些要求,能够应用 Google Colab 的收费实例,因为它就足够应用了。

软件要求:

必须要 CUDA。这是必定的。而后还须要一些依赖:

  • bitsandbytes: 蕴含量化 LLM 所需的所有库。
  • Hugging Face 的 Transformers 和 Accelerate: 这些是规范库,用于训练模型。
  • PEFT: 提供了各种微调办法的实现,咱们只须要外面的 LoRa。
  • 数据集: 本人的数据集,这里装置了 Hugging Face 的 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 代码

1、GPT 模型的加载与量化

咱们须要以下导入来加载和量化 LLM。

 import torch
 from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig

咱们将对 EleutherAI 预训练的 GPT NeoX 模型进行微调。这是一个有 200 亿个参数的模型。留神:GPT NeoX 具备容许商业应用的宽松许可证(Apache 2.0)。

能够从 hug Face Hub 取得这个模型和相干的标记器:

 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()

2、LoRa 的 GPT 模型预处理

为 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 万个参数。并且只训练这些参数,这样使得微调很快。

3、数据集

对于这个演示,咱们应用“english_quotes”数据集。这是一个由名言组成的数据集,在 CC BY 4.0 许可下公布。咱们为了方便使用 datasets 间接加载。

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

4、微调

微调的代码十分规范

 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 耗费的峰值是 15gb。

它有用吗? 让咱们试试推理。

基于 QLoRa 推理

微调的 QLoRa 模型能够间接与规范的 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.

5 分钟的微调成果还能够吧。

总结

LoRa 让咱们的微调变得简略,而 QLoRa 能够让咱们应用生产级的 GPU 对具备 10 亿个参数的模型进行微调,并且依据 QLoRa 论文,性能不会显著降落。

如果你对 QLoRa 感兴趣,看看他的代码吧:

https://avoid.overfit.cn/post/4c4c86e3f7974157a7a8e81c57a0f8a4

正文完
 0