TRL documentation
LoRA Tanpa Penyesalan
LoRA Tanpa Penyesalan
Penelitian terbaru dari tim di Thinking Machines Lab (Schulman et al., 2025) menunjukkan bahwa LoRA dapat menyamai kinerja fine-tuning penuh ketika dikonfigurasi dengan benar, sambil hanya menggunakan sekitar 67% dari komputasi. Temuan ini menarik bagi pengguna TRL karena mudah diimplementasikan dan dapat meningkatkan kinerja model dengan anggaran yang lebih kecil.
Panduan ini menyediakan instruksi sederhana untuk mereproduksi hasil dari blog post di TRL.
Disarankan untuk membaca artikel blog sebelum mengikuti panduan ini, atau merujuk kedua sumber secara paralel untuk hasil terbaik.
Keuntungan LoRA dibandingkan fine-tuning penuh
Pertama-tama, mari kita ingatkan kembali manfaat LoRA dibandingkan fine-tuning penuh.
LoRA menambahkan lapisan adapter di atas model dasar, yang berisi jauh lebih sedikit parameter daripada model dasar itu sendiri. Desain ini mengurangi kebutuhan memori GPU dan memungkinkan pelatihan yang lebih efisien. Seperti yang dijelaskan dalam blog, pendekatan ini awalnya dianggap melibatkan trade-off performa, meskipun konfigurasi yang cermat dapat mengatasi trade-off ini dan menyamai performa fine-tuning penuh.
Contoh dengan TRL
Mari kita implementasikan dan latih adapter LoRA dalam skrip TRL berdasarkan temuan utama dari blog post tersebut. Setelahnya, kita akan meninjau kembali setiap temuan dengan mempertimbangkan hasil dari TRL.
Penyesuaian Halus Berpengawas (SFT)
Artikel blog tersebut melakukan SFT pada berbagai model dan dataset dari Hub, yang dapat kami replikasi di TRL.
Kami dapat mengintegrasikan temuan-temuan ini dengan TRL Python API seperti berikut:
from datasets import load_dataset
from peft import LoraConfig
from trl import SFTTrainer, SFTConfig
dataset = load_dataset("open-thoughts/OpenThoughts-114k", split="train")
peft_config = LoraConfig(r=256, lora_alpha=16, target_modules="all-linear")
training_args = SFTConfig(
learning_rate=2e-4,
per_device_train_batch_size=1,
gradient_accumulation_steps=4,
num_train_epochs=1,
report_to=["trackio"],
)
trainer = SFTTrainer(
model="Qwen/Qwen2.5-3B-Instruct",
train_dataset=dataset,
peft_config=peft_config,
args=training_args,
)
trainer.train()
hf jobs uv run \
--flavor a100-large \
--timeout 8h \
--secrets HF_TOKEN \
"https://raw.githubusercontent.com/huggingface/trl/main/trl/scripts/sft.py" \
--model_name_or_path Qwen/Qwen2.5-3B-Instruct \
--dataset_name open-thoughts/OpenThoughts-114k \
--learning_rate 2.0e-5 \
--num_train_epochs 1 \
--packing \
--per_device_train_batch_size 2 \
--gradient_accumulation_steps 16 \
--use_peft \
--lora_r 256 \
--lora_alpha 16 \
--lora_target_modules all-linear \
--output_dir Qwen2.5-3B-OpenThoughts-LoRA \
--report_to trackio \
--push_to_hub
Untuk menggunakan Hugging Face Jobs, masuk ke Hub (hf auth login) dan pastikan memiliki saldo kredit yang positif. Lihat dokumentasi Jobs untuk detailnya.
uv run "https://raw.githubusercontent.com/huggingface/trl/main/trl/scripts/sft.py" \
--model_name_or_path Qwen/Qwen2.5-3B-Instruct \
--dataset_name open-thoughts/OpenThoughts-114k \
--learning_rate 2.0e-5 \
--num_train_epochs 1 \
--packing \
--per_device_train_batch_size 2 \
--gradient_accumulation_steps 16 \
--eval_strategy no \
--use_peft \
--lora_r 256 \
--lora_alpha 16 \
--lora_target_modules all-linear \
--output_dir Qwen2.5-3B-OpenThoughts-LoRA \
--report_to trackio \
--push_to_hub
Untuk menjalankan skrip secara lokal, Anda perlu menginstal uv. Lihat dokumentasi uv untuk detail lebih lanjut.
Setelah pelatihan dimulai, Anda dapat memantau progresnya di Trackio, yang akan mencatat URL-nya.
Pembelajaran Penguatan (GRPO)
Artikel blog tersebut melakukan GRPO pada berbagai model dan dataset dari Hub, dan sekali lagi kita dapat mereproduksi hasilnya di TRL.
| Model | Dataset |
|---|---|
| Llama-3.1-8B-Base | GSM8k |
| Llama-3.1-8B-Base | DeepMath-103K |
| Qwen3-8b-base | DeepMath-103K |
Untuk pembelajaran penguatan, blog ini menggunakan tugas penalaran matematika yang dapat kami replikasi sebagai fungsi Python.
Kami dapat menerapkan rekomendasi ini dengan API Python TRL seperti berikut:
from datasets import load_dataset
from peft import LoraConfig
from trl import GRPOConfig, GRPOTrainer
from trl.rewards import reasoning_accuracy_reward
dataset = load_dataset("HuggingFaceH4/OpenR1-Math-220k-default-verified", split="train")
peft_config = LoraConfig(
r=1,
lora_alpha=32,
target_modules="all-linear"
)
training_args = GRPOConfig(
learning_rate=5e-5,
per_device_train_batch_size=1,
gradient_accumulation_steps=4,
num_train_epochs=1,
num_generations=8,
generation_batch_size=8,
report_to=["trackio"],
)
trainer = GRPOTrainer(
model="Qwen/Qwen3-0.6B",
reward_funcs=reasoning_accuracy_reward,
args=training_args,
train_dataset=dataset,
peft_config=peft_config,
)
trainer.train()
Snippet ini melewati fungsi reward yang didefinisikan di atas agar contoh tetap ringkas.
hf jobs uv run \
--flavor a100-large \
--timeout 4h \
--secrets HF_TOKEN \
--env PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True \
"https://huggingface.co/datasets/burtenshaw/lora-without-regrets/resolve/main/grpo.py" \
--model_name_or_path Qwen/Qwen3-0.6B \
--dataset_name HuggingFaceH4/OpenR1-Math-220k-default-verified \
--output_dir grpo-full-qwen3-0.6b \
--learning_rate 1.0e-6 \
--lr_scheduler_type cosine \
--warmup_steps 0.0 \
--max_grad_norm 1.0 \
--beta 0.0 \
--max_completion_length 4096 \
--num_generations 16 \
--generation_batch_size 16 \
--gradient_accumulation_steps 8 \
--per_device_train_batch_size 1 \
--num_train_epochs 1 \
--lora_r 1 \
--lora_alpha 32 \
--lora_dropout 0.0 \
--lora_target_modules all-linear \
--vllm_mode colocate \
--save_strategy steps \
--save_steps 50 \
--save_total_limit 1 \
--logging_steps 1 \
--max_steps 200 \
--report_to trackioUntuk menggunakan Hugging Face Jobs, masuk ke Hub (hf auth login) dan pastikan memiliki saldo kredit yang positif. Lihat dokumentasi Jobs untuk detailnya.
uv run "https://huggingface.co/datasets/burtenshaw/lora-without-regrets/resolve/main/grpo.py" \
--model_name_or_path Qwen/Qwen3-0.6B \
--dataset_name HuggingFaceH4/OpenR1-Math-220k-default-verified \
--output_dir grpo-full-qwen3-0.6b \
--learning_rate 1.0e-6 \
--lr_scheduler_type cosine \
--warmup_steps 0.0 \
--max_grad_norm 1.0 \
--beta 0.0 \
--max_completion_length 4096 \
--num_generations 16 \
--generation_batch_size 16 \
--gradient_accumulation_steps 8 \
--per_device_train_batch_size 1 \
--num_train_epochs 1 \
--lora_r 1 \
--lora_alpha 32 \
--lora_dropout 0.0 \
--lora_target_modules all-linear \
--vllm_mode colocate \
--save_strategy steps \
--save_steps 50 \
--save_total_limit 1 \
--logging_steps 1 \
--max_steps 200 \
--report_to trackioUntuk menjalankan skrip secara lokal, Anda perlu menginstal uv. Lihat dokumentasi uv untuk detail lebih lanjut.
Skrip pembelajaran penguatan dengan GRPO diimplementasikan sebagai skrip kustom di TRL, yang menggunakan fungsi reward yang ditunjukkan di atas. Anda dapat meninjaunya di grpo.py - Praktik terbaik pembelajaran penguatan dengan LoRA
Temuan utama dalam mengoptimalkan LoRA
Para penulis merekomendasikan penerapan LoRA ke semua matriks bobot, bukan membatasinya hanya pada lapisan perhatian, karena peningkatan rank tidak mengompensasi pembatasan tersebut. Di TRL, ini dapat dikonfigurasi menggunakan --lora_target_modules all-linear untuk menerapkan LoRA ke semua matriks bobot.
Kami berhasil mereproduksi hasil dari blog post tersebut menggunakan TRL dan model SmolLM3. Kami melatih model selama 500 langkah pada dataset Math 220k dengan fungsi reward dan konfigurasi di atas. Seperti yang dapat Anda lihat pada gambar di bawah, kurva reward rata-rata pelatihan model LoRA cocok dengan kurva fine-tuning penuh.

