Spaces:
Paused
Paused
| <!--Copyright 2023 The HuggingFace Team. All rights reserved. | |
| Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with | |
| the License. You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | |
| an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | |
| specific language governing permissions and limitations under the License. | |
| β οΈ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be | |
| rendered properly in your Markdown viewer. | |
| --> | |
| # π€ PEFTλ‘ μ΄λν° κ°μ Έμ€κΈ° [[load-adapters-with-peft]] | |
| [[open-in-colab]] | |
| [Parameter-Efficient Fine Tuning (PEFT)](https://huggingface.co/blog/peft) λ°©λ²μ μ¬μ νλ ¨λ λͺ¨λΈμ λ§€κ°λ³μλ₯Ό λ―ΈμΈ μ‘°μ μ€ κ³ μ μν€κ³ , κ·Έ μμ νλ ¨ν μ μλ λ§€μ° μ μ μμ λ§€κ°λ³μ(μ΄λν°)λ₯Ό μΆκ°ν©λλ€. μ΄λν°λ μμ λ³ μ 보λ₯Ό νμ΅νλλ‘ νλ ¨λ©λλ€. μ΄ μ κ·Ό λ°©μμ μμ ν λ―ΈμΈ μ‘°μ λ λͺ¨λΈμ νμ νλ κ²°κ³Όλ₯Ό μμ±νλ©΄μ, λ©λͺ¨λ¦¬ ν¨μ¨μ μ΄κ³ λΉκ΅μ μ μ μ»΄ν¨ν 리μμ€λ₯Ό μ¬μ©ν©λλ€. | |
| λν PEFTλ‘ νλ ¨λ μ΄λν°λ μΌλ°μ μΌλ‘ μ 체 λͺ¨λΈλ³΄λ€ ν¨μ¬ μκΈ° λλ¬Έμ 곡μ , μ μ₯ λ° κ°μ Έμ€κΈ°κ° νΈλ¦¬ν©λλ€. | |
| <div class="flex flex-col justify-center"> | |
| <img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/peft/PEFT-hub-screenshot.png"/> | |
| <figcaption class="text-center">Hubμ μ μ₯λ OPTForCausalLM λͺ¨λΈμ μ΄λν° κ°μ€μΉλ μ΅λ 700MBμ λ¬νλ λͺ¨λΈ κ°μ€μΉμ μ 체 ν¬κΈ°μ λΉν΄ μ½ 6MBμ λΆκ³Όν©λλ€.</figcaption> | |
| </div> | |
| π€ PEFT λΌμ΄λΈλ¬λ¦¬μ λν΄ μμΈν μμλ³΄λ €λ©΄ [λ¬Έμ](https://huggingface.co/docs/peft/index)λ₯Ό νμΈνμΈμ. | |
| ## μ€μ [[setup]] | |
| π€ PEFTλ₯Ό μ€μΉνμ¬ μμνμΈμ: | |
| ```bash | |
| pip install peft | |
| ``` | |
| μλ‘μ΄ κΈ°λ₯μ μ¬μ©ν΄λ³΄κ³ μΆλ€λ©΄, λ€μ μμ€μμ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ€μΉνλ κ²μ΄ μ’μ΅λλ€: | |
| ```bash | |
| pip install git+https://github.com/huggingface/peft.git | |
| ``` | |
| ## μ§μλλ PEFT λͺ¨λΈ [[supported-peft-models]] | |
| π€ Transformersλ κΈ°λ³Έμ μΌλ‘ μΌλΆ PEFT λ°©λ²μ μ§μνλ©°, λ‘컬μ΄λ Hubμ μ μ₯λ μ΄λν° κ°μ€μΉλ₯Ό κ°μ Έμ€κ³ λͺ μ€μ μ½λλ§μΌλ‘ μ½κ² μ€ννκ±°λ νλ ¨ν μ μμ΅λλ€. λ€μ λ°©λ²μ μ§μν©λλ€: | |
| - [Low Rank Adapters](https://huggingface.co/docs/peft/conceptual_guides/lora) | |
| - [IA3](https://huggingface.co/docs/peft/conceptual_guides/ia3) | |
| - [AdaLoRA](https://arxiv.org/abs/2303.10512) | |
| π€ PEFTμ κ΄λ ¨λ λ€λ₯Έ λ°©λ²(μ: ν둬ννΈ νλ ¨ λλ ν둬ννΈ νλ) λλ μΌλ°μ μΈ π€ PEFT λΌμ΄λΈλ¬λ¦¬μ λν΄ μμΈν μμλ³΄λ €λ©΄ [λ¬Έμ](https://huggingface.co/docs/peft/index)λ₯Ό μ°Έμ‘°νμΈμ. | |
| ## PEFT μ΄λν° κ°μ Έμ€κΈ° [[load-a-peft-adapter]] | |
| π€ Transformersμμ PEFT μ΄λν° λͺ¨λΈμ κ°μ Έμ€κ³ μ¬μ©νλ €λ©΄ Hub μ μ₯μλ λ‘컬 λλ ν°λ¦¬μ `adapter_config.json` νμΌκ³Ό μ΄λν° κ°μ€μΉκ° ν¬ν¨λμ΄ μλμ§ νμΈνμμμ€. κ·Έλ° λ€μ `AutoModelFor` ν΄λμ€λ₯Ό μ¬μ©νμ¬ PEFT μ΄λν° λͺ¨λΈμ κ°μ Έμ¬ μ μμ΅λλ€. μλ₯Ό λ€μ΄ μΈκ³Ό κ΄κ³ μΈμ΄ λͺ¨λΈμ© PEFT μ΄λν° λͺ¨λΈμ κ°μ Έμ€λ €λ©΄ λ€μ λ¨κ³λ₯Ό λ°λ₯΄μμμ€: | |
| 1. PEFT λͺ¨λΈ IDλ₯Ό μ§μ νμμμ€. | |
| 2. [`AutoModelForCausalLM`] ν΄λμ€μ μ λ¬νμμμ€. | |
| ```py | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| peft_model_id = "ybelkada/opt-350m-lora" | |
| model = AutoModelForCausalLM.from_pretrained(peft_model_id) | |
| ``` | |
| <Tip> | |
| `AutoModelFor` ν΄λμ€λ κΈ°λ³Έ λͺ¨λΈ ν΄λμ€(μ: `OPTForCausalLM` λλ `LlamaForCausalLM`) μ€ νλλ₯Ό μ¬μ©νμ¬ PEFT μ΄λν°λ₯Ό κ°μ Έμ¬ μ μμ΅λλ€. | |
| </Tip> | |
| `load_adapter` λ©μλλ₯Ό νΈμΆνμ¬ PEFT μ΄λν°λ₯Ό κ°μ Έμ¬ μλ μμ΅λλ€. | |
| ```py | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| model_id = "facebook/opt-350m" | |
| peft_model_id = "ybelkada/opt-350m-lora" | |
| model = AutoModelForCausalLM.from_pretrained(model_id) | |
| model.load_adapter(peft_model_id) | |
| ``` | |
| ## 8λΉνΈ λλ 4λΉνΈλ‘ κ°μ Έμ€κΈ° [[load-in-8bit-or-4bit]] | |
| `bitsandbytes` ν΅ν©μ 8λΉνΈμ 4λΉνΈ μ λ°λ λ°μ΄ν° μ νμ μ§μνλ―λ‘ ν° λͺ¨λΈμ κ°μ Έμ¬ λ μ μ©νλ©΄μ λ©λͺ¨λ¦¬λ μ μ½ν©λλ€. λͺ¨λΈμ νλμ¨μ΄μ ν¨κ³Όμ μΌλ‘ λΆλ°°νλ €λ©΄ [`~PreTrainedModel.from_pretrained`]μ `load_in_8bit` λλ `load_in_4bit` λ§€κ°λ³μλ₯Ό μΆκ°νκ³ `device_map="auto"`λ₯Ό μ€μ νμΈμ: | |
| ```py | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| peft_model_id = "ybelkada/opt-350m-lora" | |
| model = AutoModelForCausalLM.from_pretrained(peft_model_id, device_map="auto", load_in_8bit=True) | |
| ``` | |
| ## μ μ΄λν° μΆκ° [[add-a-new-adapter]] | |
| μ μ΄λν°κ° νμ¬ μ΄λν°μ λμΌν μ νμΈ κ²½μ°μ νν΄ κΈ°μ‘΄ μ΄λν°κ° μλ λͺ¨λΈμ μ μ΄λν°λ₯Ό μΆκ°νλ €λ©΄ [`~peft.PeftModel.add_adapter`]λ₯Ό μ¬μ©ν μ μμ΅λλ€. μλ₯Ό λ€μ΄ λͺ¨λΈμ κΈ°μ‘΄ LoRA μ΄λν°κ° μ°κ²°λμ΄ μλ κ²½μ°: | |
| ```py | |
| from transformers import AutoModelForCausalLM, OPTForCausalLM, AutoTokenizer | |
| from peft import PeftConfig | |
| model_id = "facebook/opt-350m" | |
| model = AutoModelForCausalLM.from_pretrained(model_id) | |
| lora_config = LoraConfig( | |
| target_modules=["q_proj", "k_proj"], | |
| init_lora_weights=False | |
| ) | |
| model.add_adapter(lora_config, adapter_name="adapter_1") | |
| ``` | |
| μ μ΄λν°λ₯Ό μΆκ°νλ €λ©΄: | |
| ```py | |
| # attach new adapter with same config | |
| model.add_adapter(lora_config, adapter_name="adapter_2") | |
| ``` | |
| μ΄μ [`~peft.PeftModel.set_adapter`]λ₯Ό μ¬μ©νμ¬ μ΄λν°λ₯Ό μ¬μ©ν μ΄λν°λ‘ μ€μ ν μ μμ΅λλ€: | |
| ```py | |
| # use adapter_1 | |
| model.set_adapter("adapter_1") | |
| output = model.generate(**inputs) | |
| print(tokenizer.decode(output_disabled[0], skip_special_tokens=True)) | |
| # use adapter_2 | |
| model.set_adapter("adapter_2") | |
| output_enabled = model.generate(**inputs) | |
| print(tokenizer.decode(output_enabled[0], skip_special_tokens=True)) | |
| ``` | |
| ## μ΄λν° νμ±ν λ° λΉνμ±ν [[enable-and-disable-adapters]] | |
| λͺ¨λΈμ μ΄λν°λ₯Ό μΆκ°ν ν μ΄λν° λͺ¨λμ νμ±ν λλ λΉνμ±νν μ μμ΅λλ€. μ΄λν° λͺ¨λμ νμ±ννλ €λ©΄: | |
| ```py | |
| from transformers import AutoModelForCausalLM, OPTForCausalLM, AutoTokenizer | |
| from peft import PeftConfig | |
| model_id = "facebook/opt-350m" | |
| adapter_model_id = "ybelkada/opt-350m-lora" | |
| tokenizer = AutoTokenizer.from_pretrained(model_id) | |
| text = "Hello" | |
| inputs = tokenizer(text, return_tensors="pt") | |
| model = AutoModelForCausalLM.from_pretrained(model_id) | |
| peft_config = PeftConfig.from_pretrained(adapter_model_id) | |
| # to initiate with random weights | |
| peft_config.init_lora_weights = False | |
| model.add_adapter(peft_config) | |
| model.enable_adapters() | |
| output = model.generate(**inputs) | |
| ``` | |
| μ΄λν° λͺ¨λμ λΉνμ±ννλ €λ©΄: | |
| ```py | |
| model.disable_adapters() | |
| output = model.generate(**inputs) | |
| ``` | |
| ## PEFT μ΄λν° νλ ¨ [[train-a-peft-adapter]] | |
| PEFT μ΄λν°λ [`Trainer`] ν΄λμ€μμ μ§μλλ―λ‘ νΉμ μ¬μ© μ¬λ‘μ λ§κ² μ΄λν°λ₯Ό νλ ¨ν μ μμ΅λλ€. λͺ μ€μ μ½λλ₯Ό μΆκ°νκΈ°λ§ νλ©΄ λ©λλ€. μλ₯Ό λ€μ΄ LoRA μ΄λν°λ₯Ό νλ ¨νλ €λ©΄: | |
| <Tip> | |
| [`Trainer`]λ₯Ό μ¬μ©νμ¬ λͺ¨λΈμ λ―ΈμΈ μ‘°μ νλ κ²μ΄ μ΅μνμ§ μλ€λ©΄ [μ¬μ νλ ¨λ λͺ¨λΈμ λ―ΈμΈ μ‘°μ νκΈ°](training) νν 리μΌμ νμΈνμΈμ. | |
| </Tip> | |
| 1. μμ μ ν λ° νμ΄νΌνλΌλ―Έν°λ₯Ό μ§μ νμ¬ μ΄λν° κ΅¬μ±μ μ μν©λλ€. νμ΄νΌνλΌλ―Έν°μ λν μμΈν λ΄μ©μ [`~peft.LoraConfig`]λ₯Ό μ°Έμ‘°νμΈμ. | |
| ```py | |
| from peft import LoraConfig | |
| peft_config = LoraConfig( | |
| lora_alpha=16, | |
| lora_dropout=0.1, | |
| r=64, | |
| bias="none", | |
| task_type="CAUSAL_LM", | |
| ) | |
| ``` | |
| 2. λͺ¨λΈμ μ΄λν°λ₯Ό μΆκ°ν©λλ€. | |
| ```py | |
| model.add_adapter(peft_config) | |
| ``` | |
| 3. μ΄μ λͺ¨λΈμ [`Trainer`]μ μ λ¬ν μ μμ΅λλ€! | |
| ```py | |
| trainer = Trainer(model=model, ...) | |
| trainer.train() | |
| ``` | |
| νλ ¨ν μ΄λν°λ₯Ό μ μ₯νκ³ λ€μ κ°μ Έμ€λ €λ©΄: | |
| ```py | |
| model.save_pretrained(save_dir) | |
| model = AutoModelForCausalLM.from_pretrained(save_dir) | |
| ``` | |