Transformers documentation
Fine-tuning yang efisien secara parameter
Fine-tuning yang efisien secara parameter
Metode Parameter-efficient fine-tuning (PEFT) 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, yang ditambahkan ke semua kelas 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 PEFT library secara langsung.
Instal PEFT untuk memulai. Integrasi ini membutuhkan peft >= 0.20.0.
pip install -U peft
Tambahkan adapter
Buat konfigurasi PEFT, misalnya LoraConfig, lalu lampirkan ke model dengan add_adapter().
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.
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 sudah didefinisikan, berikan target_modules secara eksplisit sebagai daftar nama modul atau pola regex.
lora_config = LoraConfig(
target_modules=["q_proj", "k_proj"],
...
)
model.add_adapter(lora_config)Pelatihan
Lewatkan model dengan adapter yang terpasang ke Trainer dan panggil train(). Trainer hanya memperbarui parameter adapter (yang memiliki requires_grad=True) karena model dasar dibekukan.
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 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().
model.save_pretrained("./my_adapter")Melanjutkan dari checkpoint
Trainer secara otomatis mendeteksi checkpoint adapter saat melanjutkan. Trainer memindai direktori checkpoint untuk subdirektori yang berisi bobot adapter dan memuat ulang setiap adapter dengan status trainable yang benar.
trainer.train(resume_from_checkpoint="./output/checkpoint-1000")Pelatihan terdistribusi
Adaptor PEFT berfungsi dengan pelatihan terdistribusi secara bawaan.
Untuk ZeRO-3, 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 memperbarui kebijakan auto-wrap FSDP untuk menangani lapisan LoRA dengan benar. Untuk QLoRA (model dasar terkuantisasi + LoRA), 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 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() 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.
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().
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 untuk menghemat memori. Tambahkan device_map="auto" untuk mendistribusikan model di seluruh perangkat keras yang tersedia.
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.
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() untuk mengaktifkan adapter tertentu. Adapter lainnya dinonaktifkan tetapi tetap berada di memori.
model.set_adapter("adapter_2")enable_adapters() mengaktifkan semua adapter yang terpasang, dan disable_adapters() menonaktifkan semuanya.
# Disable all adapters for base model inference
model.disable_adapters()
# Re-enable all adapters
model.enable_adapters()Gunakan active_adapters() untuk melihat adapter mana yang saat ini aktif.
model.active_adapters()
# ["adapter_1"]Hapus adapter yang tidak lagi Anda butuhkan dengan delete_adapter() untuk membebaskan memori.
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).
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 2torch.compile
Untuk model yang dikompilasi, panggil enable_peft_hotswap() sebelum memuat adapter pertama dan sebelum kompilasi.
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 rank maksimum di antara semua adapter LoRA yang akan Anda muat. Jika Anda memiliki adapter dengan rank 8 dan rank 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.
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 beserta contoh yang dapat direproduksi.
Langkah selanjutnya
- Dokumentasi PEFT mencakup seluruh metode dan opsi PEFT.
- Referensi hotswapping PEPE merinci batasan dan kasus tepi.
- Sebuah artikel blog menguji seberapa jauh
torch.compiledengan hotswapping meningkatkan waktu eksekusi.