# Fine-tuning yang efisien secara parameter

Metode [Parameter-efficient fine-tuning (PEFT)](https://huggingface.co/docs/peft/index) hanya melakukan fine-tuning pada sejumlah kecil parameter model tambahan (adapters) di atas model pretrained. Karena hanya parameter adapter yang diperbarui, optimizer melacak jauh lebih sedikit gradien dan state, sehingga penggunaan memori berkurang secara signifikan. Adapters bersifat ringan, sehingga mudah untuk dibagikan, disimpan, dan dimuat.

Transformers terintegrasi langsung dengan pustaka PEFT melalui [PeftAdapterMixin](/docs/transformers/v5.23.0/id/main_classes/peft#transformers.integrations.PeftAdapterMixin), yang ditambahkan ke semua kelas [PreTrainedModel](/docs/transformers/v5.23.0/id/main_classes/model#transformers.PreTrainedModel). Anda dapat memuat, menambahkan, melatih, mengganti, dan menghapus adapter tanpa membungkus model Anda dalam `PeftModel` terpisah. Semua metode PEFT non-prompt-learning didukung (LoRA, IA3, AdaLoRA). Metode berbasis prompt seperti prompt tuning dan prefix tuning memerlukan penggunaan [pustaka PEFT](https://huggingface.co/docs/peft/index) secara langsung.

Instal PEFT untuk memulai. Integrasi ini membutuhkan `peft >= 0.20.0`.

```shell
pip install -U peft
```

## Tambahkan adapter

Buat konfigurasi PEFT, misalnya `LoraConfig`, lalu lampirkan ke model dengan [add_adapter()](/docs/transformers/v5.23.0/id/main_classes/peft#transformers.integrations.PeftAdapterMixin.add_adapter).

```py
from peft import LoraConfig, TaskType
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained("google/gemma-2-2b")

lora_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    inference_mode=False,
    r=8,
    lora_alpha=32,
    lora_dropout=0.1,
)

model.add_adapter(lora_config, adapter_name="my_adapter")
```

### Menyesuaikan secara penuh lapisan tertentu

Untuk melatih modul tambahan bersama adapter (misalnya, kepala model bahasa), tentukan modul tersebut di `modules_to_save`. `modules_to_save` menentukan lapisan yang dilatih penuh (fully fine-tuned) bersama adapter, sehingga *semua* parameter di lapisan tersebut diperbarui. Hal ini berguna ketika lapisan tertentu perlu diperbarui, misalnya kepala model bahasa (`lm_head`), saat mengadaptasi LM kausal untuk klasifikasi sekuens.

```py
lora_config = LoraConfig(
    modules_to_save=["lm_head"],
    ...
)
model.add_adapter(lora_config)
```

### Memilih lapisan mana yang akan diadaptasi

Untuk arsitektur umum (Llama, Gemma, Qwen, dll.), PEFT memiliki target default yang sudah didefinisikan (seperti `q_proj` dan `v_proj`), sehingga Anda tidak perlu menentukan `target_modules`. Jika Anda ingin menargetkan lapisan yang berbeda, atau model tidak memiliki target yang didefinisikan sebelumnya, berikan `target_modules` secara eksplisit sebagai daftar nama modul atau pola regex.

```py
lora_config = LoraConfig(
    target_modules=["q_proj", "k_proj"],
    ...
)
model.add_adapter(lora_config)
```

## Pelatihan

Lewatkan model dengan adapter yang terpasang ke [Trainer](/docs/transformers/v5.23.0/id/main_classes/trainer#transformers.Trainer) dan panggil [train()](/docs/transformers/v5.23.0/id/main_classes/trainer#transformers.Trainer.train). [Trainer](/docs/transformers/v5.23.0/id/main_classes/trainer#transformers.Trainer) hanya memperbarui parameter adapter (yang memiliki `requires_grad=True`) karena model dasar dibekukan.

```py
from transformers import Trainer, TrainingArguments

training_args = TrainingArguments(
    output_dir="./output",
    num_train_epochs=3,
    per_device_train_batch_size=4,
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=dataset,
)

trainer.train()
```

Selama pelatihan, checkpoint [Trainer](/docs/transformers/v5.23.0/id/main_classes/trainer#transformers.Trainer) hanya berisi bobot adapter (`adapter_model.safetensors`) dan konfigurasi (`adapter_config.json`), sehingga ukuran checkpoint tetap kecil. Model dasar tidak disertakan.

Setelah pelatihan, simpan adapter akhir dengan [save_pretrained()](/docs/transformers/v5.23.0/id/main_classes/model#transformers.PreTrainedModel.save_pretrained).

```py
model.save_pretrained("./my_adapter")
```

### Melanjutkan dari checkpoint

[Trainer](/docs/transformers/v5.23.0/id/main_classes/trainer#transformers.Trainer) secara otomatis mendeteksi checkpoint adapter saat melanjutkan. [Trainer](/docs/transformers/v5.23.0/id/main_classes/trainer#transformers.Trainer) memindai direktori checkpoint untuk subdirektori yang berisi bobot adapter dan memuat ulang setiap adapter dengan status trainable yang benar.

```py
trainer.train(resume_from_checkpoint="./output/checkpoint-1000")
```

### Pelatihan terdistribusi

Adaptor PEFT berfungsi dengan pelatihan terdistribusi secara bawaan.

Untuk ZeRO-3, [Trainer](/docs/transformers/v5.23.0/id/main_classes/trainer#transformers.Trainer) meneruskan `exclude_frozen_parameters=True` saat menyimpan checkpoint dengan model PEFT. Bobot model dasar yang dibekukan akan dilewati. Hanya parameter adapter yang dapat dilatih yang disimpan, sehingga mengurangi ukuran checkpoint dan waktu penyimpanan.

Untuk FSDP, [Trainer](/docs/transformers/v5.23.0/id/main_classes/trainer#transformers.Trainer) memperbarui kebijakan auto-wrap FSDP untuk menangani lapisan LoRA dengan benar. Untuk QLoRA (model dasar terkuantisasi + LoRA), [Trainer](/docs/transformers/v5.23.0/id/main_classes/trainer#transformers.Trainer) juga menyesuaikan kebijakan presisi campuran agar sesuai dengan dtype penyimpanan kuantisasi.

Anda dapat memuat adapter PEFT ke model dasar yang menggunakan tensor parallel, dan membiarkan PEFT menangani sharding bobot adapter. Memuat adapter memerlukan `peft >= 0.21.1`. Lihat [Tensor parallelism](./tensor_parallelism) untuk pelatihan dengan TP.

## Memuat adapter

Untuk memuat adapter, repositori Hub atau direktori lokal harus berisi file `adapter_config.json` dan bobot adapter.

[from_pretrained()](/docs/transformers/v5.23.0/id/main_classes/model#transformers.PreTrainedModel.from_pretrained) mendeteksi adapter secara otomatis. Ketika menemukan `adapter_config.json`, fungsi ini membaca field `base_model_name_or_path` untuk memuat model dasar yang tepat, kemudian memuat adapter di atasnya.

```py
from transformers import AutoModelForCausalLM

# Automatically loads the base model and attaches the adapter
model = AutoModelForCausalLM.from_pretrained("klcsp/gemma7b-lora-alpaca-11-v1")
```

Untuk memuat adapter ke model yang sudah ada, gunakan [load_adapter()](/docs/transformers/v5.23.0/id/main_classes/peft#transformers.integrations.PeftAdapterMixin.load_adapter).

```py
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained("google/gemma-7b")
model.load_adapter("klcsp/gemma7b-lora-alpaca-11-v1")
```

Untuk model besar, muat versi terkuantisasi dalam presisi 8-bit atau 4-bit dengan [bitsandbytes](./quantization/bitsandbytes) untuk menghemat memori. Tambahkan `device_map="auto"` untuk mendistribusikan model di seluruh perangkat keras yang tersedia.

```py
from transformers import AutoModelForCausalLM, BitsAndBytesConfig

model = AutoModelForCausalLM.from_pretrained(
    "klcsp/gemma7b-lora-alpaca-11-v1",
    quantization_config=BitsAndBytesConfig(load_in_8bit=True),
    device_map="auto",
)
```

## Mengelola beberapa adapter

Sebuah model dapat menyimpan beberapa adapter sekaligus. Tambahkan adapter dengan nama yang unik, dan beralih di antara mereka sesuai kebutuhan.

```py
from peft import LoraConfig

model.add_adapter(LoraConfig(r=8, lora_alpha=32), adapter_name="adapter_1")
model.add_adapter(LoraConfig(r=16, lora_alpha=64), adapter_name="adapter_2")
```

Gunakan [set_adapter()](/docs/transformers/v5.23.0/id/main_classes/peft#transformers.integrations.PeftAdapterMixin.set_adapter) untuk mengaktifkan adapter tertentu. Adapter lainnya dinonaktifkan tetapi tetap berada di memori.

```py
model.set_adapter("adapter_2")
```

[enable_adapters()](/docs/transformers/v5.23.0/id/main_classes/peft#transformers.integrations.PeftAdapterMixin.enable_adapters) mengaktifkan semua adapter yang terpasang, dan [disable_adapters()](/docs/transformers/v5.23.0/id/main_classes/peft#transformers.integrations.PeftAdapterMixin.disable_adapters) menonaktifkan semuanya.

```py
# Disable all adapters for base model inference
model.disable_adapters()

# Re-enable all adapters
model.enable_adapters()
```

Gunakan [active_adapters()](/docs/transformers/v5.23.0/id/main_classes/peft#transformers.integrations.PeftAdapterMixin.active_adapters) untuk melihat adapter mana yang saat ini aktif.

```py
model.active_adapters()
# ["adapter_1"]
```

Hapus adapter yang tidak lagi Anda butuhkan dengan [delete_adapter()](/docs/transformers/v5.23.0/id/main_classes/peft#transformers.integrations.PeftAdapterMixin.delete_adapter) untuk membebaskan memori.

```py
model.delete_adapter("adapter_1")
```

## Mengganti adapter secara langsung

Memuat adapter baru setiap kali Anda melayani permintaan akan mengalokasikan memori baru. Jika model dikompilasi dengan `torch.compile`, setiap adapter baru akan memicu kompilasi ulang. Hotswapping mengganti bobot adapter secara in-place, sehingga menghindari kedua masalah tersebut. Hanya adapter LoRA yang didukung.

Lewatkan `hotswap=True` saat memuat adapter LoRA untuk mengganti bobotnya ke slot adapter yang sudah ada. Atur `adapter_name` ke nama adapter yang akan diganti (`"default"` adalah nama adapter bawaan).

```py
model = AutoModel.from_pretrained(...)
# Load the first adapter normally
model.load_adapter(adapter_path_1)
# Generate outputs with adapter 1
...
# Hotswap the second adapter in-place
model.load_adapter(adapter_path_2, hotswap=True, adapter_name="default")
# Generate outputs with adapter 2
```

### torch.compile

Untuk model yang dikompilasi, panggil [enable_peft_hotswap()](/docs/transformers/v5.23.0/id/main_classes/peft#transformers.integrations.PeftAdapterMixin.enable_peft_hotswap) *sebelum* memuat adapter pertama dan sebelum kompilasi.

```py
model = AutoModel.from_pretrained(...)
max_rank = ...  # highest rank among all LoRAs you'll load
model.enable_peft_hotswap(target_rank=max_rank)
model.load_adapter(adapter_path_1, adapter_name="default")
model = torch.compile(model, ...)
output_1 = model(...)

# Hotswap without recompilation
model.load_adapter(adapter_path_2, adapter_name="default")
output_2 = model(...)
```

Argumen `target_rank` mengatur peringkat maksimum di antara semua adapter LoRA yang akan Anda muat. Jika Anda memiliki adapter dengan peringkat 8 dan peringkat 16, gunakan `target_rank=16`. Nilai defaultnya adalah 128.

Setelah memanggil `enable_peft_hotswap`, semua pemanggilan `load_adapter` berikutnya akan melakukan hotswap secara default. Sampaikan `hotswap=False` secara eksplisit untuk menonaktifkan hotswap.

Rekompilasi masih dapat terjadi jika adapter yang di-hotswap menargetkan lebih banyak lapisan daripada adapter awal. Muat adapter yang menargetkan lapisan terbanyak terlebih dahulu untuk menghindari rekompilasi.

> [!TIP]
> Bungkus kode Anda dengan `with torch._dynamo.config.patch(error_on_recompile=True)` untuk mendeteksi kompilasi ulang yang tidak terduga. Jika Anda mendeteksi kompilasi ulang meskipun telah mengikuti langkah-langkah di atas, buka masalah dengan [PEFT](https://github.com/huggingface/peft/issues) beserta contoh yang dapat direproduksi.

## Langkah selanjutnya

- Dokumentasi [PEFT](https://huggingface.co/docs/peft/index) mencakup seluruh metode dan opsi PEFT.
- [Referensi hotswapping](https://huggingface.co/docs/peft/main/en/package_reference/hotswap#peft.utils.hotswap.hotswap_adapter) PEPE merinci batasan dan kasus tepi.
- Sebuah [artikel blog](https://huggingface.co/blog/lora-fast) menguji seberapa jauh `torch.compile` dengan hotswapping meningkatkan waktu eksekusi.

