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) | |
``` | |