Dan yang paling penting, model LoRA menggunakan memori yang jauh lebih sedikit daripada model fine-tuning penuh, seperti yang dapat kita lihat pada gambar di bawah.

Berikut adalah parameter yang kami gunakan untuk melatih model-model di atas
| Parameter | LoRA | FT Penuh |
|---|---|---|
--model_name_or_path | HuggingFaceTB/SmolLM3-3B | HuggingFaceTB/SmolLM3-3B |
--dataset_name | HuggingFaceH4/OpenR1-Math-220k-default-verified | HuggingFaceH4/OpenR1-Math-220k-default-verified |
--learning_rate | 1.0e-5 | 1.0e-6 |
--max_completion_length | 4096 | 4096 |
--lora_r | 1 | - |
--lora_alpha | 32 | - |
--lora_dropout | 0.0 | - |
--lora_target_modules | all-linear | - |
Mari kita bedah temuan utama dari artikel blog tersebut dan bagaimana kami berhasil mereplikasinya.
1. LoRA memberikan hasil yang lebih baik ketika diterapkan ke semua matriks bobot
Para penulis merekomendasikan penerapan LoRA pada semua matriks bobot, bukan membatasinya hanya pada lapisan perhatian, karena peningkatan rank tidak mengompensasi pembatasan tersebut.

