Dev.to AI πŸ€– Ai πŸ‘ 0 πŸ“– 3 min read

Apa yang sebenarnya dilatih oleh fine-tuning LoRA?

"LoRA melatih sekitar 1% dari model" adalah penjelasan satu baris yang biasa kita dengar. Itu benar, tetapi menyembunyikan bagian-bagian yang menentukan apakah satu proses training muat di mesin Anda dan berapa lama wakt

Apa yang sebenarnya dilatih oleh fine-tuning LoRA?

"LoRA melatih sekitar 1% dari model" adalah penjelasan satu baris yang biasa kita dengar. Itu benar, tetapi menyembunyikan bagian-bagian yang menentukan apakah satu proses training muat di mesin Anda dan berapa lama waktunya: layer mana yang diberi adapter, apa pengaruh rank terhadap jumlahnya, dalam presisi apa weights yang dibekukan disimpan, dan berapa banyak langkah optimizer yang sebenarnya dihasilkan dataset kecil.

Berikut hitungannya untuk satu proses konkret: Qwen2.5-1.5B-Instruct, rank 16, di Mac Apple Silicon 16GB. Pengaturannya adalah nilai bawaan trainer lokal di aplikasi desktop osFoundry, yang berupa skrip biasa dengan transformers + PEFT + TRL, jadi hitungannya berlaku untuk setup serupa mana pun. (Halaman fine-tuning LoRA di aplikasi menampilkan antarmukanya.)

Langkah konfigurasi: Local, LoRA, rank 16, alpha 32

Satu adapter adalah dua matriks tipis

Untuk matriks weight W berukuran d_out Γ— d_in, LoRA membekukan W dan mempelajari dua matriks, A (r Γ— d_in) dan B (d_out Γ— r). Output layer menjadi WΒ·x + (Ξ±/r)Β·BΒ·AΒ·x. B dimulai dari nol, jadi training berangkat tepat dari model dasar.

Jumlah parameter yang bisa dilatih untuk layer itu adalah r Γ— (d_in + d_out). Jumlahnya naik linear terhadap rank dan lebar layer, bukan terhadap luasnya.

Di mana adapter dipasang

Trainer memasang adapter pada ketujuh proyeksi linear di setiap blok transformer:

target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
                "gate_proj", "up_proj", "down_proj"]

Qwen2.5-1.5B punya 28 blok, hidden size 1536, ukuran MLP 8960, dan grouped-query attention dengan 2 KV head berdimensi 128, sehingga k dan v memproyeksikan turun ke 256. Per blok, pada r = 16:

Layer d_in β†’ d_out Dapat dilatih
q_proj 1536 β†’ 1536 49,152
k_proj 1536 β†’ 256 28,672
v_proj 1536 β†’ 256 28,672
o_proj 1536 β†’ 1536 49,152
gate_proj 1536 β†’ 8960 167,936
up_proj 1536 β†’ 8960 167,936
down_proj 8960 β†’ 1536 167,936

Totalnya 659,456 per blok, dan 18,464,768 untuk 28 blok: 18.5M parameter yang dilatih dari total 1.54B, atau 1.2%.

Ada dua hal yang menonjol. Proyeksi MLP memegang tiga perempat weight adapter, jadi kalau dilewati (seperti beberapa resep lama yang hanya mengadaptasi q dan v), jumlahnya turun menjadi sekitar 2.2M, seperdelapan dari kapasitas. Dan karena GQA membuat k dan v sempit, adapter untuk keduanya murah.

Sebagian besar memori dipakai weights yang dibekukan

Di GPU Apple, trainer memuat model dalam float32:

torch_dtype = torch.float16 if device == "cuda" else torch.float32

Half precision di MPS cenderung menghasilkan loss NaN, jadi 32-bit adalah pilihan aman di sana. Itu membuat base yang dibekukan berukuran 1.54B Γ— 4 byte β‰ˆ 6.2 GB.

Bagian yang dilatih kecil sekali jika dibandingkan. 18.5M weight dalam fp32 adalah 74 MB, gradiennya 74 MB lagi, dan AdamW menyimpan dua estimasi momen per weight, 148 MB lagi. Totalnya sekitar 0.3 GB. Sisa anggaran dipakai untuk aktivasi, yang skalanya mengikuti batch size dan panjang sekuens (trainer membatasi sekuens sampai 2048 token; balasan chat yang pendek jauh di bawah itu).

Dengan sekitar 12 GB dari Mac 16 GB yang bisa dipakai GPU, model 1.5B dalam fp32 masih menyisakan ruang. Base 7B dalam fp32 sudah sekitar 30 GB bahkan sebelum training dimulai. Itu sebabnya di Mac model dasarnya dijaga tetap kecil, dan itu sebabnya QLoRA (weights beku 4-bit) ada, meski jalur 4-bit dari bitsandbytes membutuhkan GPU NVIDIA, sehingga di Mac yang dipakai LoRA biasa.

Dataset kecil berarti update yang lebih sedikit dari dugaan

Trainer memakai batch size 4 dengan 4 langkah gradient accumulation, jadi setiap update optimizer melihat 16 contoh. Dengan 200 pasangan:

  • 200 Γ· 4 = 50 batch forward/backward per epoch
  • 50 Γ· 4 β‰ˆ 13 update optimizer per epoch
  • 3 epoch β‰ˆ 39 update total, 10 yang pertama berupa warmup learning rate

Tiga puluh sembilan update dengan learning rate 2e-4 dan penurunan linear cukup untuk menggeser gaya bahasa, tetapi tidak cukup untuk mengajarkan pengetahuan baru. Ini sesuai dengan yang terlihat dalam praktik: beberapa ratus balasan mengubah cara model menulis, bukan apa yang diketahuinya.

Training LoRA lokal yang sedang berjalan, epoch 3 dari 3

Apa hasilnya

Setelah training, hanya adapter yang disimpan: A dan B untuk masing-masing dari 196 layer yang diadaptasi, puluhan megabyte. Untuk inferensi, aplikasi mengubahnya menjadi file LoRA GGUF dan llama.cpp menerapkannya di atas salinan base yang sudah dikuantisasi, di sini qwen2.5-1.5b-instruct pada Q4_K_M. Base-nya dipakai bersama, jadi beberapa adapter (satu per gaya bahasa atau tugas) masing-masing hanya memakan beberapa puluh MB.

Contoh: model dasar dan adapter pada prompt yang sama

Perhatikan ketidakcocokan presisinya: adapter dilatih terhadap weights dasar fp32 dan dijalankan terhadap weights 4-bit. Untuk adapter gaya yang kecil, perbedaannya biasanya tidak terasa, tetapi ini salah satu alasan model yang di-merge lalu dikuantisasi ulang bisa berperilaku sedikit berbeda dari adapter yang sama yang diterapkan saat runtime.

πŸ“° Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.