PEFT documentation

Konversi LoRA

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.21.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Konversi LoRA

Fungsi yang memungkinkan konversi model PEFT non-LoRA menjadi model LoRA.

Deskripsi

PEFT mendukung puluhan teknik fine-tuning parameter efisien yang berbeda. Yang paling populer sejauh ini adalah LoRA. Artinya, banyak paket lain juga mendukung LoRA. Misalnya, Diffusers memungkinkan pemuatan adapter LoRA untuk mengubah kemampuan model difusi. vLLM memungkinkan penyajian model dengan adapter LoRA. Ini bagus, tetapi sayangnya, semua metode PEFT non-LoRA lainnya jarang didukung. Oleh karena itu, bahkan jika metode PEFT lain akan bekerja lebih baik untuk kasus penggunaan spesifik Anda, Anda mungkin dicegah untuk menggunakannya karena paket downstream tidak menawarkan dukungan.

Di sini kami menyajikan solusi potensial. PEFT menyediakan dua fungsi, save_as_lora() dan convert_to_lora(), yang memungkinkan konversi adapter PEFT menjadi adapter LoRA. Saat ini, tidak semua metode PEFT mendukung hal ini, tetapi jika didukung, artinya Anda dapat memulai dengan metode PEFT yang paling sesuai untuk Anda dan kemudian menggunakannya seolah-olah itu adalah adapter LoRA.

Contoh

Rank LoRA untuk adapter yang dikonversi dapat diatur ke rank tetap dengan meneruskan int > 0 ke argumen rank, atau ke rank dinamis yang beradaptasi dengan setiap layer, dengan meneruskan float antara 0 dan 1 ke argumen rank. Rank dinamis berpotensi lebih efisien (kinerja sama dengan jumlah parameter yang lebih sedikit).

Rank LoRA yang tetap

Penggunaan save_as_lora() relatif sederhana:

from peft import get_peft_model, save_as_lora

# first load and train your non-LoRA PEFT model as normal
base_model = ...
non_lora_config = ...
model = get_peft_model(base_model, non_lora_config)
# check that this PEFT method can indeed be converted to LoRA
assert model.supports_lora_conversion()
...  # train the model

# the rank of the LoRA adapter that you want to convert to
target_rank = 64
# save as a LoRA checkpoint
save_as_lora(output_path, model, rank=target_rank)

Hal ini akan membuat checkpoint LoRA di output_path yang dapat dimuat seperti adapter LoRA lainnya, atau digunakan dalam paket turunan seperti Diffusers atau vLLM.

Fungsi convert_to_lora() berguna jika Anda tidak ingin menyimpan adapter LoRA yang dikonversi, melainkan ingin langsung menggunakan bobot yang telah dikonversi, misalnya untuk melakukan evaluasi:

from peft import convert_to_lora, get_peft_model, set_peft_model_state_dict

base_model = ...
non_lora_config = ...
model = get_peft_model(base_model, non_lora_config)
...  # train the model

# get the lora config and state dict of the converted lora model
lora_config, lora_state_dict = convert_to_lora(model, rank=target_rank)
# reload the base model, or use model.unload()
base_model = ...
# apply the lora config to the base model
lora_model = get_peft_model(base_model, lora_config)
# load the LoRA weights onto the base model
set_peft_model_state_dict(lora_model, state_dict)

Rank LoRA dinamis

Pada contoh di atas, kami menggunakan rank LoRA yang tetap untuk konversi. Namun, dapat dibayangkan bahwa beberapa lapisan tidak memerlukan rank tinggi untuk dikonversi secara akurat, sementara lapisan lain memerlukan rank yang lebih tinggi. Untuk mengakomodasi hal ini, PEFT menawarkan opsi untuk melewatkan float antara 0 dan 1 sebagai argumen rank. Misalkan Anda melewatkan rank=0.5. Ini berarti bahwa untuk setiap lapisan, rank untuk adapter LoRA dipilih sedemikian rupa sehingga adapter LoRA menjelaskan 50% dari varians pada bobot yang diperkenalkan oleh adapter asli. Dalam istilah yang lebih teknis, di balik layar kami melakukan Singular Value Decomposition pada kontribusi bobot dari adapter dan kemudian mengambil nilai singular teratas yang, ketika dinormalisasi, berjumlah sama dengan nilai yang dilewatkan.

