量化HuggingFace的Transformers 模型
量化 ?? Transformers 模型
原文地址:https://huggingface.co/docs/transformers/main/en/main_classes/quantization
AutoGPTQ
?集成
?? Transformers 已集成了?optimum
?API 以對語言模型執(zhí)行 GPTQ 量化。您可以在不大幅降低性能并提高推理速度的情況下,以 8、6、4 甚至 2 位加載并量化您的模型!大多數(shù) GPU 硬件都支持這一功能。
要了解有關(guān)量化模型的更多信息,請查閱:
GPTQ?論文
作為后端使用的?
AutoGPTQ
?庫
依賴庫
要運(yùn)行下面的代碼,您需要安裝以下依賴庫:
安裝最新的?
AutoGPTQ
?庫pip install auto-gptq
從源安裝最新的?
optimum
pip install git+https://github.com/huggingface/optimum.git
從源安裝最新的?
transformers
pip install git+https://github.com/huggingface/transformers.git
安裝最新的?
accelerate
?庫pip install --upgrade accelerate
目前,GPTQ 集成僅支持文本模型,對于視覺、語音或多模態(tài)模型,您可能會遇到意外的行為。
加載并量化模型
GPTQ 是一種量化方法,需要在使用量化模型之前進(jìn)行權(quán)重校準(zhǔn)。如果您想從頭開始量化 transformers 模型,可能需要一些時間才能產(chǎn)生量化模型(在 Google colab 上為?facebook/opt-350m
?模型大約需要 10 分鐘)。
因此,您可能會遇到兩種使用GPTQ-量化模型的場景。第一種情況是加載已經(jīng)被其他用戶量化并上傳到Hub的模型;第二種情況是從零開始量化您自己的模型,并保存或上傳到Hub,這樣其他用戶也能使用它。
GPTQ 配置
為了加載并量化模型,您需要創(chuàng)建一個 [GPTQConfig
]。您需要傳遞?bits
?的數(shù)量,一個?dataset
?以校準(zhǔn)量化和模型的?tokenizer
?以準(zhǔn)備數(shù)據(jù)集。
請注意,您可以將自己的數(shù)據(jù)集作為字符串列表傳遞。但強(qiáng)烈建議使用 GPTQ 論文中的數(shù)據(jù)集。
量化
您可以通過使用?from_pretrained
?并設(shè)置?quantization_config
?來量化模型。
請注意,您需要一個GPU來進(jìn)行模型的量化。我們會將模型放置在CPU中,并在GPU和CPU之間來回移動各個模塊以進(jìn)行量化。
如果您想在使用CPU offload的同時最大化您的GPU使用率,您可以設(shè)置?device_map = "auto"
。
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", quantization_config=gptq_config)
請注意,不支持磁盤 offload。此外,如果由于數(shù)據(jù)集而導(dǎo)致內(nèi)存不足,您可能需要在?from_pretained
?中傳遞?max_memory
。查看此指南以了解有關(guān)?device_map
?和?max_memory
?的更多信息。
目前,GPTQ 量化僅適用于文本模型。此外,根據(jù)硬件,量化過程可能需要很長時間(使用 NVIDIA A100 的 175B 模型 = 4 個 GPU 小時)。請檢查 Hub 上是否有該模型的 GPTQ 量化版本。如果沒有,您可以在 github 上提交需求。
將量化模型推送到 ?? Hub
您可以使用?push_to_hub
?將量化模型推送到 Hub,就像任何 ?? 模型一樣。量化配置將與模型一起保存并推送。
quantized_model.push_to_hub("opt-125m-gptq")tokenizer.push_to_hub("opt-125m-gptq")
1
2
如果您想將您的量化模型保存到本地計算機(jī),您也可以使用?save_pretrained
:
quantized_model.save_pretrained("opt-125m-gptq")tokenizer.save_pretrained("opt-125m-gptq")
如果您已使用device_map
量化了您的模型,在保存之前,請確保將整個模型移動到您的GPU之一或cpu
上。
quantized_model.to("cpu")quantized_model.save_pretrained("opt-125m-gptq")
從?? Hub加載量化模型
您可以使用from_pretrained
從Hub加載量化模型。
確保已推送的權(quán)重已量化,通過檢查模型配置對象中是否存在quantization_config
屬性。
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("{your_username}/opt-125m-gptq")
1
2
如果您希望更快地加載模型并且不分配比所需更多的內(nèi)存,device_map
參數(shù)也適用于量化模型。確保您已安裝accelerate
庫。
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("{your_username}/opt-125m-gptq", device_map="auto")
Exllama核心用于更快的推理
對于4位模型,您可以使用exllama核心以獲得更快的推理速度。它默認(rèn)是激活的。您可以通過在[GPTQConfig
]中傳遞disable_exllama
來改變這種行為。這將覆蓋存儲在配置中的量化配置。請注意,您只能覆蓋與核心相關(guān)的屬性。此外,如果您想使用exllama核心,您需要將整個模型放在gpu上。
import torch
gptq_config = GPTQConfig(bits=4, disable_exllama=False)model = AutoModelForCausalLM.from_pretrained("{your_username}/opt-125m-gptq", device_map="auto", quantization_config = gptq_config)
1
2
3
請注意,現(xiàn)在只支持4位模型。此外,如果您正在使用peft微調(diào)量化模型,建議禁用exllama核心。
微調(diào)量化模型
借助Hugging Face生態(tài)系統(tǒng)中對適配器的官方支持,您可以微調(diào)已使用GPTQ量化的模型。
請查看peft
庫以獲取更多詳細(xì)信息。
示例演示
查看Google Colab?筆記本?以學(xué)習(xí)如何使用GPTQ量化您的模型以及如何使用peft微調(diào)量化模型。
GPTQConfig
[[autodoc]] GPTQConfig
bitsandbytes
?集成
?? Transformers與bitsandbytes
上最常用的模塊緊密集成。您只需幾行代碼即可以8位精度加載模型。
自0.37.0
版本發(fā)布以來,大多數(shù)GPU硬件都支持此功能。
在LLM.int8()?論文或關(guān)于合作的博客文章中了解更多關(guān)于量化方法的信息。
自其0.39.0
版本發(fā)布以來,您可以使用4位量化加載任何支持device_map
的模型,利用FP4數(shù)據(jù)類型。
如果您想量化自己的pytorch模型,請查看來自?? Accelerate庫的文檔。
以下是您可以使用bitsandbytes
集成完成的操作:
通用使用
只要您的模型支持使用?? Accelerate加載并包含torch.nn.Linear
層,您就可以在調(diào)用[~PreTrainedModel.from_pretrained
]方法時使用load_in_8bit
或load_in_4bit
參數(shù)來量化模型。這應(yīng)適用于任何模式。
from transformers import AutoModelForCausalLM
model_8bit = AutoModelForCausalLM.from_pretrained("facebook/opt-350m", load_in_8bit=True)model_4bit = AutoModelForCausalLM.from_pretrained("facebook/opt-350m", load_in_4bit=True)
默認(rèn)情況下,所有其他模塊(例如torch.nn.LayerNorm
)將轉(zhuǎn)換為torch.float16
,但如果您想更改其dtype
,則可以覆蓋torch_dtype
參數(shù):
>>> import torch>>> from transformers import AutoModelForCausalLM>>> model_8bit = AutoModelForCausalLM.from_pretrained("facebook/opt-350m", load_in_8bit=True, torch_dtype=torch.float32)>>> model_8bit.model.decoder.layers[-1].final_layer_norm.weight.dtype
torch.float32
FP4 量化
要求
在運(yùn)行以下任何代碼片段之前,請確保已經(jīng)安裝了以下要求。
最新的?
bitsandbytes
?庫pip install bitsandbytes>=0.39.0
安裝最新的?
accelerate
pip install --upgrade accelerate
安裝最新的?
transformers
pip install --upgrade transformers
提示和最佳實(shí)踐
高級使用:?參考這個Google Colab筆記本以了解4位量化的高級用法以及所有可能的選項。
batch_size=1
的更快推理:?從bitsandbytes的0.40.0
版本開始,對于batch_size=1
,你可以受益于快速推理。查看這些發(fā)布說明,確保版本大于0.40.0
,以便開箱即用地使用此功能。訓(xùn)練:?根據(jù)QLoRA論文,對于訓(xùn)練4位基礎(chǔ)模型(例如使用LoRA適配器),應(yīng)使用
bnb_4bit_quant_type='nf4'
。推理:?對于推理,
bnb_4bit_quant_type
對性能影響不大。但為了與模型權(quán)重的一致性,請確保使用相同的bnb_4bit_compute_dtype
和torch_dtype
參數(shù)。
以4bit加載大型模型
使用load_in_4bit=True
調(diào)用?.from_pretrained
?方法時,您可以將內(nèi)存使用量減少4倍(大致)。
# pip install transformers accelerate bitsandbytesfrom transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "bigscience/bloom-1b7"tokenizer = AutoTokenizer.from_pretrained(model_id)model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", load_in_4bit=True)
1
2
3
4
5
6
7
請注意,一旦以4位加載了模型,目前無法將量化權(quán)重推送到Hub。還要注意,目前還不支持訓(xùn)練4位權(quán)重。但是您可以使用4位模型來訓(xùn)練額外的參數(shù),這將在下一節(jié)中介紹。
以8bit加載大型模型
您可以通過使用load_in_8bit=True
參數(shù)調(diào)用?.from_pretrained
?方法大致將內(nèi)存需求減半。
# pip install transformers accelerate bitsandbytesfrom transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "bigscience/bloom-1b7"tokenizer = AutoTokenizer.from_pretrained(model_id)model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", load_in_8bit=True)
然后,像通常使用[PreTrainedModel
]一樣使用你的模型。
你可以使用get_memory_footprint
方法檢查你的模型的內(nèi)存占用。
print(model.get_memory_footprint())
1
通過這種集成,我們能夠在較小的設(shè)備上加載大型模型并毫無問題地運(yùn)行它們。
請注意,一旦模型已經(jīng)以8位加載,目前無法將量化權(quán)重推送到Hub,除非您使用最新的transformers
和bitsandbytes
。還要注意,目前還不支持訓(xùn)練8位權(quán)重。但是您可以使用8位模型來訓(xùn)練額外的參數(shù),這將在下一節(jié)中介紹。
還要注意,device_map
是可選的,但是設(shè)置device_map = 'auto'
是推薦的,因為它會高效地將模型分派到可用的資源上。
高級用例
在這里,我們將介紹您可以使用FP4量化執(zhí)行的一些高級用例。
改變計算數(shù)據(jù)類型
計算數(shù)據(jù)類型用于改變計算期間使用的數(shù)據(jù)類型。例如,隱藏狀態(tài)可以是float32
,但計算可以設(shè)置為bf16以加速。默認(rèn)情況下,計算數(shù)據(jù)類型設(shè)置為float32
。
import torchfrom transformers import BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)
使用NF4(Normal Float 4)數(shù)據(jù)類型
你還可以使用NF4數(shù)據(jù)類型,這是一種新的4位數(shù)據(jù)類型,適用于使用正態(tài)分布初始化的權(quán)重。為此運(yùn)行:
from transformers import BitsAndBytesConfig
nf4_config = BitsAndBytesConfig(
? ?load_in_4bit=True,
? ?bnb_4bit_quant_type="nf4",)model_nf4 = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=nf4_config)
使用嵌套量化進(jìn)行更高效的內(nèi)存推理
我們還建議用戶使用嵌套量化技術(shù)。這可以節(jié)省更多的內(nèi)存,而不需要額外的性能 - 根據(jù)我們的經(jīng)驗觀察,這使得在NVIDIA-T4 16GB上以序列長度為1024、批量大小為1和梯度積累步驟為4進(jìn)行微調(diào)llama-13b模型成為可能。
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)
將量化模型推送到 ?? Hub
您可以通過簡單地使用?push_to_hub
?方法將一個量化模型推送到 Hub。這將首先推送量化配置文件,然后推送量化的模型權(quán)重。確保使用?bitsandbytes>0.37.2
?(在撰寫本文時,我們在?bitsandbytes==0.38.0.post1
?上測試過)來使用此功能。
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("bigscience/bloom-560m", device_map="auto", load_in_8bit=True)tokenizer = AutoTokenizer.from_pretrained("bigscience/bloom-560m")model.push_to_hub("bloom-560m-8bit")
強(qiáng)烈建議將8位模型推送到 Hub,尤其是大型模型。這將允許社區(qū)從內(nèi)存占用減少中受益,并例如在 Google Colab 上加載大型模型。
從 ?? Hub 加載一個量化模型
您可以使用?from_pretrained
?方法從 Hub 加載一個量化模型。確保推送的權(quán)重是量化的,通過檢查模型配置對象中是否存在?quantization_config
?屬性。
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("{your_username}/bloom-560m-8bit", device_map="auto")
1
2
3
注意,在這種情況下,您不需要指定?load_in_8bit=True
?參數(shù),但您需要確保已安裝?bitsandbytes
?和?accelerate
。同樣注意,device_map
?是可選的,但設(shè)置?device_map = 'auto'
?在推理時是首選,因為它會有效地將模型分派到可用的資源上。
高級用例
本節(jié)面向希望探索除了加載和運(yùn)行8位模型之外還可以做什么的高級用戶。
在?cpu
?和?gpu
?之間進(jìn)行卸載
這其中的一個高級用例是能夠加載一個模型并在?CPU
?和?GPU
?之間分派權(quán)重。請注意,將在 CPU 上分派的權(quán)重不會被轉(zhuǎn)換為8位,因此保持為?float32
。此功能面向希望適應(yīng)非常大的模型并在 GPU 和 CPU 之間分派模型的用戶。
首先,從?transformers
?加載一個 [BitsAndBytesConfig
],并將屬性?llm_int8_enable_fp32_cpu_offload
?設(shè)置為?True
:
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(llm_int8_enable_fp32_cpu_offload=True)
1
2
3
假設(shè)您想加載?bigscience/bloom-1b7
?模型,而您的 GPU RAM 只足夠適應(yīng)整個模型,除了?lm_head
。因此,如下所示編寫一個自定義的 device_map:
device_map = {
? ?"transformer.word_embeddings": 0,
? ?"transformer.word_embeddings_layernorm": 0,
? ?"lm_head": "cpu",
? ?"transformer.h": 0,
? ?"transformer.ln_f": 0,}
然后如下加載您的模型:
model_8bit = AutoModelForCausalLM.from_pretrained(
? ?"bigscience/bloom-1b7",
? ?device_map=device_map,
? ?quantization_config=quantization_config,)
就是這樣!盡情享受您的模型吧!
使用?llm_int8_threshold
?進(jìn)行玩耍
您可以使用?llm_int8_threshold
?參數(shù)更改離群值的閾值。"離群值"是一個隱藏狀態(tài)值,大于某個閾值。這對應(yīng)于?LLM.int8()
?論文中描述的離群值檢測的離群值閾值。任何超過此閾值的隱藏狀態(tài)值都將被視為離群值,這些值上的操作將以 fp16 進(jìn)行。值通常呈正態(tài)分布,即大多數(shù)值在范圍 [-3.5, 3.5] 內(nèi),但對于大型模型,有一些特殊的系統(tǒng)性離群值分布非常不同。這些離群值通常在區(qū)間 [-60, -6] 或 [6, 60] 內(nèi)。Int8 量化對于大約為5的值工作得很好,但超過此值,性能將受到重大影響。一個好的默認(rèn)閾值是6,但更不穩(wěn)定的模型(小模型,微調(diào))可能需要較低的閾值。這個參數(shù)可能會影響模型的推理速度。我們建議您玩弄這個參數(shù),找
到最適合您用例的值。
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
model_id = "bigscience/bloom-1b7"quantization_config = BitsAndBytesConfig(
? ?llm_int8_threshold=10,)model_8bit = AutoModelForCausalLM.from_pretrained(
? ?model_id,
? ?device_map=device_map,
? ?quantization_config=quantization_config,)tokenizer = AutoTokenizer.from_pretrained(model_id)
跳過某些模塊的轉(zhuǎn)換
有些模型有幾個模塊需要不轉(zhuǎn)換為8位以確保穩(wěn)定性。例如 Jukebox 模型有幾個?lm_head
?模塊應(yīng)該被跳過。使用?llm_int8_skip_modules
?進(jìn)行玩耍:
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
model_id = "bigscience/bloom-1b7"quantization_config = BitsAndBytesConfig(
? ?llm_int8_skip_modules=["lm_head"],)model_8bit = AutoModelForCausalLM.from_pretrained(
? ?model_id,
? ?device_map=device_map,
? ?quantization_config=quantization_config,)tokenizer = AutoTokenizer.from_pretrained(model_id)
微調(diào)已加載為8位的模型
憑借 Hugging Face 生態(tài)系統(tǒng)對適配器的官方支持,您可以微調(diào)已加載為8位的模型。這使得在單個 Google Colab 中微調(diào)大型模型,如?flan-t5-large
?或?facebook/opt-6.7b
?成為可能。請查看?peft
?庫以獲取更多詳細(xì)信息。
注意,加載模型進(jìn)行訓(xùn)練時,您不需要傳遞?device_map
。它將自動在您的 GPU 上加載您的模型。如有需要,您還可以將 device map 設(shè)置為特定的設(shè)備(例如?cuda:0
、0
、torch.device('cuda:0')
)。請注意,device_map=auto
?僅用于推理。
BitsAndBytesConfig
[[autodoc]] BitsAndBytesConfig
使用 ???optimum
?進(jìn)行量化
請查看?Optimum 文檔?以了解?optimum
?支持的量化方法,并查看這些是否適用于您的用例。