- LoRA (Low-Rank Adaptation) adalah teknik untuk mengurangi biaya fine-tuning dengan memperbarui hanya matriks kecil berperingkat rendah tanpa melatih ulang seluruh LLM; Studio ini mengimplementasikan layer LoRA secara langsung untuk memeriksa cara kerjanya
- Intinya adalah mengaproksimasi perubahan bobot ΔW pada fine-tuning umum sebagai hasil perkalian dua matriks kecil
A dan B; makin kecil rank r, makin berkurang parameter pelatihan sekaligus kapasitas representasinya
- Matriks bobot 5.000×10.000 memiliki 50 juta parameter, tetapi LoRA dengan
r=8 hanya menambahkan B 5.000×8 dan A 8×10.000, sehingga menjadi 120 ribu parameter, 400 kali lebih kecil
- Pada klasifikasi sentimen IMDb berbasis DistilBERT, LoRA dasar mencatat Test acc 89,44%, lebih tinggi daripada 86,22% saat hanya melatih dua layer terakhir, tetapi lebih rendah daripada 92,31% dari fine-tuning penuh
- Setelah eksplorasi hyperparameter, LoRA mencatat Val acc 92,96% dan Test acc 92,39% dengan sekitar 500 ribu parameter pelatihan, menghasilkan akurasi sedikit lebih tinggi daripada fine-tuning penuh yang melatih 66.955.010 parameter
Biaya fine-tuning yang dikurangi LoRA
- LoRA adalah singkatan dari Low-Rank Adaptation, sebuah teknik untuk melakukan fine-tuning LLM dengan lebih efisien
- Fine-tuning umum menyesuaikan semua parameter model deep learning, tetapi LoRA hanya memperbarui sekumpulan kecil matriks berperingkat rendah
- LLM pralatih dapat digunakan untuk banyak tugas, tetapi fine-tuning berguna untuk menyesuaikannya dengan dataset atau tugas tertentu
- Makin besar model, pendekatan memperbarui semua layer makin membebani biaya komputasi
Mengaproksimasi ΔW sebagai perkalian matriks kecil
- Dalam fine-tuning umum, pembaruan matriks bobot
W dihitung sebagai ΔW
- LoRA mengaproksimasi
ΔW sebagai hasil perkalian dua matriks kecil A dan B
- Jika Anda familier dengan PCA atau SVD, ini bisa dipandang mirip dengan memfaktorkan
ΔW menjadi A dan B
- Rank
r adalah hyperparameter LoRA
r yang lebih kecil dapat mengurangi jumlah parameter pelatihan, mempercepat pelatihan, dan menurunkan kebutuhan komputasi
- Pada saat yang sama, kapasitas matriks berperingkat rendah untuk menangkap informasi spesifik tugas juga menurun
- Contoh matriks bobot 5.000×10.000:
- Pembaruan umum
ΔW: total 50 juta parameter
- LoRA
r=8: B 5.000×8, A 8×10.000
- Parameter tambahan: 80.000 + 40.000 = 120.000
- 400 kali lebih kecil dibanding fine-tuning umum
- Dalam penggunaan nyata, berbagai nilai
r perlu dicoba untuk menemukan keseimbangan antara performa dan biaya
Mengimplementasikan layer LoRA dengan PyTorch
LoRALayer dasar menerima dimensi input, dimensi output, rank, dan koefisien penskalaan alpha
class LoRALayer(torch.nn.Module):
def __init__(self, in_dim, out_dim, rank, alpha):
super().__init__()
std_dev = 1 / torch.sqrt(torch.tensor(rank).float())
self.A = torch.nn.Parameter(torch.randn(in_dim, rank) * std_dev)
self.B = torch.nn.Parameter(torch.zeros(rank, out_dim))
self.alpha = alpha
def forward(self, x):
x = self.alpha * (x @ self.A @ self.B)
return x
in_dim adalah dimensi input layer tempat LoRA diterapkan, dan out_dim adalah dimensi output
rank mengendalikan kompleksitas matriks A dan B serta jumlah parameter yang ditambahkan LoRA
alpha menentukan besar perubahan yang diberikan LoRA pada bobot model yang sudah ada
- Jika
alpha tinggi, perilaku model disesuaikan lebih besar
- Jika
alpha rendah, perubahannya lebih halus
A diinisialisasi dengan bilangan acak kecil, dan simpangan bakunya ditentukan oleh akar kuadrat rank
- Ini dipilih agar nilai awal
A tidak terlalu besar
B diinisialisasi dengan nol
- Sebelum pelatihan dimulai, karena
B=0, maka AB=0
- Sebelum
A dan B diperbarui melalui backpropagation, LoRALayer tidak memengaruhi bobot asli
Mengganti layer Linear dengan LinearWithLoRA
- LoRA biasanya diterapkan pada layer Linear/feed-forward dalam jaringan saraf
- Jika forward yang ada memanggil dua layer Linear secara berurutan, setelah menerapkan LoRA, output LoRA ditambahkan ke output masing-masing Linear
def forward(self, x):
x = self.linear_1(x) + self.lora_1(x)
x = F.relu(x)
x = self.linear_2(x) + self.lora_2(x)
return logits
- Saat memodifikasi model PyTorch yang ada, cara sederhananya adalah mengganti tiap layer
Linear dengan LinearWithLoRA
class LinearWithLoRA(torch.nn.Module):
def __init__(self, linear, rank, alpha):
super().__init__()
self.linear = linear
self.lora = LoRALayer(
linear.in_features, linear.out_features, rank, alpha
)
def forward(self, x):
return self.linear(x) + self.lora(x)
LinearWithLoRA menyimpan layer Linear asli bersama LoRALayer baru
- Dengan mengganti layer
Linear pada model pralatih dengan LinearWithLoRA, Anda dapat memasang LoRA lalu melakukan fine-tuning
Eksperimen klasifikasi IMDb dengan DistilBERT
- Contoh praktik ini menggunakan klasifikasi teks, yang akurasinya lebih mudah dievaluasi dibanding teks generatif
- Model menggunakan DistilBERT pralatih dari Hugging Face transformers
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained(
"distilbert-base-uncased", num_labels=2)
- Untuk melatih hanya bobot LoRA baru,
requires_grad dari semua parameter model diatur ke False
for param in model.parameters():
param.requires_grad = False
- DistilBERT memiliki 6 layer Transformer, dan di dalam tiap layer ada layer Linear
- Pada attention terdapat
q_lin, k_lin, v_lin, out_lin
- Pada FFN terdapat
lin1, lin2
- Di sisi output terdapat dua layer Linear,
pre_classifier dan classifier
Konfigurasi untuk menerapkan LoRA secara selektif
- Konfigurasi LoRA dasar menerapkan LoRA hanya pada matriks bobot query dan value di attention
lora_r = 8
lora_alpha = 16
lora_dropout = 0.05
lora_query = True
lora_key = False
lora_value = True
lora_projection = False
lora_mlp = False
lora_head = False
- Dengan melakukan loop pada tiap layer Transformer di DistilBERT, layer Linear yang dipilih diganti dengan
LinearWithLoRA
- Jika
lora_query=True, ganti q_lin
- Jika
lora_key=True, ganti k_lin
- Jika
lora_value=True, ganti v_lin
- Jika
lora_projection=True, ganti out_lin
- Jika
lora_mlp=True, ganti ffn.lin1, ffn.lin2
- Jika
lora_head=True, ganti pre_classifier, classifier
- Setelah penggantian, output model dapat memperlihatkan bahwa
q_lin, v_lin, dan lainnya telah berubah menjadi LinearWithLoRA
Perbandingan LoRA dasar dan fine-tuning umum
- Hasil pelatihan klasifikasi IMDb Movie Reviews dengan konfigurasi LoRA dasar:
- Train acc: 92,15%
- Val acc: 89,98%
- Test acc: 89,44%
- Hasil fine-tuning hanya dua layer output terakhir:
- Train acc: 86,68%
- Val acc: 87,26%
- Test acc: 86,22%
- Jumlah parameter pelatihan: 592.130
- LoRA dasar memiliki Test acc lebih tinggi daripada metode yang hanya melatih dua layer terakhir, dengan jumlah parameter pelatihan lebih sedikit, yaitu 147.456
- Hasil fine-tuning seluruh layer dengan cara tradisional:
- Train acc: 96,41%
- Val acc: 92,80%
- Test acc: 92,31%
- Jumlah parameter pelatihan: 66.955.010
- Fine-tuning penuh memiliki Test acc sekitar 2% lebih tinggi daripada LoRA dasar, tetapi memperbarui sekitar 450 kali lebih banyak parameter dibanding konfigurasi LoRA
Eksplorasi hyperparameter LoRA
- Performa LoRA dapat bervariasi tergantung pada
lora_r, lora_alpha, dan pengaturan layer target penerapan
03_finetune-lora.py menerima hyperparameter sebagai argumen command-line
python 03_finetune-lora.py --lora_alpha 32 --lora_r 16
- Target penerapan LoRA lainnya juga dapat diaktifkan bersamaan
python 03_finetune-lora.py \
--lora_alpha 32 \
--lora_r 16 \
--lora_query True \
--lora_key True \
--lora_value True \
--lora_projection True \
--lora_mlp True \
--lora_head True
03_gridsearch.py menjalankan grid berikut pada semua GPU yang tersedia
alpha_values = [1, 4, 8, 16, 32, 64]
rank_values = [1, 2, 4, 8, 16, 32]
lora_query = ["True"]
lora_key = ["False", "True"]
lora_value = ["True"]
lora_projection = ["False", "True"]
lora_mlp = ["False", "True"]
lora_head = ["False", "True"]
- Skrip dapat dijalankan melalui Visual Studio Code, terminal command-line, atau Job; Job akan otomatis berhenti setelah selesai
- Hasil disimpan di
results.txt
Konfigurasi terbaik dari pencarian grid
- Berdasarkan
results.txt, konfigurasi hyperparameter terbaik adalah sebagai berikut
lora_r: 8
lora_alpha: 1
lora_query: True
lora_key: False
lora_value: True
lora_projection: False
lora_mlp: True
lora_head: False
- Hasil dari konfigurasi ini:
- Val acc: 92,96%
- Test acc: 92,39%
- Konfigurasi LoRA ini memiliki sekitar 500k parameter pelatihan, jauh lebih sedikit daripada 66M parameter pada fine-tuning penuh
- Akurasinya sedikit lebih tinggi daripada Val acc 92,80% dan Test acc 92,31% dari fine-tuning penuh
Lingkungan eksekusi dan materi tambahan
- Dengan mengeklik Run di bagian atas Studio, Anda dapat menggandakan lingkungan yang berisi kode
- Setelah Studio digandakan, file kode dapat dijalankan tanpa langkah instalasi, unduhan, atau konfigurasi tambahan
- Notebook dan skrip terkait:
00_lora-layer.ipynb: implementasi layer LoRA
01_finetune-last-layers.ipynb: fine-tuning layer terakhir
02_finetune-with-lora.ipynb: fine-tuning dengan LoRA
03_finetune-lora.py: menjalankan LoRA dengan argumen hyperparameter
03_gridsearch.py: pencarian grid hyperparameter LoRA
04_finetune-all-layers.ipynb: fine-tuning seluruh layer
- Materi tambahan:
1 komentar
Komentar Hacker News
Alur tekniknya mengikuti LLMs 101 dari Maxime Labonne: https://github.com/mlabonne/llm-course#4-supervised-fine-tun...
LoRA != LoRa, jadi terus bikin bingung. Saya tidak suka mereka memakai ulang akronim yang sudah ada
Terutama di tempat seperti halaman depan HN, di mana kedua makna sama-sama wajar
Masih terasa aneh bahwa di bidang ilmu komputer ada ucapan seperti “kita tidak tahu persis bagaimana angka-angka ini, yaitu hyperparameter, memengaruhi hasil, jadi mari coba berbagai nilai lalu pakai yang paling bagus”
Kadang bisa tersangkut di maksimum lokal alih-alih optimum/jawaban benar, tetapi tetap bekerja. Karena tidak bisa diselesaikan dengan rumus bentuk tertutup, kita mengambil sampel acak kira-kira miliaran kali untuk menemukan nilai yang diinginkan. Bukan berarti LLM juga persis sama, tetapi pendekatan seperti ini cukup sering dipakai
Sampai sekarang sebagian besar industri ini adalah hal yang dirancang secara rekayasa, sedangkan LLM lebih dekat ke sesuatu yang ditemukan
Idealnya memang perlu landasan teoretis, tetapi untuk menarik cukup data guna membuat atau memverifikasi teori, kadang diperlukan pencarian acak
Kita tertinggal beberapa tahun dari posisi yang seharusnya. Saat saya bekerja di industri game pada 1990-an, “akal sehat” saat itu adalah bahwa neural network paling banter jalan buntu, paling buruk penipuan. Sangat disayangkan begitu banyak waktu hilang karena beberapa figur otoritatif mencegah semua orang mencobanya, dan kali ini kita harus memastikan hal itu tidak terulang
Masih belum jelas kapan harus melakukan fine-tuning dan kapan memakai RAG
Dulu saya mengira fine-tuning terutama dipakai untuk mengubah perilaku model, tetapi belakangan beberapa perusahaan tampaknya juga memakai fine-tuning untuk menambahkan pengetahuan. Saya penasaran apa penggunaan utama fine-tuning
Menurut saya penggunaan utamanya masih perubahan perilaku. Misalnya instruction fine-tuning dan fine-tuning untuk klasifikasi
Menambahkan pengetahuan ke bobot paling baik dilakukan lewat pre-training. Atau jika ada database eksternal atau dokumen yang akan dikueri saat generasi, gunakan RAG seperti untuk pertanyaan. Sebagai catatan, di NeurIPS 2023 LLM Efficiency Challenge, semua pemenang yang melakukan fine-tuning LLM “terbaik” dalam 24 jam dengan 1 GPU memakai LoRA atau QLoRA (LoRA terkuantisasi)
Jika data tambahan tidak ringkas atau membutuhkan konteks, fine-tuning lebih baik daripada RAG
Jika konteks terlalu banyak atau fokusnya kabur, kepatuhan terhadap prompt bisa terdilusi, dan RAG tidak membuat model mempelajari asosiasi token berdimensi lebih tinggi. Jadi Anda harus beruntung mengambil konten yang dibutuhkan dari materi pelengkap, dan itu tidak jauh lebih baik daripada mesin pencari yang agak canggih. Ini terutama bermasalah ketika menangani korpus khusus yang memiliki mikro-dialek internal sendiri dan tidak banyak muncul di dataset publik, seperti dokumen internal pemerintah atau perusahaan besar
Sejauh pemahaman saya, fine-tuning luar biasa efektif [0]. Sebab in-context learning sangat bergantung pada seberapa kuat model dasar dan bagaimana RAG disusun, yaitu pemrosesan kueri, pencarian embedding, pemeringkatan hasil, dan sebagainya [1]
Menurut paper yang saya baca, fine-tuning dapat menambahkan pengetahuan domain baru atau memperkuat pengetahuan tertentu, sedangkan RAG terbatas pada penguatan saja. Namun, dua teknik dengan trade-off berbeda ini kadang menunjukkan kemampuan pada tingkat yang mirip [2]
[0] Fast.ai: Can Models learn from one sample, https://www.fast.ai/posts/2023-09-04-learning-jumps/ / https://archive.is/eJMPR
[1] LlamaIndex: Advanced RAG, https://blog.llamaindex.ai/a-cheat-sheet-and-some-recipes-fo... / https://archive.is/qtBXX
[2] Microsoft: RAG vs Fine-tuning: Pipelines, Tradeoffs, and a Case Study, https://arxiv.org/html/2401.08406v2#S6 / https://archive.is/UQ8Sa#S6
Ini adalah model autoregresif. Jika ada jenis sekuens baru yang elemen berikutnya dapat diprediksi dari bagian sebelumnya, dan caranya berbeda dari yang pernah dilihat model sebelumnya, fine-tuning tampaknya masuk akal
Sebagai kriteria untuk menentukan apa yang harus dilakukan dalam situasi data tertentu, ini memang cukup kabur, tetapi mungkin cukup sebagai heuristik kasar. Apakah penambahan pengetahuan termasuk di sini mungkin soal selera tanpa eksperimen
Tulisan yang bagus. Saya bukan orang di bidang ini, tetapi saat membaca makalah aslinya, saya memahami bahwa LoRA hanya diterapkan pada lapisan padat terakhir, dan tidak diterapkan secara independen ke semua lapisan. Bisa jadi saya salah baca
Setelah menelusuri kenapa implementasi di tautan itu seperti ini, ternyata QLoRA memakai cara ini dan tampaknya ada efek yang menarik. Akan bagus jika ditambahkan catatan tentang keputusan QLoRA tersebut. Namun saya tidak terlalu paham kenapa ini bekerja; dari sudut pandang pemula, menerapkan LoRA pada lapisan terakhir masuk akal, tetapi saya belum menangkap dasar untuk menerapkannya berulang pada setiap lapisan linear. Bisa jelaskan intuisiinyaa?
Semakin banyak lapisan yang diganti menjadi lapisan LoRA, semakin besar derajat kebebasan dalam optimisasi. Sebagian metode fine-tuning menyarankan hanya melakukan fine-tuning pada lapisan terakhir, karena diasumsikan memuat representasi input yang “paling tingkat tinggi”. Metode lain melakukan fine-tuning pada semua lapisan. Sebagian besar bergantung pada data dan masalahnya, dan LoRA mencerminkan praktik ini apa adanya
Saya lebih suka pendekatan mulai dari konfigurasi, bukan “dari nol” ala Axolotl. Axolotl mendukung fine-tuning Mistral dan Llama 2, serta banyak teknik modern seperti sample packing, FlashAttention, dan xFormers
Alih-alih belajar LoRA dari nol, saya fokus mengumpulkan dan mengkurasi data fine-tuning, lalu melakukan fine-tuning yang berpusat pada data
https://github.com/Lightning-AI/lit-gpt
Penamaan memang sulit. Awalnya saya kira ini membahas LoRa yang berarti “long range”, atau LoRaWAN untuk komunikasi sensor IoT
Library apa yang paling banyak dipakai untuk fine-tuning? Maksudnya untuk cara yang bukan “dari nol”
Wah, awalnya saya juga tentu saja mengira ini membahas LoRa
Seberapa besar biaya performa LoRA?
Saat inferensi, ada dua kemungkinan. Jika nilai LoRA ditambahkan secara dinamis selama forward pass, secara teori bisa sedikit lebih lambat, tetapi ini juga bisa menjadi keunggulan jika ingin mempertahankan set bobot kecil yang terpisah untuk tiap pelanggan. Sebab, kita bisa menjalankan satu model dasar besar saja dan menerapkan bobot LoRA per pelanggan secara langsung. Jika bobot LoRA digabungkan kembali ke model dasar, performanya bisa persis sama dengan model dasar