# set a dynamic rank by passing a float
threshold = 0.7
# save as a LoRA checkpoint
save_as_lora(output_path, model, rank=threshold)
# get the lora config and state dict directly:
lora_config, lora_state_dict = convert_to_lora(model, rank=threshold)
# inspect the different ranks per layer:
print(lora_config.rank_pattern)

Menggunakan jenis rank LoRA dinamis ini dapat berguna jika kontribusi dari lapisan yang berbeda sangat bervariasi. Kekurangannya adalah beberapa lapisan mungkin akan memiliki rank LoRA yang sangat tinggi, yang dapat menyebabkan lonjakan memori. Silakan uji coba apa yang paling sesuai untuk kasus penggunaan Anda.

Mengompilasi model

Untuk model besar, proses konversi mungkin memerlukan waktu; misalnya, setiap modul PEFT harus melewati komputasi SVD. Dengan meneruskan compile_kwargs ke save_as_lora() atau convert_to_lora(), Anda dapat menerapkan torch.compile pada fungsi konversi dan berpotensi mempercepat proses. compile_kwargs adalah dict berisi argumen kata kunci yang diteruskan ke torch.compile (dict kosong juga berfungsi). Berikut adalah contohnya:

compile_kwargs = {"dynamic": True, "mode": "max-autotune-no-cudagraphs", "fullgraph": True}
save_as_lora(output_path, model, rank=rank, compile_kwargs=compile_kwargs)

Konversi LoRA ke LoRA

Anda juga dapat mengonversi adapter LoRA menjadi adapter LoRA lain. Mengapa Anda ingin melakukan hal itu? Ada satu alasannya, yaitu jika Anda ingin mengurangi rank dari adapter LoRA. Jika, setelah pelatihan, Anda ingin mengecilkan adapter LoRA, gunakan save_as_lora() atau convert_to_lora() dan berikan rank yang lebih kecil. Hal ini akan menghasilkan adapter LoRA baru yang memiliki jejak memori dan penyimpanan yang lebih kecil.

Metrik

Konversi Non-LoRA ke LoRA

Tentu saja, mengonversi satu adapter PEFT menjadi adapter lain adalah proses yang kehilangan informasi. Adapter baru kemungkinan besar tidak akan berkinerja sebaik adapter awal. Oleh karena itu, sangat disarankan untuk mengevaluasi adapter LoRA yang telah dikonversi. Dengan cara ini, Anda dapat memastikan bahwa adapter yang dikonversi memiliki kinerja yang cukup baik untuk kasus penggunaan Anda. Aturan umum berlaku bahwa semakin tinggi rank adapter LoRA, semakin baik adapter tersebut akan mengaproksimasi adapter awal Anda. Ini berarti bahwa adapter LoRA yang dikonversi mungkin memerlukan lebih banyak parameter daripada adapter asli untuk mencapai kinerja yang serupa.

Sebagai contoh, berikut adalah beberapa angka yang diturunkan dari benchmark PEFT MetaMathQA. Untuk ini, adapter LoHa digunakan untuk fine-tune meta-llama/Llama-3.2-3B pada MetaMathQA dan dievaluasi pada GSM8K. Adapter LoKr awal memiliki rank 32, menghasilkan 18.350.080 parameter yang dapat dilatih dan akurasi tes 41,85%. Evaluasi membutuhkan 12,25 GB memori. Checkpoint dikonversi menjadi LoRA dengan nilai rank yang berbeda. Hasilnya adalah:

rankparameter yang dapat dilatihakurasi uji (%)perubahan akurasimemori yang dicadangkan (maks, GB)peningkatan memori
8229376037.60-4.2512.410.16
16458752038.89-2.9612.15-0.10
32917504040.11-1.7412.410.16
641835008039.20-2.6512.18-0.07
0.4242892837.60-4.2512.410.16
0.5476160040.18-1.6712.410.16
0.6885760039.42-2.4312.410.16
0.71623040039.04-2.8112.15-0.10

