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