LoRA yang hanya diterapkan pada attention menghasilkan performa yang lebih rendah bahkan ketika menggunakan rank yang lebih tinggi untuk menyamai jumlah parameter. Di TRL, ini dapat dikonfigurasi menggunakan --lora_target_modules all-linear untuk menerapkan LoRA ke semua matriks bobot. Dalam Python, kita dapat melakukannya seperti ini:
from peft import LoraConfig
peft_config = LoraConfig(target_modules="all-linear") 2. Adapter membutuhkan kapasitas yang cukup untuk belajar dari dataset
Artikel blog tersebut merekomendasikan penggunaan rank LoRA yang cukup untuk belajar dari dataset. Rank menentukan jumlah parameter yang dapat dilatih dalam adapter LoRA. Oleh karena itu, “Untuk dataset yang melampaui kapasitas LoRA, LoRA kinerjanya lebih rendah daripada FullFT”.

Dalam skrip TRL, kita dapat menggunakan --lora_r untuk mengatur rank dan menyesuaikannya berdasarkan tugas serta dataset yang digunakan untuk pelatihan. Artikel blog tersebut merekomendasikan rank berikut berdasarkan tugas dan ukuran dataset:
Tugas pembelajaran penguatan umumnya membutuhkan kapasitas yang lebih rendah, sehingga rank LoRA yang lebih kecil dapat digunakan. Hal ini karena algoritma gradien kebijakan mengekstrak sekitar ~1 bit informasi per episode, sehingga membutuhkan kapasitas parameter yang minimal.
Artikel blog mendefinisikan ukuran dataset ideal untuk LoRA agar setara dengan fine-tuning penuh sebagai “Post-training scale”. Yang dapat kita gunakan untuk menentukan rank yang direkomendasikan untuk LoRA SFT dan RL sebagai:
| Jenis Tugas | Ukuran Dataset | Rank yang Direkomendasikan |
|---|---|---|
| SFT | Skala pelatihan pasca | 256 |
| RL | Ukuran apa pun | 1-32 |
3. “FullFT dan LoRA ber-rank tinggi memiliki kurva pembelajaran yang serupa”
Secara kontra-intuitif, artikel blog tersebut merekomendasikan penggunaan learning rate yang lebih tinggi dibandingkan fine-tuning penuh. Pada tabel di atas, kami menggunakan 1.0e-5 untuk LoRA dan 1.0e-6 untuk fine-tuning penuh. Dalam skrip TRL, kami bisa menggunakan --learning_rate untuk mengatur learning rate. Skala pada LoRA membuat learning rate optimal menjadi kurang lebih tidak bergantung pada rank.

4. “Dalam beberapa skenario, LoRA kurang toleran terhadap ukuran batch yang besar dibandingkan fine-tuning penuh.”
Artikel blog tersebut merekomendasikan penggunaan ukuran batch efektif < 32 karena para penulis menemukan bahwa LoRA kurang toleran terhadap ukuran batch yang besar. Hal ini tidak dapat dimitigasi dengan meningkatkan rank LoRA. Dalam skrip TRL, kita dapat menggunakan --per_device_train_batch_size dan --gradient_accumulation_steps untuk mengatur ukuran batch.

Poin-poin penting
Dengan TRL, Anda dapat mengimplementasikan adapter LoRA secara efisien untuk mencapai kinerja yang setara dengan fine-tuning penuh, dengan menerapkan wawasan inti (menargetkan semua matriks bobot, memilih rank yang tepat, dan mengelola ukuran batch serta learning rate) tanpa biaya komputasi berat dari FullFT.
Sitasi
@article{schulman2025lora,
title = {{LoRA Without Regret}},
author = {John Schulman and Thinking Machines Lab},
year = 2025,
journal = {Thinking Machines Lab: Connectionism},
doi = {10.64434/tml.20250929},
note = {https://thinkingmachines.ai/blog/lora/}
}