Seperti yang dapat Anda lihat, kita dapat mencapai akurasi pengujian yang mendekati adapter LoHa asli jika rank cukup tinggi. Memilih rank yang tepat merupakan pertukaran antara kinerja model dan efisiensi model. Untuk mereproduksi eksperimen ini, ikuti skrip di https://github.com/huggingface/peft/tree/main/scripts/evaluate-lora-conversion.py.

Perhatikan bahwa jumlah parameter yang dapat dilatih tidak dapat diterjemahkan satu per satu ke dalam penggunaan memori. Beberapa metode PEFT membutuhkan lebih banyak, beberapa lebih sedikit memori, bahkan dengan jumlah parameter yang dapat dilatih yang sama. Oleh karena itu, bahkan jika setelah konversi, adapter LoRA memiliki lebih banyak parameter daripada yang asli, adapter tersebut masih bisa lebih efisien dalam penggunaan memori saat disajikan (serving).

Konversi LoRA ke LoRA

Mirip dengan eksperimen di atas, kita juga dapat mengevaluasi konversi LoRA ke LoRA (yaitu kompresi LoRA). Di sini, kita memulai dengan adapter LoRA ber-rank 64 yang dilatih pada setup yang sama seperti di atas menggunakan RS-LoRA. Adapter awal memiliki 18.350.080 parameter yang dapat dilatih, akurasi uji 52,92%, dan membutuhkan 12,58 GB memori untuk evaluasi. Tabel berikut menunjukkan hasil konversi adapter ini menjadi adapter LoRA dengan rank yang lebih kecil:

rankparameter yang dapat dilatihakurasi uji (%)perubahan akurasimemori yang dicadangkan (maks, GB)peningkatan memori
8229376043.37-9.5512.38-0.20
16458752048.90-4.0212.38-0.20
32917504051.48-1.4412.49-0.09
481376256052.01-0.9112.38-0.20
0.5215040044.12-8.8012.37-0.21
0.6308224047.54-5.3812.37-0.21
0.7444825650.49-2.4312.37-0.21
0.8651059250.11-2.8112.37-0.21
0.91002291251.55-1.3712.38-0.20
0.951297612852.62-0.3012.39-0.19

Sebagai contoh, untuk rank 0.95, kita dapat memperkecil selisih akurasi menjadi hanya 0,3 poin persentase sambil mengurangi jumlah parameter sebesar 30%. Perhatikan juga bahwa LoRA yang dikompresi ini dapat lebih baik daripada melatihnya secara langsung pada rank yang lebih rendah β€” misalnya, untuk rank 32, pelatihan langsung menghasilkan akurasi uji 48,22%, sedangkan konversi dari rank 64 menghasilkan 51,48%.

Catatan

Ada beberapa keterbatasan pada konversi LoRA. Seperti yang disebutkan di atas, penurunan kinerja diharapkan terjadi dan LoRA yang dikonversi kemungkinan besar akan kurang efisien dalam hal parameter dibandingkan adapter aslinya. Selain itu, konversi LoRA memiliki keterbatasan berikut:

  • Saat ini, hanya adapter yang diterapkan pada lapisan linear yang dapat dikonversi.
  • Tidak semua metode PEFT saat ini mendukung konversi LoRA.

Jika ada banyak permintaan untuk memperluas konversi LoRA, silakan beri tahu kami dengan membuat diskusi GitHub dan kami akan membuatnya berfungsi dengan lebih banyak tipe layer dan metode PEFT.

API

Mengonversi model non-LoRA menjadi model LoRA, mengembalikan LoraConfig dan state_dict

peft.convert_to_lora

< >

( model: Modulerank: floatadapter_name: str = 'default'progressbar: bool = Falsecompile_kwargs = None )

