🤗量化入門,💗🧑🍳烹製

量化是一組技術,用於降低深度學習模型的精度,使模型更小,訓練更快。如果你不理解這句話,別擔心,在這篇部落格文章的最後你會明白。在這篇部落格文章中,我們將介紹...
- 什麼是精度,為什麼我們需要量化,以及一個簡單的量化示例;
- GPTQ 量化;
- 4/8 位(bitsandbytes)量化。
衝呀!
精度
精度可以定義為表示一個數字所使用的有效數字或位數。它是衡量一個數字可以被**精確**表示的程度,或者在表示中可以保留多少細節(在我們的例子中,是二進位制表示)。
在這篇部落格文章中,我不會詳細介紹用於精度的二進位制表示如何工作,但你可以檢視這篇直觀的部落格文章來了解它的工作原理。
我們根據數字本身的不同,以不同的資料型別表示數字。每種資料型別都有其可以表示的數字範圍。常見的資料型別包括:
資料型別 | 範圍 | 精度 |
---|---|---|
FP32(單精度) | 約 ±1.4013 x 10^-45 到 ±3.4028 x 10^38 | 7 位小數 |
FP16(半精度) | 約 ±5.96 x 10^-8 到 ±6.55 x 10^4 | 3-4 位小數 |
FP8(自定義 8 位浮點) | 動態 | 動態 |
Int8(8 位整數) | -128 到 127(有符號)或 0 到 255(無符號) | 無小數 |
一個數字需要表示得越精確,它所佔用的記憶體就越多。在深度學習中,我們使用浮點表示(FP32/16/8...)來表示權重。雖然 FP32 表示能提供更高的精度和準確性,但模型大小會變得更大,並且訓練或推理(取決於量化型別)期間的計算會變慢。因此,需要降低精度,這也被稱為量化。它是一種有失真壓縮形式,我們壓縮的資訊越多,效能損失就越大。
一種非常簡單的量化技術是將較大範圍的量化型別縮放/投影到較小的尺度,例如(FP32 到 int8)。這看起來如下圖所示 👇
對於給定資料類型範圍 [-α, α],我們可以使用以下公式投影給定值
然而,這種方法有不同的缺點,例如在訓練和推理過程中引入開銷,降低效能,並且對資料中的分佈變化敏感。儘管它非常簡單,但在不同的混合精度訓練方法中被大量使用。
主要有兩種量化方法 👇
- 訓練後量化:這些方法側重於在模型訓練後降低精度。由於它更容易理解,我們將在本部落格文章中主要介紹這種方法,儘管它的效能不如量化感知訓練。
- 量化感知訓練:這種方法允許量化模型,然後對模型進行微調,以減少量化引起的效能下降,或者量化可以在訓練期間進行。
最先進的方法正試圖克服上述問題。我們現在將討論它們以及如何透過 🤗 生態系統中的工具(transformers、TGI、optimum 和 PEFT)使用它們。
GPTQ 量化
GPTQ 是一種訓練後量化方法,透過校準資料集使模型更小。GPTQ 的核心思想非常簡單:它透過找到權重的壓縮版本來量化每個權重,以使均方誤差最小,如下圖所示 👇
給定一個層 及其權重矩陣 和層輸入 ,找到量化權重
在 GPTQ 中,我們一次性進行後量化,這既能節省記憶體又能加快推理速度(與我們稍後將介紹的 4/8 位量化不同)。AutoGPTQ 是一個支援 GPTQ 量化的庫。它已整合到 🤗 生態系統中的各種庫中,用於量化模型、使用/服務已量化模型或進一步微調模型。讓我們看看如何做到這些。
首先,安裝 AutoGPTQ
pip install auto-gptq # for cuda versions other than 11.7, refer to installation guide in above link
pip install transformers optimum peft
- 你可以在 Hugging Face Hub 上執行給定的 GPTQ 模型,如下所示(在此處查詢它們:這裡)👇
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("TheBloke/Llama-2-7b-Chat-GPTQ", torch_dtype=torch.float16, device_map="auto")
你可以像下面這樣量化任何 transformer 模型 👇
from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig
model_id = "facebook/opt-125m"
tokenizer = AutoTokenizer.from_pretrained(model_id)
quantization_config = GPTQConfig(bits=4, dataset = "c4", tokenizer=tokenizer)
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", quantization_config=quantization_config)
- 你可以使用 PEFT 在這個gist中進一步微調給定的 GPTQ 模型。
- 你可以使用 text-generation-inference 量化和提供已經用 GPTQ 方法量化的模型。它在底層不使用 AutoGPTQ 庫。按照此處的說明安裝 TGI 後,你可以像下面這樣執行你在 hub 上找到的 GPTQ 模型 👇
docker run --gpus all --shm-size 1g -p 8080:80 -v $volume:/data ghcr.io/huggingface/text-generation-inference:latest --model-id $model --quantize gptq
要僅使用校準資料集執行量化,只需執行
text-generation-server quantize tiiuae/falcon-40b /data/falcon-40b-gptq
您可以透過執行 text-generation-server quantize --help
瞭解更多量化選項。
使用 bitsandbytes 進行 4/8 位量化
bitsandbytes 是一個用於對模型進行 8 位和 4 位量化的庫。它可以在訓練期間用於混合精度訓練,也可以在推理前使用,以使模型更小。
8 位量化使數十億引數規模的模型能夠適應更小的硬體,而不會降低效能。8 位量化工作原理如下 👇
- 從輸入隱藏狀態中按列提取較大的值(離群值)。
- 對 FP16 中的離群值和 int8 中的非離群值進行矩陣乘法。
- 將非離群值結果放大以將值拉回到 FP16,並將其新增到 FP16 中的離群值結果中。
所以本質上,我們執行矩陣乘法以節省精度,然後將非離群值結果拉回 FP16,而不會在非離群值的初始值和縮放回的值之間產生很大的差異。您可以在下面看到一個示例 👇
您可以像下面這樣安裝 bitsandbytes 👇
pip install bitsandbytes
要在 transformers 中以 8 位載入模型,只需執行 👇
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
model_8bit = AutoModelForCausalLM.from_pretrained(name, device_map="auto", load_in_8bit=True)
tokenizer = AutoTokenizer.from_pretrained(name)
encoded_input = tokenizer(text, return_tensors='pt')
output_sequences = model.generate(input_ids=encoded_input['input_ids'].cuda())
print(tokenizer.decode(output_sequences[0], skip_special_tokens=True))
bitsandbytes 8 位量化的一個缺點是推理速度比 GPTQ 慢。
4 位浮點(FP4)和 4 位 NormalFloat(NF4)是兩種與 QLoRA 技術(一種引數高效微調技術)一起使用的資料型別。這些資料型別也可以用於在不使用 QLoRA 的情況下減小預訓練模型的大小。TGI 基本上在推理前使用這些資料型別進行訓練後量化。
與 8 位載入類似,您可以在 4 位中載入 transformers 模型,如下所示 👇
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("facebook/opt-350m", load_in_4bit=True, device_map="auto")
在 TGI 中,您可以透過將 --quantize
與以下值一起傳遞來使用 bitsandbytes 量化技術,以實現不同的量化方法
- 用於 8 位量化的 bitsandbytes
- 用於 4 位 NormalFloat 的 bitsandbytes-nf4
- 用於 4 位的 bitsandbytes-fp4,如下所示 👇
docker run --gpus all --shm-size 1g -p 8080:80 -v $volume:/data ghcr.io/huggingface/text-generation-inference:latest --model-id $model --quantize bitsandbytes
有用資源
您可以透過以下連結瞭解更多上述概念。