點(diǎn)擊參加51CTO網(wǎng)站內(nèi)容調(diào)查問卷
譯者 | 崔皓
審校 | 重樓
摘要
文章介紹了QLoRa(Quantized LLMs with Low-Rank Adapters),一種在消費(fèi)者級別的硬件上微調(diào)大型語言模型(LLM)的新方法。QLoRa通過引入4位量化、雙重量化和利用nVidia統(tǒng)一內(nèi)存進(jìn)行分頁,大大減少了微調(diào)所需的內(nèi)存,同時保持了與標(biāo)準(zhǔn)微調(diào)相當(dāng)?shù)男阅?。文章還提供了如何使用QLoRa微調(diào)一個擁有200億參數(shù)的GPT模型的詳細(xì)步驟,包括硬件和軟件的要求,以及如何準(zhǔn)備數(shù)據(jù)集和進(jìn)行微調(diào)。
開篇
微調(diào)具有數(shù)十億參數(shù)的模型現(xiàn)在可以在消費(fèi)者硬件上實(shí)現(xiàn)。大多數(shù)大型語言模型(LLM)過于龐大,無法在消費(fèi)者硬件上進(jìn)行微調(diào)。例如,要微調(diào)一個擁有650億參數(shù)的模型,我們需要超過780 Gb的GPU內(nèi)存。這相當(dāng)于十個A100 80 Gb的GPU。換句話說,您需要云計(jì)算來微調(diào)您的模型?,F(xiàn)在,有了QLoRa,只需要一個A100就可以做到。
在這篇博客文章中,將介紹QLoRa的工作原理,同時會描述如何使用QLoRa在GPU上微調(diào)一個擁有200億參數(shù)的GPT模型。
注意:我使用我自己的nVidia RTX 3060 12 Gb來運(yùn)行這篇文章中的所有命令。您也可以使用Google Colab的免費(fèi)實(shí)例來達(dá)到相同的效果。如果你想使用一個內(nèi)存更小的GPU,就必須選擇更小的LLM。
QLoRa:使用低秩適配器的量化LLM
2021年6月,Hu等人(2021)在一篇論文中提出這樣一個概念,就是為LLM引入低秩適配器(Low-Rank Adapters)。
【編者:低秩low rank是指一個矩陣的秩(rank)比較低,也就是說,這個矩陣中的行向量或列向量之間存在一定的線性相關(guān)性,可以用更少的向量來表示整個矩陣。在某些應(yīng)用中,低秩的矩陣可以幫助我們更好地理解數(shù)據(jù)的結(jié)構(gòu)和特征,例如在降維、數(shù)據(jù)壓縮、圖像處理等領(lǐng)域中都有廣泛的應(yīng)用。】
LoRa為LLM的每一層添加了微小量的可訓(xùn)練參數(shù),即適配器,并凍結(jié)所有原始參數(shù)。對于微調(diào),我們只需要更新適配器權(quán)重,這大大減少了內(nèi)存占用。
QLoRa通過引入4位量化、雙重量化和利用nVidia統(tǒng)一內(nèi)存進(jìn)行分頁。
下面簡單描述,其工作原理:
- 4位NormalFloat量化:這是一種改進(jìn)量化的方法。它確保每個量化箱中的值數(shù)量相等。這避免了計(jì)算問題和異常值的錯誤。
- 雙重量化:QLoRa的作者將其定義為:“對量化常數(shù)進(jìn)行量化以節(jié)省更多內(nèi)存的過程?!?/span>
- 使用統(tǒng)一內(nèi)存進(jìn)行分頁:它依賴于NVIDIA統(tǒng)一內(nèi)存功能,并自動處理CPU和GPU之間的頁到頁傳輸。它確保GPU處理無誤,特別是在GPU可能內(nèi)存不足的情況下。
所有這些步驟都大大減少了微調(diào)所需的內(nèi)存,同時幾乎與標(biāo)準(zhǔn)微調(diào)的性能相當(dāng)。
使用QLoRa微調(diào)GPT模型
QLoRa的硬件要求:
- GPU:以下演示適用于擁有12 Gb VRAM的GPU,對于參數(shù)少于200億的模型,例如GPT-J。我用我的RTX 3060 12 Gb運(yùn)行了它。如果你有一個更大的卡,擁有24 Gb的VRAM,你可以用一個200億參數(shù)的模型,例如GPT-NeoX-20b。
- RAM:我建議最少6 Gb。大多數(shù)最新的計(jì)算機(jī)都有足夠的RAM。
- 硬盤:GPT-J和GPT-NeoX-20b都是非常大的模型。我建議至少有80 Gb的可用空間。
如果你的機(jī)器不滿足這些要求,Google Colab的免費(fèi)實(shí)例將足夠。
【編者:Google Colab是一種云端的Jupyter Notebook環(huán)境,由Google提供,用戶可以在其中編寫和運(yùn)行Python代碼。它提供了免費(fèi)的GPU和TPU資源,使得用戶可以在云端進(jìn)行機(jī)器學(xué)習(xí)和深度學(xué)習(xí)的實(shí)驗(yàn),而無需購買昂貴的硬件設(shè)備。同時,Google Colab還與Google Drive集成,用戶可以將Notebook存儲在自己的Google Drive中,并與其他人共享。】
QLoRa的軟件要求:
我們需要CUDA。確保它已經(jīng)安裝在你的機(jī)器上。
【編者:CUDA (Compute Unified Device Architecture) 是由 NVIDIA 開發(fā)的一種并行計(jì)算平臺和編程模型,它允許開發(fā)人員使用 C/C++、Fortran 等高級語言編寫并行計(jì)算程序,利用 NVIDIA GPU 的并行計(jì)算能力加速計(jì)算。CUDA 可以在多種操作系統(tǒng)上運(yùn)行,包括 Windows、Linux 和 macOS。它被廣泛應(yīng)用于科學(xué)計(jì)算、機(jī)器學(xué)習(xí)、深度學(xué)習(xí)、圖像處理、計(jì)算機(jī)視覺等領(lǐng)域。】
與此同時還需要如下依賴項(xiàng):
- bitsandbytes:一個包含我們需要量化LLM所需的所有內(nèi)容的庫。
- Hugging Face Transformers和Accelerate:這些是用于有效訓(xùn)練Hugging Face Hub模型的標(biāo)準(zhǔn)庫。
- PEFT:一個提供各種方法實(shí)現(xiàn)只微調(diào)少量(額外)模型參數(shù)的庫。我們需要它來進(jìn)行LoRa。
- Datasets:并不是必選項(xiàng)。我們只會用它來獲取一個用于微調(diào)的數(shù)據(jù)集。當(dāng)然,你也可以提供你自己的數(shù)據(jù)集。
我們可以使用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模型
我們需要以下導(dǎo)入來加載和量化LLM。
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
對于這個演示,我們將微調(diào)EleutherAI預(yù)訓(xùn)練的GPT NeoX模型。這是一個擁有200億參數(shù)的模型。注意:GPT NeoX有一個寬松的許可證(Apache 2.0)允許商業(yè)使用。
我們可以從Hugging Face Hub獲取這個模型和相關(guān)的tokenizer:
model_name = "EleutherAI/gpt-neox-20b"
#Tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name)
然后,我們需要詳細(xì)描述量化器的配置,如下:
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位精度加載到內(nèi)存中。
- bnb_4bit_use_double_quant:我們將進(jìn)行QLoRa提出的雙重量化。
- bnb_4bit_quant_type:這是量化的類型。“nf4”代表4位NormalFloat。
- bnb_4bit_compute_dtype:雖然我們以4位加載和存儲模型,但我們在需要時會部分地反量化它,并以16位精度(bfloat16)進(jìn)行所有的計(jì)算。
所以,現(xiàn)在我們可以以4位加載模型:
model = AutoModelForCausalLM.from_pretrained(model_name, quantization_config=quant_config, device_map={"":0})
然后,我們啟用梯度檢查點(diǎn):
model.gradient_checkpointing_enable()
為LoRa預(yù)處理GPT模型
這是我們使用PEFT的地方。我們?yōu)長oRa準(zhǔn)備模型,為每一層添加可訓(xùn)練的適配器。
【編者:PEFT(參數(shù)高效微調(diào))庫是一個由HuggingFace支持的庫,它支持LoRa(低秩適應(yīng))】
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中,你可以調(diào)整r、alpha和dropout以在你的任務(wù)上獲得更好的結(jié)果。你可以在PEFT倉庫中找到更多的選項(xiàng)和細(xì)節(jié)。
使用LoRa,我們只添加了800萬參數(shù)。我們將只訓(xùn)練這些參數(shù)并凍結(jié)其他所有內(nèi)容。微調(diào)應(yīng)該很快。
準(zhǔn)備你的數(shù)據(jù)集
對于這個演示,我使用了“english_quotes”數(shù)據(jù)集。這是一個由著名引語組成的數(shù)據(jù)集,根據(jù)CC BY 4.0許可分發(fā)。
markdown
from datasets import load_dataset
data = load_dataset("Abirate/english_quotes")
data = data.map(lambda samples: tokenizer(samples["quote"]), batched=True)
使用QLoRa微調(diào)GPT-NeoX-20B
最后,使用Hugging Face Transformers進(jìn)行微調(diào)非常標(biāo)準(zhǔn)。
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”。它激活了分頁以更好地管理內(nèi)存。沒有它,程序會報(bào)內(nèi)存不足的錯誤。
運(yùn)行這個微調(diào)應(yīng)該只需要在Google Colab上花費(fèi)5分鐘。
VRAM消耗應(yīng)該在15 Gb達(dá)到峰值。
就這樣,我們免費(fèi)微調(diào)了一個LLM!
使用QLoRa的GPT推理
我們微調(diào)的QLoRa模型可以直接使用標(biāo)準(zhǔn)的Hugging Face Transformers進(jìn)行推理,如下:
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))
你應(yīng)該得到這樣的輸出:
Ask not what your country can do for you, ask what you can do for your country.”– John F.
輸出翻譯:“不要問你的國家能為你做什么,問你能為你的國家做什么。”– 約翰·F。
我們得到了預(yù)期的結(jié)果。對于5分鐘的微調(diào)來說,已經(jīng)不錯了!
結(jié)論
在大型語言模型變得更大的同時我們找到了響應(yīng)的微調(diào)工具,QLoRa可以在消費(fèi)者硬件上對模型進(jìn)行微調(diào)和推理。有了QLoRa的幫助,我們可以在不依賴云計(jì)算的情況下,微調(diào)數(shù)十億參數(shù)的模型,根據(jù)QLoRa的相關(guān)論文描述,微調(diào)并沒有帶來性能的顯著下降。
譯者介紹
崔皓,51CTO社區(qū)編輯,資深架構(gòu)師,擁有18年的軟件開發(fā)和架構(gòu)經(jīng)驗(yàn),10年分布式架構(gòu)經(jīng)驗(yàn)。
原文標(biāo)題:QLoRa: Fine-Tune a Large Language Model on Your GPU,作者:Benjamin Marie


2024-05-07 08:00:00