Parameter

  • model β€” Model yang akan dikonversi. Harus berupa model yang memiliki lapisan PEFT yang mendukung konversi.
  • rank (int atau float) β€” Rank yang diinginkan untuk adapter LoRA yang dikembalikan. Rank yang lebih tinggi menghasilkan adapter LoRA yang lebih akurat mencerminkan adapter asli. Namun, hal ini juga akan membutuhkan lebih banyak memori, komputasi, dan ruang disk. Oleh karena itu, pilih nilai yang mewakili kompromi terbaik untuk kasus penggunaan Anda dan validasi adapter akhir. Jika float diberikan, nilainya diinterpretasikan sebagai ambang batas varians/energi yang dijelaskan: kami memilih rank k terkecil sehingga k nilai singular teratas menyumbang setidaknya fraksi tersebut dari total nilai singular kuadrat. Ini secara efektif menghasilkan rank yang lebih rendah jika beberapa nilai singular dapat menangkap adaptasi dari layer ini. Float yang lebih rendah berarti rank lebih rendah dan sebaliknya. Perhatikan bahwa rank dinamis dapat menyebabkan rank yang sangat tidak merata per layer, yang berarti beberapa layer mungkin membutuhkan jumlah memori yang tidak proporsional untuk aktivasi. Memilih rank tetap (int) lebih baik untuk mencapai kebutuhan memori yang dapat diprediksi.
  • adapter_name (str, opsional) β€” Nama adapter yang akan dikonversi. Hanya dapat mengonversi satu adapter pada satu waktu. Defaultnya adalah "default".
  • progressbar (bool) β€” apakah menampilkan progressbar yang menunjukkan kemajuan konversi (dapat memakan waktu beberapa menit untuk model besar).
  • compile_kwargs (dict, opsional) β€” Jika disediakan, kompilasi fungsi untuk mengonversi modul individual menjadi LoRA dengan kwargs yang diberikan diteruskan ke torch.compile. Hal ini berpotensi mempercepat konversi pada model besar.

Konversi model non-LoRA dengan lapisan PEFT menjadi checkpoint LoRA.

Ini hanya didukung untuk beberapa metode PEFT tertentu yang memungkinkan konversi ekuivalen. Pada dasarnya, ini merujuk pada metode PEFT yang bekerja dengan memperbarui bobot dasar dengan bobot delta. Selain itu, saat ini hanya lapisan linear yang didukung.

Adaptor LoRA akan berusaha mengaproksimasi adaptor awal sedekat mungkin. Semakin tinggi rank, semakin baik aproksimasinya. Diperkirakan bahwa aproksimasi tidak akan pernah mencapai kinerja penuh dari adaptor asli, dan efisiensi parameter dari adaptor LoRA akan lebih rendah daripada adaptor asli (yaitu, untuk kinerja yang serupa, adaptor ini akan membutuhkan lebih banyak parameter). Konversi ini masih dapat berguna dalam banyak situasi:

  • Di PEFT, LoRA mendukung lebih banyak fitur daripada sebagian besar metode lain, misalnya batch adapter campuran. Dengan demikian, adapter yang dikonversi dapat digunakan dengan fitur-fitur tersebut.
  • Beberapa paket hilir mendukung adapter LoRA, tetapi tidak mendukung metode PEFT lainnya, misalnya Diffusers. Konversi ini memungkinkan penggunaan adapter non-LoRA dengan paket-paket tersebut.

Faktor penskalaan LoRA sudah tertanam dalam bobot LoRA, sehingga penskalaan akan selalu satu (yaitu, rank dan alpha dipilih agar identik).

Catatan: Fungsi ini belum mendukung model yang dipecah (sharded).

Raises TypeError: Jika model yang diberikan tidak memiliki lapisan apa pun yang dapat dikonversi ke LoRA, TypeError akan dilempar. ValueError: Jika rank yang dipilih tidak valid (terlalu tinggi atau terlalu rendah).

Mengonversi model non-LoRA menjadi model LoRA, menyimpan checkpoint adapter dan konfigurasi di path yang diberikan

peft.save_as_lora

< >

( path: str | os.PathLikemodel: Modulerank: floatadapter_name: str = 'default'progressbar: bool = Falsecompile_kwargs = None )

