TRL documentation
後悔しないLoRA
後悔しないLoRA
Thinking Machines Labのチームによる最近の研究(Schulman et al., 2025)は、適切に設定された場合、LoRAはフルファインチューニングと同等のパフォーマンスを発揮できることを示しており、その際に必要な計算量は約67%に抑えられます。これらの知見は、TRLのユーザーにとって非常に魅力的です。なぜなら、実装が容易であり、より少ない予算でモデルのパフォーマンスを向上させることができるからです。
このガイドでは、TRLでブログ記事の結果を再現するための簡単な手順を説明します。
このガイドに従う前にブログ記事を読むことをお勧めします。または、最適な結果を得るために、両方のリソースを並行して参照してください。
完全なファインチューニングに対するLoRAの利点
まず、フルファインチューニングに対するLoRAの利点を思い出しましょう。
LoRAはベースモデルの上にアダプタ層を追加しますが、このアダプタ層はベースモデル自体よりもはるかに少ないパラメータ数で構成されています。この設計により、GPUメモリ要件が削減され、より効率的なトレーニングが可能になります。ブログに記載されているように、このアプローチは当初、パフォーマンスのトレードオフを伴うと考えられていましたが、慎重な設定を行うことでこのトレードオフを克服し、フルファインチューニングと同等のパフォーマンスを実現できます。
TRLの例
ブログ記事の主要な調査結果に基づいて、TRLスクリプトでLoRAアダプタを実装して学習しましょう。その後、TRLの結果を踏まえて、各調査結果を再検討します。
教師ありファインチューニング(SFT)
このブログ記事では、Hub上のさまざまなモデルとデータセットに対してSFTを実行しており、これはTRLで再現できます。
これらの知見をTRL Python APIに次のように統合できます。
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
Hugging Face Jobs を使用するには、Hub にログイン(hf auth login)し、クレジット残高がプラスになっている必要があります。詳細は Jobs のドキュメントを参照してください。
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
スクリプトをローカルで実行するには、uv のインストールが必要です。詳細については、uv のドキュメントを参照してください。
トレーニングが開始されると、Trackioで進捗を監視できます。URLはログに記録されます。
強化学習(GRPO)
このブログ記事では、Hub上のさまざまなモデルとデータセットに対してGRPOを実行しており、TRLでも結果を再現できます。
| モデル | データセット |
|---|---|
| Llama-3.1-8B-Base | GSM8k |
| Llama-3.1-8B-Base | DeepMath-103K |
| Qwen3-8b-base | DeepMath-103K |
強化学習では、ブログではPython関数として再現可能な数学推論タスクを使用しています。
これらの推奨事項は、TRL Python API を使用して次のように実装できます。
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()
このスニペットは、例を簡潔に保つため、上記で定義された報酬関数を省略しています。
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 trackioHugging Face Jobs を使用するには、Hub にログイン(hf auth login)し、クレジット残高がプラスになっている必要があります。詳細は Jobs のドキュメントを参照してください。
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 trackioスクリプトをローカルで実行するには、uv のインストールが必要です。詳細については、uv のドキュメントを参照してください。
GRPOによる強化学習スクリプトは、TRLのカスタムスクリプトとして実装されており、上記の報酬関数を使用しています。grpo.py - LoRAによる強化学習のベストプラクティスで確認できます。
LoRAの最適化における主な調査結果
著者らは、ランクを上げてもこの制限を補うことはできないため、LoRAをアテンション層に限定するのではなく、すべての重み行列に適用することを推奨しています。TRLでは、--lora_target_modules all-linear を使用して、すべての重み行列にLoRAを適用するように設定できます。
TRLとSmolLM3モデルを使用して、ブログ記事の結果を再現することができました。上記の報酬関数と設定を用いて、Math 220k データセットでモデルを500ステップ訓練しました。下の図に示すように、LoRAモデルの平均訓練報酬の曲線は、フルファインチューニングの曲線と一致しています。

そして最も重要なのは、下の図に示すように、LoRAモデルはフルファインチューニングモデルよりもはるかに少ないメモリで済む点です。

上記のモデルを学習するために使用したパラメータは以下の通りです
| パラメータ | LoRA | フルFT |
|---|---|---|
--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 | - |
ブログ記事の主要な発見と、それらをどのように再現したのかを分解して見ていきましょう。
1. LoRA はすべての重み行列に適用した場合に、より良いパフォーマンスを発揮します
著者らは、ランクを高くしてもこの制限を補うことはできないため、LoRAをアテンション層に限定するのではなく、すべての重み行列に適用することを推奨しています。

Attentionのみを対象にしたLoRAは、パラメータ数を合わせるためにより高いランクを使用しても、性能が劣ることがあります。TRLでは、--lora_target_modules all-linear を使用して、すべての重み行列にLoRAを適用するように設定できます。Pythonでは、次のように実行できます。
from peft import LoraConfig
peft_config = LoraConfig(target_modules="all-linear") 2. アダプターは、データセットから学習するために十分な容量を必要とします
ブログ記事では、データセットから学習するために十分なLoRAランクを使用することを推奨しています。ランクは、LoRAアダプター内の学習可能なパラメータの数を決定します。したがって、「LoRAの容量を超えるデータセットでは、LoRAはFullFTよりも性能が劣ります」。

TRLスクリプトでは、--lora_r を使用してランクを設定し、トレーニング対象のタスクとデータセットに応じて調整できます。ブログ記事では、タスクとデータセットのサイズに基づいて、以下のランクが推奨されています。
強化学習のタスクは通常、より低い容量で済むため、より小さいLoRAランクを使用できます。これは、ポリシーグラデーションアルゴリズムがエピソードあたり約1ビットの情報を抽出するだけで済むため、パラメータ容量の要求が最小限だからです。
ブログ記事では、LoRAのフルファインチューニングと同等の性能を発揮するための理想的なデータセットサイズを「Post-training scale」と定義しています。これを用いて、SFTおよびRLのLoRAの推奨ランクを以下のように決定できます。
| タスクタイプ | データセットサイズ | 推奨ランク |
|---|---|---|
| SFT | ポストトレーニングのスケール | 256 |
| 強化学習 | 任意のサイズ | 1-32 |
3. “FullFTと高ランクLoRAは類似の学習曲線を示す”
直感に反して、このブログ記事ではフルファインチューニングよりも高い学習率の使用を推奨しています。上記の表では、LoRAに1.0e-5、フルファインチューニングに1.0e-6を使用しました。TRLスクリプトでは、 --learning_rate で学習率を設定できます。LoRAにおける のスケーリングにより、最適な学習率はランクにほぼ依存しなくなります。

4. 「一部のシナリオでは、LoRAはフルファインチューニングよりも大きなバッチサイズに対して許容度が低い場合があります。」
ブログ記事では、著者らがLoRAは大きなバッチサイズにあまり耐性がないことを発見したため、実効バッチサイズが32未満になるよう設定することを推奨しています。この問題は、LoRAのランクを大きくしても緩和できませんでした。TRLのスクリプトでは、--per_device_train_batch_sizeと--gradient_accumulation_stepsを使用してバッチサイズを設定できます。

要点
TRLを使用すると、FullFTの重い計算コストを伴うことなく、コアなインサイト(すべての重み行列を対象とすること、適切なランクの選択、バッチサイズと学習率の管理)を適用しながら、フルファインチューニングのパフォーマンスに匹敵するLoRAアダプターを効率的に実装できます。
引用
@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/}
}