透過 bitsandbytes、4 位量化和 QLoRA 讓 LLM 更易於訪問
眾所周知,LLM 體積龐大,在消費級硬體上執行或訓練它們對使用者和可訪問性來說是一個巨大的挑戰。我們的LLM.int8 部落格文章展示瞭如何在 Transformer 中使用 `bitsandbytes` 庫整合LLM.int8 論文中的技術。為了讓模型更易於訪問,我們決定再次與 bitsandbytes 合作,允許使用者以 4 位精度執行模型。這包括絕大多數 Hugging Face 模型,支援任何模態(文字、視覺、多模態等)。使用者還可以利用 Hugging Face 生態系統中的工具在 4 位模型之上訓練介面卡。這是 Dettmers 等人在今天的 QLoRA 論文中介紹的一種新方法。論文摘要如下:
我們提出了 QLoRA,這是一種高效的微調方法,它能顯著減少記憶體使用,足以在單個 48GB GPU 上微調一個 65B 引數的模型,同時保持完整的 16 位微調任務效能。QLoRA 透過一個凍結的 4 位量化預訓練語言模型將梯度反向傳播到低秩介面卡(LoRA)中。我們最佳的模型家族,命名為 Guanaco,在 Vicuna 基準測試中超越了所有先前公開的模型,達到了 ChatGPT 效能水平的 99.3%,而只需在單個 GPU 上進行 24 小時的微調。QLoRA 引入了多項創新來節省記憶體而不犧牲效能:(a) 4 位 NormalFloat (NF4),一種資訊理論上最適合正態分佈權重的全新資料型別;(b) 雙重量化,透過量化量化常數來減少平均記憶體佔用;(c) 分頁最佳化器來管理記憶體峰值。我們使用 QLoRA 微調了 1000 多個模型,詳細分析了 8 個指令資料集、多種模型型別(LLaMA、T5)和模型規模(例如 33B 和 65B 引數模型)下的指令遵循和聊天機器人效能,這些規模的模型使用常規微調是不可能執行的。我們的結果表明,在小型高質量資料集上進行 QLoRA 微調可以獲得最先進的結果,即使使用的模型比以前的 SoTA 小。我們根據人工和 GPT-4 評估提供了詳細的聊天機器人效能分析,表明 GPT-4 評估是人工評估的一種廉價且合理的替代方案。此外,我們發現當前的聊天機器人基準測試不可靠,無法準確評估聊天機器人的效能水平。一個精心挑選的分析展示了 Guanaco 與 ChatGPT 相比的不足之處。我們釋出了所有模型和程式碼,包括用於 4 位訓練的 CUDA 核心。
資源
這篇部落格文章和釋出附帶了多項資源,可幫助您開始使用 4 位模型和 QLoRA
- 原始論文
- 基本用法 Google Colab 筆記本 - 這個筆記本展示瞭如何使用 4 位模型進行推理,以及如何在免費的 Google Colab 例項上執行 GPT-neo-X(一個 20B 引數模型)🤯
- 微調 Google Colab 筆記本 - 這個筆記本展示瞭如何使用 Hugging Face 生態系統在下游任務上微調 4 位模型。我們展示了在 Google Colab 例項上微調 GPT-neo-X 20B 是可行的!
- 用於復現論文結果的原始儲存庫
- Guanaco 33b 遊樂場 - 或檢視下面的遊樂場部分
引言
如果您不熟悉模型精度和最常見的資料型別(float16、float32、bfloat16、int8),我們建議您仔細閱讀我們第一篇部落格文章中的介紹,其中透過視覺化簡單地闡述了這些概念的細節。
有關更多資訊,我們建議您透過這篇維基教科書文件閱讀浮點表示的基礎知識。
最近的 QLoRA 論文探討了不同的資料型別:4 位浮點和 4 位 NormalFloat。這裡我們將討論 4 位浮點資料型別,因為它更容易理解。
FP8 和 FP4 分別代表 8 位和 4 位浮點精度。它們是浮點值微浮點家族的一部分(在該家族中,還有其他精度,包括 bfloat16 和 float16)。
我們首先來看看如何在 FP8 格式中表示浮點值,然後瞭解 FP4 格式的特點。
FP8 格式
正如我們在之前的部落格文章中討論的,浮點數包含 n 位,其中每個位都屬於一個特定類別,負責表示數字的組成部分(符號位、尾數和指數)。它們代表以下內容:
FP8(8 位浮點)格式首次在論文“FP8 for Deep Learning”中提出,包含兩種不同的 FP8 編碼:E4M3(4 位指數和 3 位尾數)和 E5M2(5 位指數和 2 位尾數)。
![]() |
---|
8 位浮點 (FP8) 格式概述。來源:sgugger 的原創內容 |
儘管透過將位數從 32 位減少到 8 位,精度大幅降低,但這兩個版本都可以在各種情況下使用。目前可以使用Transformer Engine 庫,它也透過 accelerate 整合到 HF 生態系統中。
E4M3 格式可以表示的潛在浮點數範圍是 -448 到 448,而 E5M2 格式,由於指數位數增加,範圍擴大到 -57344 到 57344 - 但精度有所損失,因為可表示的數量保持不變。經驗證明,E4M3 最適合前向傳播,而第二種版本最適合反向計算。
FP4 精度簡介
符號位表示符號(+/-),指數位表示以 2 為底,指數為由這些位表示的整數(例如,`2^{010} = 2^{2} = 4`),而小數部分或尾數是負 2 的冪之和,這些冪在每個“1”的位上都是“活躍的”。如果一個位是“0”,則該位對應的 `2^-i` 冪(i 是該位在位序列中的位置)的小數部分保持不變。例如,對於尾數位 1010,我們有 `(0 + 2^-1 + 0 + 2^-3) = (0.5 + 0.125) = 0.625`。為了得到一個值,我們將 1 加到小數部分,並將所有結果相乘。例如,如果使用 2 個指數位和 1 個尾數位,表示 1101 將是:
-1 * 2^(2) * (1 + 2^-1) = -1 * 4 * 1.5 = -6
對於 FP4,沒有固定的格式,因此可以嘗試不同的尾數/指數組合。通常,在大多數情況下,3 個指數位表現得稍好。但有時 2 個指數位和 1 個尾數位會產生更好的效能。
QLoRA 論文:量化大型 Transformer 模型民主化的新途徑
簡單來說,QLoRA 在不犧牲效能的前提下,降低了 LLM 微調的記憶體使用量,與標準 16 位模型微調相比。該方法使得在單個 24GB GPU 上微調 33B 模型,以及在單個 46GB GPU 上微調 65B 模型成為可能。
更具體地說,QLoRA 使用 4 位量化來壓縮預訓練語言模型。然後,LM 引數被凍結,並以低秩介面卡 (Low-Rank Adapters) 的形式向模型新增相對較少的可訓練引數。在微調過程中,QLoRA 透過凍結的 4 位量化預訓練語言模型將梯度反向傳播到低秩介面卡中。LoRA 層是訓練期間唯一被更新的引數。有關 LoRA 的更多資訊,請閱讀原始 LoRA 論文。
QLoRA 有一個用於基礎模型權重的儲存資料型別(通常是 4 位 NormalFloat)和一個用於執行計算的計算資料型別(16 位 BrainFloat)。QLoRA 將權重從儲存資料型別反量化到計算資料型別以執行前向和後向傳播,但僅計算使用 16 位 bfloat 的 LoRA 引數的權重梯度。權重僅在需要時才解壓縮,因此在訓練和推理期間記憶體使用率保持較低。
QLoRA 微調在廣泛的實驗中與 16 位微調方法表現出了一致的效能。此外,使用 QLoRA 在 OpenAssistant 資料集 (OASST1) 上對 LLaMA 模型進行微調的 Guanaco 模型,是當前最先進的聊天機器人系統,在 Vicuna 基準測試中與 ChatGPT 表現接近。這進一步證明了 QLoRA 微調的強大之處。
如需更詳細的閱讀,我們建議您閱讀 QLoRA 論文。
如何在 Transformers 中使用?
在本節中,我們將介紹該方法在 Transformer 中的整合,如何使用它以及哪些模型可以有效地量化。
開始使用
作為快速入門,請透過(截至本文撰寫時)從原始碼安裝 accelerate 和 transformers 來載入 4 位模型,並確保您已安裝最新版本的 bitsandbytes 庫(0.39.0)。
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
快速入門
載入 4 位模型的基本方法是在呼叫 `from_pretrained` 方法時,傳遞引數 `load_in_4bit=True` 並提供裝置對映(傳入 `"auto"` 以自動推斷裝置對映)。
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("facebook/opt-350m", load_in_4bit=True, device_map="auto")
...
就這些!
通常,我們建議使用者在模型載入時使用 `device_map` 後,不要手動設定裝置。因此,在此行之後,應避免對模型或模型的任何子模組進行任何裝置分配呼叫 - 除非您知道自己在做什麼。
請記住,載入量化模型將自動將其他模型的子模組轉換為 `float16` 資料型別。您可以透過將 `torch_dtype=dtype` 傳遞給 `from_pretrained` 方法來更改此行為(例如,如果您希望層範數使用 `float32`)。
高階用法
您可以嘗試 4 位量化的不同變體,例如 NF4(規範化浮點 4(預設))或純 FP4 量化。根據論文的理論考量和實證結果,我們建議使用 NF4 量化以獲得更好的效能。
其他選項包括 `bnb_4bit_use_double_quant`,它在第一次量化之後進行第二次量化,每個引數額外節省 0.4 位。最後是計算型別。儘管 4 位 bitsandbytes 將權重儲存在 4 位中,但計算仍然以 16 位或 32 位進行,並且這裡可以選擇任何組合(float16、bfloat16、float32 等)。
如果使用 16 位計算資料型別(預設 torch.float32),矩陣乘法和訓練會更快。應該利用 transformers 中最新的 `BitsAndBytesConfig` 來更改這些引數。下面是一個使用 NF4 量化、雙重量化和計算資料型別 bfloat16 來更快訓練的 4 位模型載入示例。
from transformers import BitsAndBytesConfig
nf4_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype=torch.bfloat16
)
model_nf4 = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=nf4_config)
更改計算資料型別
如上所述,您還可以透過更改 `BitsAndBytesConfig` 中的 `bnb_4bit_compute_dtype` 引數來更改量化模型的計算資料型別。
import torch
from transformers import BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.bfloat16
)
巢狀量化
要啟用巢狀量化,您可以在 `BitsAndBytesConfig` 中使用 `bnb_4bit_use_double_quant` 引數。這將允許在第一次量化之後進行第二次量化,從而每個引數額外節省 0.4 位。我們還在訓練 Google Colab 筆記本中使用了此功能。
from transformers import BitsAndBytesConfig
double_quant_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_use_double_quant=True,
)
model_double_quant = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=double_quant_config)
當然,如本節開頭所述,所有這些元件都可以組合使用。您可以將所有這些引數組合在一起,以找到最適合您的用例。經驗法則是:如果記憶體有問題,請使用雙量化;為了獲得更高的精度,請使用 NF4;為了更快地進行微調,請使用 16 位資料型別。例如,在推理演示中,我們使用巢狀量化、bfloat16 計算資料型別和 NF4 量化,以便將 gpt-neo-x-20b(40GB)完全以 4 位裝入單個 16GB GPU 中。
常見問題
在本節中,我們還將回答一些關於此整合可能存在的常見問題。
FP4 量化是否有硬體要求?
請注意,此方法僅與 GPU 相容,因此無法在 CPU 上將模型量化為 4 位。在 GPU 中,此方法不應有任何硬體要求,因此任何 GPU 都可以用於執行 4 位量化,只要安裝了 CUDA >= 11.2。還要記住,計算並非以 4 位進行,權重和啟用被壓縮為該格式,計算仍然保持在所需或原始資料型別中。
支援哪些模型?
與這篇部落格文章中介紹的 LLM.int8 整合類似,該整合嚴重依賴 `accelerate` 庫。因此,任何支援 accelerate 載入的模型(即呼叫 `from_pretrained` 時帶 `device_map` 引數)都應該可以進行 4 位量化。另請注意,這完全與模態無關,只要模型可以使用 `device_map` 引數載入,就可以對其進行量化。
對於文字模型,截至本文撰寫時,這包括大多數常用架構,例如文字模型的 Llama、OPT、GPT-Neo、GPT-NeoX,多模態模型的 Blip2 等。
截至本文撰寫時,支援 accelerate 的模型有:
[
'bigbird_pegasus', 'blip_2', 'bloom', 'bridgetower', 'codegen', 'deit', 'esm',
'gpt2', 'gpt_bigcode', 'gpt_neo', 'gpt_neox', 'gpt_neox_japanese', 'gptj', 'gptsan_japanese',
'lilt', 'llama', 'longformer', 'longt5', 'luke', 'm2m_100', 'mbart', 'mega', 'mt5', 'nllb_moe',
'open_llama', 'opt', 'owlvit', 'plbart', 'roberta', 'roberta_prelayernorm', 'rwkv', 'switch_transformers',
't5', 'vilt', 'vit', 'vit_hybrid', 'whisper', 'xglm', 'xlm_roberta'
]
請注意,如果您喜歡的模型不在其中,您可以開啟 Pull Request 或在 transformers 中提出 issue,以新增對該架構的 accelerate 載入支援。
我們可以訓練 4 位/8 位模型嗎?
無法對這些模型進行純 4 位訓練。但是,您可以利用引數高效微調方法 (PEFT) 訓練這些模型,例如在其之上訓練介面卡。論文中就是這樣做的,並且 Hugging Face 的 PEFT 庫也正式支援。我們還提供了一個訓練筆記本,並建議使用者檢視QLoRA 儲存庫,如果他們有興趣重現論文中的結果。
還有哪些其他影響?
這項整合可以為社群和人工智慧研究帶來多項積極影響,因為它能影響多個用例和可能的應用。在 RLHF(基於人類反饋的強化學習)中,可以載入單個 4 位基礎模型,並在其之上訓練多個介面卡,一個用於獎勵建模,另一個用於價值策略訓練。關於此用例的更詳細的部落格文章和公告將很快釋出。
我們還對這種量化方法在消費級硬體上訓練大型模型的影響進行了一些基準測試。我們對微調兩種不同架構進行了多次實驗:Llama 7B(fp16 格式為 15GB)和 Llama 13B(fp16 格式為 27GB),均在 NVIDIA T4(16GB)上進行,結果如下:
模型名稱 | 半精度模型大小(GB) | 硬體型別 / 總視訊記憶體 | 量化方法 (CD=計算資料型別 / GC=梯度檢查點 / NQ=巢狀量化) | 批處理大小 | 梯度累積步數 | 最佳化器 | 序列長度 | 結果 |
---|---|---|---|---|---|---|---|---|
<10B 規模模型 | ||||||||
decapoda-research/llama-7b-hf | 14GB | 1xNVIDIA-T4 / 16GB | LLM.int8 (8 位) + GC | 1 | 4 | AdamW | 512 | 無 OOM |
decapoda-research/llama-7b-hf | 14GB | 1xNVIDIA-T4 / 16GB | LLM.int8 (8 位) + GC | 1 | 4 | AdamW | 1024 | OOM |
decapoda-research/llama-7b-hf | 14GB | 1xNVIDIA-T4 / 16GB | 4 位 + NF4 + bf16 CD + 無 GC | 1 | 4 | AdamW | 512 | 無 OOM |
decapoda-research/llama-7b-hf | 14GB | 1xNVIDIA-T4 / 16GB | 4 位 + FP4 + bf16 CD + 無 GC | 1 | 4 | AdamW | 512 | 無 OOM |
decapoda-research/llama-7b-hf | 14GB | 1xNVIDIA-T4 / 16GB | 4 位 + NF4 + bf16 CD + 無 GC | 1 | 4 | AdamW | 1024 | OOM |
decapoda-research/llama-7b-hf | 14GB | 1xNVIDIA-T4 / 16GB | 4 位 + FP4 + bf16 CD + 無 GC | 1 | 4 | AdamW | 1024 | OOM |
decapoda-research/llama-7b-hf | 14GB | 1xNVIDIA-T4 / 16GB | 4 位 + NF4 + bf16 CD + GC | 1 | 4 | AdamW | 1024 | 無 OOM |
10B+ 規模模型 | ||||||||
decapoda-research/llama-13b-hf | 27GB | 2xNVIDIA-T4 / 32GB | LLM.int8 (8 位) + GC | 1 | 4 | AdamW | 512 | 無 OOM |
decapoda-research/llama-13b-hf | 27GB | 1xNVIDIA-T4 / 16GB | LLM.int8 (8 位) + GC | 1 | 4 | AdamW | 512 | OOM |
decapoda-research/llama-13b-hf | 27GB | 1xNVIDIA-T4 / 16GB | 4 位 + FP4 + bf16 CD + 無 GC | 1 | 4 | AdamW | 512 | OOM |
decapoda-research/llama-13b-hf | 27GB | 1xNVIDIA-T4 / 16GB | 4 位 + FP4 + fp16 CD + 無 GC | 1 | 4 | AdamW | 512 | OOM |
decapoda-research/llama-13b-hf | 27GB | 1xNVIDIA-T4 / 16GB | 4 位 + NF4 + fp16 CD + GC | 1 | 4 | AdamW | 512 | 無 OOM |
decapoda-research/llama-13b-hf | 27GB | 1xNVIDIA-T4 / 16GB | 4 位 + NF4 + fp16 CD + GC | 1 | 4 | AdamW | 1024 | OOM |
decapoda-research/llama-13b-hf | 27GB | 1xNVIDIA-T4 / 16GB | 4 位 + NF4 + fp16 CD + GC + NQ | 1 | 4 | AdamW | 1024 | 無 OOM |
我們使用了 TRL 庫中最新的 `SFTTrainer`,基準測試指令碼可以在這裡找到
遊樂場
在遊樂場或直接在下面嘗試論文中引用的 Guananco 模型
致謝
Hugging Face 團隊衷心感謝華盛頓大學參與此專案的所有人員,以及他們為社群所做的貢獻。
作者還要感謝 Pedro Cuenca 審閱了部落格文章,以及 Olivier Dehaene 和 Omar Sanseviero 對論文成果在 HF Hub 上整合的迅速而有力的支援。