點擊參加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的相關論文描述,微調并沒有帶來性能的顯著下降。
譯者介紹
崔皓,51CTO社區編輯,資深架構師,擁有18年的軟件開發和架構經驗,10年分布式架構經驗。
原文標題:QLoRa: Fine-Tune a Large Language Model on Your GPU,作者:Benjamin Marie