Quantize ð€ Transformers models
GPT-QModel Integration
ð€ Transformers ã«ã¯ãèšèªã¢ãã«ã§ GPTQ éååãå®è¡ããããã® optimum API ãçµ±åãããŠããŸããããã©ãŒãã³ã¹ãå€§å¹ ã«äœäžãããããšãªããæšè«é床ãé«éåããããšãªããã¢ãã«ã 8ã4ã3ãããã«ã¯ 2 ãããã§ããŒãããã³éååã§ããŸããããã¯ãã»ãšãã©ã® GPU ããŒããŠã§ã¢ã§ãµããŒããããŠããŸãã
éååã¢ãã«ã®è©³çްã«ã€ããŠã¯ã以äžã確èªããŠãã ããã
è«æ
GPTQ éååã«é¢ãã optimum
ããã¯ãšã³ããšããŠäœ¿çšããã GPT-QModel (
https://github.com/ModelCloud/GPTQModel
) ã©ã€ãã©ãª
Requirements
以äžã®ã³ãŒããå®è¡ããã«ã¯ã以äžã®èŠä»¶ãã€ã³ã¹ããŒã«ãããŠããå¿ èŠããããŸãïŒ
ææ°ã® GPT-QModel ã©ã€ãã©ãªãã€ã³ã¹ããŒã«ããã pip install gptqmodel --no-build-isolation ãå®è¡ããã
ææ°ã® optimum ããœãŒã¹ããã€ã³ã¹ããŒã«ããã git+https://github.com/huggingface/optimum.git ãã€ã³ã¹ããŒã«ããã
ææ°ã® transformers ããœãŒã¹ããã€ã³ã¹ããŒã«ããã ææ°ã® transformers ããœãŒã¹ããã€ã³ã¹ããŒã«ãã pip install git+https://github.com/huggingface/transformers.git
ææ°ã® accelerate ã©ã€ãã©ãªãã€ã³ã¹ããŒã«ããã pip install --upgrade accelerate ãå®è¡ããã
GPTQçµ±åã¯ä»ã®ãšããããã¹ãã¢ãã«ã®ã¿ããµããŒãããŠããã®ã§ãèŠèŠãé³å£°ããã«ãã¢ãŒãã«ã¢ãã«ã§ã¯äºæãã¬æåã«ééãããããããªãããšã«æ³šæããŠãã ããã
Load and quantize a model
GPTQ ã¯ãéååã¢ãã«ã䜿çšããåã«éã¿ã®ãã£ãªãã¬ãŒã·ã§ã³ãå¿ èŠãšããéååæ¹æ³ã§ãããã©ã³ã¹ãã©ãŒã㌠ã¢ãã«ãæåããéååããå Žåã¯ãéååã¢ãã«ãäœæãããŸã§ã«æéããããããšããããŸã (facebook/opt-350mã¢ãã«ã® Google colab ã§ã¯çŽ 5 å)ã
ãããã£ãŠãGPTQ éååã¢ãã«ã䜿çšããã·ããªãªã¯ 2 ã€ãããŸããæåã®äœ¿çšäŸã¯ãããã§å©çšå¯èœãªä»ã®ãŠãŒã¶ãŒã«ãã£ãŠãã§ã«éååãããã¢ãã«ãããŒãããããšã§ãã2 çªç®ã®äœ¿çšäŸã¯ãã¢ãã«ãæåããéååããä¿åãããããã«ããã·ã¥ããŠãä»ã®ãŠãŒã¶ãŒã䜿çšã§ããããã«ããããšã§ããããã䜿ã£ãŠãã ããã
GPTQ Configuration
ã¢ãã«ãããŒãããŠéååããã«ã¯ã
ãäœæããå¿ èŠããããŸããããŒã¿ã»ãããæºåããã«ã¯ãbitsã®æ°ãéååã調æŽããããã®datasetãããã³ã¢ãã«ã®Tokenizerãæž¡ãå¿ èŠããããŸãã
model_id = "facebook/opt-125m" tokenizer = AutoTokenizer.from_pretrained(model_id) gptq_config = GPTQConfig(bits=4, dataset = "c4", tokenizer=tokenizer)ç¬èªã®ããŒã¿ã»ãããæååã®ãªã¹ããšããŠæž¡ãããšãã§ããããšã«æ³šæããŠãã ããããã ããGPTQ è«æã®ããŒã¿ã»ããã䜿çšããããšã匷ããå§ãããŸãã
dataset = ["gptqmodel is an easy-to-use model quantization library with user-friendly apis, based on the GPTQ algorithm."] quantization = GPTQConfig(bits=4, dataset = dataset, tokenizer=tokenizer)Quantization
from_pretrained ã䜿çšããquantization_config ãèšå®ããããšã§ã¢ãã«ãéååã§ããŸãã
from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=gptq_config)ã¢ãã«ãéååããã«ã¯ GPU ãå¿ èŠã§ããããšã«æ³šæããŠãã ãããã¢ãã«ã CPU ã«é 眮ããéååããããã«ã¢ãžã¥ãŒã«ã GPU ã«ååŸã«ç§»åãããŸãã
CPU ãªãããŒãã®äœ¿çšäžã« GPU ã®äœ¿çšéãæå€§åãããå Žåã¯ãdevice_map = "auto" ãèšå®ã§ããŸãã
from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", quantization_config=gptq_config)ãã£ã¹ã¯ ãªãããŒãã¯ãµããŒããããŠããªãããšã«æ³šæããŠãã ãããããã«ãããŒã¿ã»ãããåå ã§ã¡ã¢ãªãäžè¶³ããŠããå Žåã¯ãfrom_pretained ã§ max_memory ãæž¡ãå¿ èŠãããå ŽåããããŸãã device_mapãšmax_memoryã®è©³çްã«ã€ããŠã¯ããã®
ãåç §ããŠãã ããã
GPTQ éååã¯ãçŸæç¹ã§ã¯ããã¹ã ã¢ãã«ã§ã®ã¿æ©èœããŸããããã«ãéååããã»ã¹ã¯ããŒããŠã§ã¢ã«ãã£ãŠã¯é·æéãããå ŽåããããŸã (NVIDIA A100 ã䜿çšããå Žåã175B ã¢ãã« = 4 gpu æé)ãã¢ãã«ã® GPTQ éååããŒãžã§ã³ãååšããªãå Žåã¯ãããã§ç¢ºèªããŠãã ãããããã§ãªãå Žåã¯ãgithub ã§èŠæ±ãéä¿¡ã§ããŸãã
Push quantized model to ð€ Hub
ä»ã® ð€ ã¢ãã«ãšåæ§ã«ãpush_to_hub ã䜿çšããŠéååã¢ãã«ãããã«ããã·ã¥ã§ããŸããéååæ§æã¯ä¿åãããã¢ãã«ã«æ²¿ã£ãŠããã·ã¥ãããŸãã
quantized_model.push_to_hub("opt-125m-gptq") tokenizer.push_to_hub("opt-125m-gptq")éååãããã¢ãã«ãããŒã«ã« ãã·ã³ã«ä¿åãããå Žåã¯ã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")Load a quantized model from the ð€ Hub
from_pretrainedã䜿çšããŠãéååãããã¢ãã«ãããããããŒãã§ããŸãã 屿§ quantization_config ãã¢ãã«èšå®ãªããžã§ã¯ãã«ååšããããšã確èªããŠãããã·ã¥ãããéã¿ãéååãããŠããããšã確èªããŸãã
from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("{your_username}/opt-125m-gptq")å¿ èŠä»¥äžã®ã¡ã¢ãªãå²ãåœãŠãã«ã¢ãã«ãããéãããŒããããå Žåã¯ãdevice_map åŒæ°ã¯éååã¢ãã«ã§ãæ©èœããŸãã accelerateã©ã€ãã©ãªãã€ã³ã¹ããŒã«ãããŠããããšã確èªããŠãã ããã
from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("{your_username}/opt-125m-gptq", device_map="auto")Exllama kernels for faster inference
4 ããã ã¢ãã«ã®å Žåãæšè«é床ãé«ããããã« exllama ã«ãŒãã«ã䜿çšã§ããŸããããã©ã«ãã§æå¹ã«ãªã£ãŠããŸãã
ã§ disable_exllama ãæž¡ãããšã§ããã®åäœã倿Žã§ããŸããããã«ãããèšå®ã«ä¿åãããŠããéååèšå®ãäžæžããããŸããã«ãŒãã«ã«é¢é£ãã屿§ã®ã¿ãäžæžãã§ããããšã«æ³šæããŠãã ãããããã«ã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)çŸæç¹ã§ã¯ 4 ããã ã¢ãã«ã®ã¿ããµããŒããããŠããããšã«æ³šæããŠãã ãããããã«ãpeft ã䜿çšããŠéååã¢ãã«ã埮調æŽããŠããå Žåã¯ãexllama ã«ãŒãã«ãéã¢ã¯ãã£ãåããããšããå§ãããŸãã
Fine-tune a quantized model
Hugging Face ãšã³ã·ã¹ãã ã®ã¢ããã¿ãŒã®å ¬åŒãµããŒãã«ãããGPTQ ã§éååãããã¢ãã«ã埮調æŽã§ããŸãã 詳现ã«ã€ããŠã¯ã
ã©ã€ãã©ãªãã芧ãã ããã
Example demo
GPTQ ã䜿çšããŠã¢ãã«ãéååããæ¹æ³ãšãpeft ã䜿çšããŠéååãããã¢ãã«ã埮調æŽããæ¹æ³ã«ã€ããŠã¯ãGoogle Colab
ãåç §ããŠãã ããã
GPTQConfig
classtransformers.GPTQConfig
(bits: inttokenizer: typing.Any = Nonedataset: list[str] | str | None = Nonegroup_size: int = 128damp_percent: float = 0.1desc_act: bool = Falseact_group_aware: bool = Truesym: bool = Truetrue_sequential: bool = Trueformat: str = 'gptq'meta: dict[str, typing.Any] | None = Nonebackend: str | None = Nonemodel_seqlen: int | None = Noneblock_name_to_quantize: str | None = Nonemodule_name_preceding_first_block: list[str] | None = Nonebatch_size: int = 1pad_token_id: int | None = Nonemax_input_length: int | None = Nonecache_block_outputs: bool = Truemodules_in_block_to_quantize: list[list[str]] | None = None**kwargs)
Parameters
bits (int) â The number of bits to quantize to, supported numbers are (2, 3, 4, 8).
tokenizer (str or PreTrainedTokenizerBase, optional) â The tokenizer used to process the dataset. You can pass either: A custom tokenizer object.
A string, the model id of a predefined tokenizer hosted inside a model repo on huggingface.co.
A path to a directory containing vocabulary files required by the tokenizer, for instance saved using the
method, e.g., ./my_model_directory/.
dataset (Union[list[str]], optional) â The dataset used for quantization. You can provide your own dataset in a list of string or just use the original datasets used in GPTQ paper [âwikitext2â,âc4â,âc4-newâ]
group_size (int, optional, defaults to 128) â The group size to use for quantization. Recommended value is 128 and -1 uses per-column quantization.
damp_percent (float, optional, defaults to 0.1) â The percent of the average Hessian diagonal to use for dampening. Recommended value is 0.1.
desc_act (bool, optional, defaults to False) â Whether to quantize columns in order of decreasing activation size. Setting it to False can significantly speed up inference but the perplexity may become slightly worse. Also known as act-order.
act_group_aware (bool, optional, defaults to True) â Use GAR (group aware activation order) during quantization. Has measurable positive impact on quantization quality. Only applicable when desc_act = False. Will forced to be False when desc_act = True.
sym (bool, optional, defaults to True) â Whether to use symmetric quantization.
true_sequential (bool, optional, defaults to True) â Whether to perform sequential quantization even within a single Transformer block. Instead of quantizing the entire block at once, we perform layer-wise quantization. As a result, each layer undergoes quantization using inputs that have passed through the previously quantized layers.
format (str, optional, defaults to "gptq") â GPTQ weight format. gptq (v1) is supported by gptqmodel. gptq_v2 is gptqmodel only.
meta (dict[str, any], optional) â Properties, such as tooling:version, that do not directly contributes to quantization or quant inference are stored in meta. i.e. meta.quantizer: [âoptimum:versionâ, âgptqmodel:versionâ]
backend (str, optional) â Controls which kernel to use. Valid values for gptqmodel are auto, auto_trainable and more. Ref gptqmodel backends:
https://github.com/ModelCloud/GPTQModel/blob/main/gptqmodel/utils/backend.py
model_seqlen (int, optional) â The maximum sequence length that the model can take.
block_name_to_quantize (str, optional) â The transformers block name to quantize. If None, we will infer the block name using common patterns (e.g. model.layers)
module_name_preceding_first_block (list[str], optional) â The layers that are preceding the first Transformer block.
batch_size (int, optional, defaults to 1) â The batch size used when processing the dataset
pad_token_id (int, optional) â The pad token id. Needed to prepare the dataset when batch_size > 1.
max_input_length (int, optional) â The maximum input length. This is needed to initialize a buffer that depends on the maximum expected input length. It is specific to the exllama backend with act-order.
cache_block_outputs (bool, optional, defaults to True) â Whether to cache block outputs to reuse as inputs for the succeeding block.
modules_in_block_to_quantize (list[list[str]], optional) â List of list of module names to quantize in the specified block. This argument is useful to exclude certain linear modules from being quantized. The block to quantize can be specified by setting block_name_to_quantize. We will quantize each list sequentially. If not set, we will quantize all linear layers. Example: modules_in_block_to_quantize =[["self_attn.k_proj", "self_attn.v_proj", "self_attn.q_proj"], ["self_attn.o_proj"]]. In this example, we will first quantize the q,k,v layers simultaneously since they are independent. Then, we will quantize self_attn.o_proj layer with the q,k,v layers quantized. This way, we will get better results since it reflects the real input self_attn.o_proj will get when the model is quantized.
This is a wrapper class about all possible attributes and features that you can play with a model that has been loaded using optimum api for GPTQ quantization relying on the gptqmodel backend.
Get compatible class with optimum gptq config dict
Safety checker that arguments are correct
Get compatible dict for optimum gptq config
bitsandbytes Integration
ð€ Transformers ã¯ãbitsandbytes ã§æããã䜿çšãããã¢ãžã¥ãŒã«ãšç·å¯ã«çµ±åãããŠããŸããæ°è¡ã®ã³ãŒãã§ã¢ãã«ã 8 ããã粟床ã§ããŒãã§ããŸãã ããã¯ãbitsandbytesã® 0.37.0ãªãªãŒã¹ä»¥éãã»ãšãã©ã® GPU ããŒããŠã§ã¢ã§ãµããŒããããŠããŸãã
éååæ¹æ³ã®è©³çްã«ã€ããŠã¯ã
è«æããŸãã¯
ãã芧ãã ãããçµ±åïŒã³ã©ãã¬ãŒã·ã§ã³ã«ã€ããŠã
0.39.0ãªãªãŒã¹ä»¥éãFP4 ããŒã¿åãæŽ»çšãã4 ãããéååã䜿çšããŠdevice_mapããµããŒãããä»»æã®ã¢ãã«ãããŒãã§ããŸãã
ç¬èªã® pytorch ã¢ãã«ãéååãããå Žåã¯ãð€ Accelerate ã©ã€ãã©ãªã®
ããã§ãã¯ããŠãã ããã
bitsandbytesçµ±åã䜿çšããŠã§ããããšã¯æ¬¡ã®ãšããã§ã
General usage
ã¢ãã«ã ð€ Accelerate ã«ããèªã¿èŸŒã¿ããµããŒãããtorch.nn.Linear ã¬ã€ã€ãŒãå«ãŸããŠããéãã
ã¡ãœãããåŒã³åºããšãã« load_in_8bit ãŸã㯠load_in_4bit åŒæ°ã䜿çšããŠã¢ãã«ãéååã§ããŸããããã¯ã©ã®ãããªã¢ããªãã£ã§ãåæ§ã«æ©èœããã¯ãã§ãã
from transformers import AutoModelForCausalLM, BitsAndBytesConfig model_8bit = AutoModelForCausalLM.from_pretrained("facebook/opt-350m", quantization_config=BitsAndBytesConfig(load_in_8bit=True)) model_4bit = AutoModelForCausalLM.from_pretrained("facebook/opt-350m", quantization_config=BitsAndBytesConfig(load_in_4bit=True))ããã©ã«ãã§ã¯ãä»ã®ãã¹ãŠã®ã¢ãžã¥ãŒã« (äŸ: torch.nn.LayerNorm) 㯠torch.float16 ã«å€æãããŸããããã® dtype ã倿Žãããå Žåã¯ãdtype åŒæ°ãäžæžãã§ããŸãã
>>> import torch >>> from transformers import AutoModelForCausalLM >>> model_8bit = AutoModelForCausalLM.from_pretrained("facebook/opt-350m", quantization_config=BitsAndBytesConfig(load_in_8bit=True), dtype=torch.float32) >>> model_8bit.model.decoder.layers[-1].final_layer_norm.weight.dtype torch.float32FP4 quantization
Requirements
以äžã®ã³ãŒã ã¹ãããããå®è¡ããåã«ã以äžã®èŠä»¶ãã€ã³ã¹ããŒã«ãããŠããããšã確èªããŠãã ããã
ææ°ã®bitsandbytesã©ã€ãã©ãª pip install bitsandbytes>=0.39.0
ææ°ã®accelerateãã€ã³ã¹ããŒã«ãã pip install --upgrade accelerate
ææ°ã® transformers ãã€ã³ã¹ããŒã«ãã pip install --upgrade transformers
Tips and best practices
é«åºŠãªäœ¿çšæ³: å¯èœãªãã¹ãŠã®ãªãã·ã§ã³ã䜿çšãã 4 ãããéååã®é«åºŠãªäœ¿çšæ³ã«ã€ããŠã¯ã
ãã® Google Colab ããŒãããã¯
ãåç §ããŠãã ããã
batch_size=1 ã«ããé«éæšè« : bitsandbytes ã® 0.40.0 ãªãªãŒã¹ä»¥éãbatch_size=1 ã§ã¯é«éæšè«ã®æ©æµãåããããšãã§ããŸãã
ãããã®ãªãªãŒã¹ ããŒã
ã確èªãããã®æ©èœã掻çšããã«ã¯0.40.0以éã®ããŒãžã§ã³ã䜿çšããŠããããšã確èªããŠãã ãããç®±ã®ã
ãã¬ãŒãã³ã°:
ã«ãããšã4 ãããåºæ¬ã¢ãã«ããã¬ãŒãã³ã°ããå Žå (äŸ: LoRA ã¢ããã¿ãŒã䜿çš)ãbnb_4bit_quant_type='nf4' ã䜿çšããå¿ èŠããããŸãã ã
æšè«: æšè«ã®å Žåãbnb_4bit_quant_type ã¯ããã©ãŒãã³ã¹ã«å€§ããªåœ±é¿ãäžããŸããããã ããã¢ãã«ã®éã¿ãšã®äžè²«æ§ãä¿ã€ããã«ãå¿ ãåã bnb_4bit_compute_dtype ããã³ dtype åŒæ°ã䜿çšããŠãã ããã
Load a large model in 4bit
.from_pretrained ã¡ãœãããåŒã³åºããšãã« load_in_4bit=True ã䜿çšãããšãã¡ã¢ãªäœ¿çšéã (ãããã) 4 ã§å²ãããšãã§ããŸãã
from transformers import AutoModelForCausalLM, AutoTokenizer model_id = "bigscience/bloom-1b7" tokenizer = AutoTokenizer.from_pretrained(model_id) model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", quantization_config=BitsAndBytesConfig(load_in_4bit=True))ã¢ãã«ã 4 ãããã§ããŒãããããšãçŸæç¹ã§ã¯éååãããéã¿ãããã«ããã·ã¥ããããšã¯ã§ããªãããšã«æ³šæããŠãã ããã 4 ãããã®éã¿ã¯ãŸã ãµããŒããããŠããªãããããã¬ãŒãã³ã°ã§ããªãããšã«ã泚æããŠãã ããããã ãã4 ããã ã¢ãã«ã䜿çšããŠè¿œå ã®ãã©ã¡ãŒã¿ãŒããã¬ãŒãã³ã°ããããšãã§ããŸããããã«ã€ããŠã¯æ¬¡ã®ã»ã¯ã·ã§ã³ã§èª¬æããŸãã
Load a large model in 8bit
.from_pretrained ã¡ãœãããåŒã³åºããšãã« load_in_8bit=True åŒæ°ã䜿çšãããšãã¡ã¢ãªèŠä»¶ããããååã«ããŠã¢ãã«ãããŒãã§ããŸãã
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig model_id = "bigscience/bloom-1b7" tokenizer = AutoTokenizer.from_pretrained(model_id) model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=BitsAndBytesConfig(load_in_8bit=True))次ã«ãéåžž
ã䜿çšããã®ãšåãããã«ã¢ãã«ã䜿çšããŸãã
get_memory_footprint ã¡ãœããã䜿çšããŠãã¢ãã«ã®ã¡ã¢ãª ãããããªã³ãã確èªã§ããŸãã
print(model.get_memory_footprint())ãã®çµ±åã«ããã倧ããªã¢ãã«ãå°ããªããã€ã¹ã«ããŒãããåé¡ãªãå®è¡ã§ããããã«ãªããŸããã
ã¢ãã«ã 8 ãããã§ããŒãããããšãææ°ã® `transformers`ãš`bitsandbytes`ã䜿çšããå Žåãé€ããéååãããéã¿ãããã«ããã·ã¥ããããšã¯çŸåšäžå¯èœã§ããããšã«æ³šæããŠãã ããã 8 ãããã®éã¿ã¯ãŸã ãµããŒããããŠããªãããããã¬ãŒãã³ã°ã§ããªãããšã«ã泚æããŠãã ããããã ãã8 ããã ã¢ãã«ã䜿çšããŠè¿œå ã®ãã©ã¡ãŒã¿ãŒããã¬ãŒãã³ã°ããããšãã§ããŸããããã«ã€ããŠã¯æ¬¡ã®ã»ã¯ã·ã§ã³ã§èª¬æããŸãã ãŸãã`device_map` ã¯ãªãã·ã§ã³ã§ãããå©çšå¯èœãªãªãœãŒã¹äžã§ã¢ãã«ãå¹ççã«ãã£ã¹ããããããããæšè«ã«ã¯ `device_map = 'auto'` ãèšå®ããããšãæšå¥šãããŸãã
Advanced use cases
ããã§ã¯ãFP4 éååã䜿çšããŠå®è¡ã§ããããã€ãã®é«åºŠãªäœ¿çšäŸã«ã€ããŠèª¬æããŸãã
Change the compute dtypecompute dtype ã¯ãèšç®äžã«äœ¿çšããã dtype ã倿Žããããã«äœ¿çšãããŸããããšãã°ãé ãç¶æ ã¯float32ã«ãããŸãããé«éåã®ããã«èšç®ã bf16 ã«èšå®ã§ããŸããããã©ã«ãã§ã¯ãcompute dtype 㯠float32 ã«èšå®ãããŸãã
import torch from transformers import BitsAndBytesConfig quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)Using NF4 (Normal Float 4) data typeNF4 ããŒã¿åã䜿çšããããšãã§ããŸããããã¯ãæ£èŠååžã䜿çšããŠåæåãããéã¿ã«é©åããæ°ãã 4 ããã ããŒã¿åã§ãããã®å®è¡ã®ããã«:
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)Use nested quantization for more memory efficient inferenceãŸãããã¹ããããéååææ³ã䜿çšããããšããå§ãããŸããããã«ãããããã©ãŒãã³ã¹ã远å ããããšãªããããå€ãã®ã¡ã¢ãªãç¯çŽãããŸããçµéšçãªèгå¯ãããããã«ãããNVIDIA-T4 16GB äžã§ã·ãŒã±ã³ã¹é· 1024ãããã ãµã€ãº 1ãåŸé 环ç©ã¹ããã 4 ã® 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)Push quantized models on the ð€ Hub
push_to_hubã¡ãœãããåçŽã«äœ¿çšããããšã§ãéååãããã¢ãã«ãããã«ããã·ã¥ã§ããŸããããã«ãããæåã«éååæ§æãã¡ã€ã«ãããã·ã¥ãããæ¬¡ã«éååãããã¢ãã«ã®éã¿ãããã·ã¥ãããŸãã ãã®æ©èœã䜿çšã§ããããã«ããã«ã¯ãå¿ ã bitsandbytes>0.37.2 ã䜿çšããŠãã ãã (ãã®èšäºã®å·çæç¹ã§ã¯ãbitsandbytes==0.38.0.post1 ã§ãã¹ãããŸãã)ã
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig model = AutoModelForCausalLM.from_pretrained("bigscience/bloom-560m", quantization_config=BitsAndBytesConfig(load_in_8bit=True)) tokenizer = AutoTokenizer.from_pretrained("bigscience/bloom-560m") model.push_to_hub("bloom-560m-8bit")å€§èŠæš¡ãªã¢ãã«ã§ã¯ãããäžã§ 8 ããã ã¢ãã«ãããã·ã¥ããããšãåŒ·ãæšå¥šãããŸããããã«ãããã³ãã¥ããã£ã¯ã¡ã¢ãª ãããããªã³ãã®åæžãšãããšãã° Google Colab ã§ã®å€§èŠæš¡ãªã¢ãã«ã®èªã¿èŸŒã¿ã«ããæ©æµãåããããšãã§ããŸãã
Load a quantized model from the ð€ Hub
from_pretrainedã¡ãœããã䜿çšããŠãããããéååã¢ãã«ãããŒãã§ããŸãã屿§ quantization_config ãã¢ãã«èšå®ãªããžã§ã¯ãã«ååšããããšã確èªããŠãããã·ã¥ãããéã¿ãéååãããŠããããšã確èªããŸãã
from transformers import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained("{your_username}/bloom-560m-8bit", device_map="auto")ãã®å ŽåãåŒæ° load_in_8bit=True ãæå®ããå¿ èŠã¯ãããŸããããbitsandbytes ãš accelerate ãã€ã³ã¹ããŒã«ãããŠããããšã確èªããå¿ èŠãããããšã«æ³šæããŠãã ããã ãŸããdevice_map ã¯ãªãã·ã§ã³ã§ãããå©çšå¯èœãªãªãœãŒã¹äžã§ã¢ãã«ãå¹ççã«ãã£ã¹ããããããããæšè«ã«ã¯ device_map = 'auto' ãèšå®ããããšãæšå¥šãããŸãã
Advanced use cases
ãã®ã»ã¯ã·ã§ã³ã¯ã8 ããã ã¢ãã«ã®ããŒããšå®è¡ä»¥å€ã«äœãã§ããããæ¢æ±ãããäžçŽãŠãŒã¶ãŒã察象ãšããŠããŸãã
Offload between cpu and gpu
ãã®é«åºŠãªäœ¿çšäŸã® 1 ã€ã¯ãã¢ãã«ãããŒãããCPUãšGPUã®éã§éã¿ããã£ã¹ãããã§ããããšã§ãã CPU äžã§ãã£ã¹ããããããéã¿ã¯ 8 ãããã«å€æãããªããããfloat32ã«ä¿æãããããšã«æ³šæããŠãã ããããã®æ©èœã¯ãéåžžã«å€§èŠæš¡ãªã¢ãã«ãé©åããããã®ã¢ãã«ã GPU ãš CPU ã®éã§ãã£ã¹ãããããããŠãŒã¶ãŒã察象ãšããŠããŸãã
ãŸããtransformers ãã
ãããŒããã屿§ llm_int8_enable_fp32_cpu_offload ã True ã«èšå®ããŸãã
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig quantization_config = BitsAndBytesConfig(llm_int8_enable_fp32_cpu_offload=True)bigscience/bloom-1b7ã¢ãã«ãããŒãããå¿ èŠããããlm_headãé€ãã¢ãã«å šäœã«ââé©åããã®ã«åå㪠GPU RAM ããããšããŸãããããã£ãŠã次ã®ããã«ã«ã¹ã¿ã 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, )以äžã§ãïŒã¢ãã«ã楜ããã§ãã ããïŒ
Play with llm_int8_threshold
llm_int8_threshold åŒæ°ãæäœããŠãå€ãå€ã®ãããå€ã倿Žã§ããŸãã å€ãå€ ãšã¯ãç¹å®ã®ãããå€ãã倧ããé ããç¶æ ã®å€ã§ãã ããã¯ãLLM.int8()è«æã§èª¬æãããŠããå€ã倿€åºã®å€ãå€ãããå€ã«å¯Ÿå¿ããŸãããã®ãããå€ãè¶ ããé ãç¶æ ã®å€ã¯å€ãå€ãšã¿ãªããããããã®å€ã«å¯Ÿããæäœã¯ fp16 ã§å®è¡ãããŸããéåžžãå€ã¯æ£èŠååžããŸããã€ãŸããã»ãšãã©ã®å€ã¯ [-3.5, 3.5] ã®ç¯å²å ã«ãããŸãããå€§èŠæš¡ãªã¢ãã«ã§ã¯å€§ããç°ãªãååžã瀺ãäŸå€çãªç³»çµ±çå€ãå€ãããã€ããããŸãããããã®å€ãå€ã¯ãå€ãã®å Žå [-60, -6] ãŸã㯠[6, 60] ã®ç¯å²å ã«ãããŸãã Int8 éååã¯ã倧ããã 5 çšåºŠãŸã§ã®å€ã§ã¯ããŸãæ©èœããŸããããããè¶ ãããšãããã©ãŒãã³ã¹ãå€§å¹ ã«äœäžããŸããé©åãªããã©ã«ãã®ãããå€ã¯ 6 ã§ãããããäžå®å®ãªã¢ãã« (å°èŠæš¡ãªã¢ãã«ã埮調æŽ) ã§ã¯ãããäœããããå€ãå¿ èŠã«ãªãå ŽåããããŸãã ãã®åŒæ°ã¯ãã¢ãã«ã®æšè«é床ã«åœ±é¿ãäžããå¯èœæ§ããããŸãããã®ãã©ã¡ãŒã¿ã詊ããŠã¿ãŠããŠãŒã¹ã±ãŒã¹ã«æé©ãªãã©ã¡ãŒã¿ãèŠã€ããããšããå§ãããŸãã
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)Skip the conversion of some modules
äžéšã®ã¢ãã«ã«ã¯ãå®å®æ§ã確ä¿ããããã« 8 ãããã«å€æããå¿ èŠããªãã¢ãžã¥ãŒã«ãããã€ããããŸããããšãã°ããžã¥ãŒã¯ããã¯ã¹ ã¢ãã«ã«ã¯ãã¹ãããããå¿ èŠãããããã€ãã® lm_head ã¢ãžã¥ãŒã«ããããŸãã llm_int8_skip_modules ã§éãã§ã¿ã
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)Fine-tune a model that has been loaded in 8-bit
Hugging Face ãšã³ã·ã¹ãã ã®ã¢ããã¿ãŒã®å ¬åŒãµããŒãã«ããã8 ãããã§ããŒããããã¢ãã«ã埮調æŽã§ããŸãã ããã«ãããåäžã® Google Colab ã§flan-t5-largeãfacebook/opt-6.7bãªã©ã®å€§èŠæš¡ã¢ãã«ã埮調æŽããããšãã§ããŸãã詳现ã«ã€ããŠã¯ã
ã©ã€ãã©ãªãã芧ãã ããã
ãã¬ãŒãã³ã°çšã®ã¢ãã«ãããŒããããšãã« device_map ãæž¡ãå¿ èŠããªãããšã«æ³šæããŠãã ãããã¢ãã«ã GPU ã«èªåçã«ããŒããããŸããå¿ èŠã«å¿ããŠãããã€ã¹ ããããç¹å®ã®ããã€ã¹ã«èšå®ããããšãã§ããŸã (äŸ: cuda:0ã0ãtorch.device('cuda:0'))ã device_map=autoã¯æšè«ã®ã¿ã«äœ¿çšããå¿ èŠãããããšã«æ³šæããŠãã ããã
BitsAndBytesConfig
classtransformers.BitsAndBytesConfig
(load_in_8bit = Falseload_in_4bit = Falsellm_int8_threshold = 6.0llm_int8_skip_modules = Nonellm_int8_enable_fp32_cpu_offload = Falsellm_int8_has_fp16_weight = Falsebnb_4bit_compute_dtype = Nonebnb_4bit_quant_type = 'fp4'bnb_4bit_use_double_quant = Falsebnb_4bit_quant_storage = None**kwargs)
Parameters
load_in_8bit (bool, optional, defaults to False) â This flag is used to enable 8-bit quantization with LLM.int8().
load_in_4bit (bool, optional, defaults to False) â This flag is used to enable 4-bit quantization by replacing the Linear layers with FP4/NF4 layers from bitsandbytes.
llm_int8_threshold (float, optional, defaults to 6.0) â This corresponds to the outlier threshold for outlier detection as described in LLM.int8() : 8-bit Matrix Multiplication for Transformers at Scale paper:
https://huggingface.co/papers/2208.07339
Any hidden states value that is above this threshold will be considered an outlier and the operation on those values will be done in fp16. Values are usually normally distributed, that is, most values are in the range [-3.5, 3.5], but there are some exceptional systematic outliers that are very differently distributed for large models. These outliers are often in the interval [-60, -6] or [6, 60]. Int8 quantization works well for values of magnitude ~5, but beyond that, there is a significant performance penalty. A good default threshold is 6, but a lower threshold might be needed for more unstable models (small models, fine-tuning).
llm_int8_skip_modules (list[str], optional) â An explicit list of the modules that we do not want to convert in 8-bit. This is useful for models such as Jukebox that has several heads in different places and not necessarily at the last position. For example for CausalLM models, the last lm_head is kept in its original dtype.
llm_int8_enable_fp32_cpu_offload (bool, optional, defaults to False) â This flag is used for advanced use cases and users that are aware of this feature. If you want to split your model in different parts and run some parts in int8 on GPU and some parts in fp32 on CPU, you can use this flag. This is useful for offloading large models such as google/flan-t5-xxl. Note that the int8 operations will not be run on CPU.
llm_int8_has_fp16_weight (bool, optional, defaults to False) â This flag runs LLM.int8() with 16-bit main weights. This is useful for fine-tuning as the weights do not have to be converted back and forth for the backward pass.
bnb_4bit_compute_dtype (torch.dtype or str, optional, defaults to torch.float32) â This sets the computational type which might be different than the input type. For example, inputs might be fp32, but computation can be set to bf16 for speedups.
bnb_4bit_quant_type (str, optional, defaults to "fp4") â This sets the quantization data type in the bnb.nn.Linear4Bit layers. Options are FP4 and NF4 data types which are specified by fp4 or nf4.
bnb_4bit_use_double_quant (bool, optional, defaults to False) â This flag is used for nested quantization where the quantization constants from the first quantization are quantized again.
bnb_4bit_quant_storage (torch.dtype or str, optional, defaults to torch.uint8) â This sets the storage type to pack the quantized 4-bit params.
kwargs (dict[str, Any], optional) â Additional parameters from which to initialize the configuration object.
This is a wrapper class about all possible attributes and features that you can play with a model that has been loaded using bitsandbytes.
Currently only supports LLM.int8(), FP4, and NF4 quantization. If more methods are added to bitsandbytes, then more arguments will be added to this class.
Returns True if the model is quantizable, False otherwise.
Safety checker that arguments are correct - also replaces some NoneType arguments with their default values.
This method returns the quantization method used for the model. If the model is not quantizable, it returns None.
to_diff_dict
()âdict[str, Any]
Returns
dict[str, Any]
Dictionary of all the attributes that make up this configuration instance,
Removes all attributes from config which correspond to the default config attributes for better readability and serializes to a Python dictionary.
Quantization with ð€ optimum
optimumã§ãµããŒããããŠããéååæ¹æ³ã®è©³çްã«ã€ããŠã¯ã
ãåç §ããããããèªåã®ãŠãŒã¹ã±ãŒã¹ã«é©çšã§ãããã©ããã確èªããŠãã ããã