Parameter

  • model β€” Model yang akan dikonversi. Harus berupa model yang memiliki lapisan PEFT yang mendukung konversi.
  • rank (int atau float) β€” Rank yang diinginkan untuk adapter LoRA yang dikembalikan. Rank yang lebih tinggi menghasilkan adapter LoRA yang lebih akurat mencerminkan adapter asli. Namun, hal ini juga akan membutuhkan lebih banyak memori, komputasi, dan ruang disk. Oleh karena itu, pilih nilai yang mewakili kompromi terbaik untuk kasus penggunaan Anda dan validasi adapter akhir. Jika float diberikan, nilainya diinterpretasikan sebagai ambang batas varians/energi yang dijelaskan: kami memilih rank k terkecil sehingga k nilai singular teratas menyumbang setidaknya fraksi tersebut dari total nilai singular kuadrat. Ini secara efektif menghasilkan rank yang lebih rendah jika beberapa nilai singular dapat menangkap adaptasi dari layer ini. Float yang lebih rendah berarti rank lebih rendah dan sebaliknya. Perhatikan bahwa rank dinamis dapat menyebabkan rank yang sangat tidak merata per layer, yang berarti beberapa layer mungkin membutuhkan jumlah memori yang tidak proporsional untuk aktivasi. Memilih rank tetap (int) lebih baik untuk mencapai kebutuhan memori yang dapat diprediksi.
  • adapter_name (str, opsional) β€” Nama adapter yang akan dikonversi. Hanya dapat mengonversi satu adapter pada satu waktu. Defaultnya adalah "default".
  • progressbar (bool) β€” apakah menampilkan progressbar yang menunjukkan kemajuan konversi (dapat memakan waktu beberapa menit untuk model besar).
  • compile_kwargs (dict, opsional) β€” Jika disediakan, kompilasi fungsi untuk mengonversi modul individual menjadi LoRA dengan kwargs yang diberikan diteruskan ke torch.compile. Hal ini berpotensi mempercepat konversi pada model besar.

Konversi model non-LoRA dengan lapisan PEFT menjadi LoRA, lalu simpan file checkpoint dan konfigurasi PEFT.

Ini hanya didukung untuk beberapa metode PEFT tertentu yang memungkinkan konversi ekuivalen. Pada dasarnya, ini merujuk pada metode PEFT yang bekerja dengan memperbarui bobot dasar dengan bobot delta. Selain itu, saat ini hanya lapisan linear yang didukung.

Adaptor LoRA akan berusaha mengaproksimasi adaptor awal sedekat mungkin. Semakin tinggi rank, semakin baik aproksimasinya. Diperkirakan bahwa aproksimasi tidak akan pernah mencapai kinerja penuh dari adaptor asli, dan efisiensi parameter dari adaptor LoRA akan lebih rendah daripada adaptor asli (yaitu, untuk kinerja yang serupa, adaptor ini akan membutuhkan lebih banyak parameter). Konversi ini masih dapat berguna dalam banyak situasi:

  • Di PEFT, LoRA mendukung lebih banyak fitur daripada sebagian besar metode lain, misalnya batch adapter campuran. Dengan demikian, adapter yang dikonversi dapat digunakan dengan fitur-fitur tersebut.
  • Beberapa paket hilir mendukung adapter LoRA, tetapi tidak mendukung metode PEFT lainnya, misalnya Diffusers. Konversi ini memungkinkan penggunaan adapter non-LoRA dengan paket-paket tersebut.

Faktor penskalaan LoRA sudah tertanam dalam bobot LoRA, sehingga penskalaan akan selalu satu (yaitu, rank dan alpha dipilih agar identik).

Anda dapat memuat bobot LoRA yang telah dikonversi seperti ini:

>>> lora_path = ...
>>> save_as_lora(lora_path, model, rank=...)
>>> base_model = AutoModel.from_pretrained(...)
>>> lora_model = PeftModel.from_pretrained(base_model, lora_path)

Catatan: Fungsi ini belum mendukung model yang dipecah (sharded).

Raises TypeError: Jika model yang diberikan tidak memiliki lapisan apa pun yang dapat dikonversi ke LoRA, TypeError akan dilempar. ValueError: Jika rank yang dipilih tidak valid (terlalu tinggi atau terlalu rendah).

Update on GitHub