TRL documentation

PEFTの統合

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

and get access to the augmented documentation experience

to get started

PEFTの統合

TRLは、メモリ効率の良いモデル学習のためのPEFT(Parameter-Efficient Fine-Tuning)手法をサポートしています。PEFTは、ベースモデルを凍結したまま、追加のパラメータをわずかに学習するだけで大規模言語モデルのファインチューニングを可能にし、計算コストとメモリ要件を大幅に削減します。

このガイドでは、LoRA、QLoRA、プロンプトチューニングなどの手法を含む、PEFTをさまざまなTRLトレーナーと組み合わせて使用する方法について説明します。

完全な動作する例については、SFT with LoRA/QLoRA notebookを参照してください。

インストール

TRLでPEFTを使用するには、必要な依存関係をインストールします:

pip install trl[peft]

QLoRAのサポート(4ビットおよび8ビットの量子化)のために、以下もインストールしてください:

pip install bitsandbytes

クイックスタート

すべてのTRLトレーナーは、peft_config引数を通じてPEFTをサポートしています。PEFTを有効にする最も簡単な方法は、--use_peftフラグを指定してコマンドラインインターフェースを使用することです。

python trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --output_dir Qwen2-0.5B-SFT-LoRA

代わりに、Python コード内で PEFT 設定を直接渡すこともできます:

from peft import LoraConfig
from trl import SFTTrainer

# Configure LoRA
peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

# Configure training - note the higher learning rate for LoRA (10x base rate)
training_args = SFTConfig(
    learning_rate=2.0e-4,  # 10x the base rate (2.0e-5) for LoRA
    ...
)

# Create trainer with PEFT
trainer = SFTTrainer(
    model=model,
    train_dataset=dataset,
    peft_config=peft_config,
)

PEFTを設定する3つの方法

TRLでは、PEFTを設定するための3つの異なる方法が提供されており、それぞれが異なるユースケースに適しています。

1. CLIフラグの使用(最も簡単)

PEFTを有効にする最も簡単な方法は、コマンドラインインターフェースで--use_peftフラグを使用することです。この方法は、クイックな実験や標準的な設定に最適です:

python trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --lora_dropout 0.05 \
    --output_dir Qwen2-0.5B-SFT-LoRA

利点:セットアップが迅速で、コード不要

デメリット:LoRAに限定され、カスタマイズの選択肢が少ない

2. Trainer に peft_config を渡す(推奨)

より詳細な制御を行うには、PEFT設定をトレーナーに直接渡します。ほとんどのユースケースにおいて、これが推奨されるアプローチです:

from peft import LoraConfig
from trl import SFTConfig, SFTTrainer

peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
)

trainer = SFTTrainer(
    model=model,
    args=training_args,
    train_dataset=dataset,
    peft_config=peft_config,  # Pass config here
)

利点:完全な制御が可能、すべてのPEFT手法(LoRA、Prompt Tuningなど)に対応

デメリット: Pythonコードが必要です

3. モデルに直接 PEFT を適用する(上級)

最大限の柔軟性を確保するために、モデルをトレーナーに渡す前にPEFTを適用できます。

from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM
from trl import SFTConfig, SFTTrainer

# Load base model
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-0.5B")

# Apply PEFT configuration
peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)
model = get_peft_model(model, peft_config)

# Pass PEFT-wrapped model to trainer
trainer = SFTTrainer(
    model=model,  # Already has PEFT applied
    args=training_args,
    train_dataset=dataset,
    # Note: no peft_config needed here
)

利点:最大限の制御が可能。カスタムモデルアーキテクチャや複雑なセットアップに有用

デメリット: 記述が冗長になり、PEFTの内部構造を理解する必要がある

学習率に関する考慮事項

LoRAやその他のPEFT手法を使用する場合、フルファインチューニングと比較して、通常、より高い学習率(約10倍)が必要です。これは、PEFT手法ではパラメータのほんの一部のみを学習するため、同様のパラメータ更新を実現するにはより大きな学習率が必要になるためです。

推奨される学習率:

Trainer完全ファインチューニングLoRA (10倍)を使用
SFT2.0e-52.0e-4
DPO5.0e-75.0e-6
GRPO1.0e-61.0e-5
Prompt TuningN/A1.0e-2から3.0e-2

なぜ10倍なのか? LoRAアダプターは、モデル全体と比較して学習可能なパラメータ数が大幅に少ないです。より高い学習率はこのパラメータ数の減少を補い、効果的な学習を確保します。詳細な説明については、このブログ記事を参照してください。

LoRAを効果的に利用するための追加のベストプラクティスについては、LoRA Without Regretのドキュメントを参照してください。

異なるTrainerでのPEFT

TRLのトレーナーは、さまざまな学習パラダイムにおけるPEFT設定をサポートしています。以下に、各主要トレーナーの詳細な例を示します。

sft
dpo
grpo

教師ありファインチューニング(SFT)

SFTTrainerは、指示データセットでの教師ありファインチューニングに使用されます。

LoRAを使用

python trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --learning_rate 2.0e-4 \
    --num_train_epochs 1 \
    --per_device_train_batch_size 2 \
    --gradient_accumulation_steps 8 \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --output_dir Qwen2-0.5B-SFT-LoRA

Pythonの例

from peft import LoraConfig
from trl import SFTConfig, SFTTrainer

# Configure LoRA
peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
    target_modules=["q_proj", "v_proj"],  # optional: specify target modules
)

# Configure training with higher learning rate for LoRA
training_args = SFTConfig(
    learning_rate=2.0e-4,  # 10x the base rate for LoRA
    ...
)

# Create trainer with PEFT config
trainer = SFTTrainer(
    model="Qwen/Qwen2-0.5B",  # can pass model name or loaded model
    args=training_args,
    train_dataset=dataset,
    peft_config=peft_config,  # pass PEFT config here
)
trainer.train()

QLoRA: 量子化低ランク適応

QLoRAは、4ビット量子化とLoRAを組み合わせることで、非常に大規模なモデルをコンシューマー向けハードウェア上でファインチューニングすることを可能にします。この手法により、標準的なLoRAと比較して、メモリ要件を最大で4分の1まで削減できます。

QLORAの仕組み

  1. 4ビット量子化: ベースモデルはbitsandbytesを使用して4ビット精度で読み込まれます
  2. フローズンウェイト: 量子化されたモデルの重みは、学習中にフローズン(固定)されたままです
  3. LoRA アダプター: LoRA アダプターのパラメータのみが高精度で学習されます
  4. メモリ効率: Llama-70Bなどのモデルを、1つのコンシューマー向けGPUでファインチューニングできるようにします

TRLでのQLoRAの使用

load_in_4bit=TrueをPEFTの設定と組み合わせるだけです:

コマンドライン

python trl/scripts/sft.py \
    --model_name_or_path meta-llama/Llama-2-7b-hf \
    --dataset_name trl-lib/Capybara \
    --load_in_4bit \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --per_device_train_batch_size 1 \
    --gradient_accumulation_steps 16 \
    --output_dir Llama-2-7b-QLoRA

Pythonの例

quantization_configをpeft_configと並べて直接trainerに渡します。trainerがモデルの読み込みと量子化を代行します。同じquantization_config引数は、SFTTrainer、DPOTrainer、GRPOTrainer、RLOOTrainerでも利用できます。

import torch

from peft import LoraConfig
from transformers import BitsAndBytesConfig
from trl import SFTConfig, SFTTrainer

# Configure 4-bit quantization
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,
)

# Configure LoRA
peft_config = LoraConfig(
    r=32,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

# Configure training with higher learning rate for LoRA
training_args = SFTConfig(
    learning_rate=2.0e-4,  # 10x the base rate for QLoRA
    ...
)

# Create trainer with quantization and PEFT config
trainer = SFTTrainer(
    model="meta-llama/Llama-2-7b-hf",
    args=training_args,
    train_dataset=dataset,
    quantization_config=bnb_config,
    peft_config=peft_config,
)

trainer.train()

QLoRAの設定オプション

BitsAndBytesConfig は、メモリとパフォーマンスを最適化するための複数のオプションを提供します:

import torch

from transformers import BitsAndBytesConfig

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",  # or "fp4"
    bnb_4bit_compute_dtype=torch.bfloat16,  # Compute dtype for 4-bit base models
    bnb_4bit_use_double_quant=True,  # Nested quantization for additional memory savings
)

設定パラメータ:

  • bnb_4bit_quant_type: 量子化データ型("nf4"または"fp4")。NF4が推奨されます。
  • bnb_4bit_compute_dtype: 計算に使用される dtype。トレーニングの安定性を高めるには bfloat16 を使用してください。
  • bnb_4bit_use_double_quant: 追加の約0.4ビット/パラメータの削減のために、ネスト量子化を有効にします。

8ビット量子化

メモリ削減の効果を少し下げつつ、より高い精度を得たい場合は、8ビット量子化を使用できます。

from transformers import BitsAndBytesConfig, AutoModelForCausalLM

bnb_config = BitsAndBytesConfig(load_in_8bit=True)

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    quantization_config=bnb_config,
    device_map="auto",
)

またはコマンドライン経由で:

python trl/scripts/sft.py \
    --model_name_or_path meta-llama/Llama-2-7b-hf \
    --load_in_8bit \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16

事前量子化済みチェックポイント

一部のチェックポイントは量子化された形式で公開されています。例えば、gpt-ossはMXFP4、Mistral Medium 3.5はFP8です。これらの重みはインプレースでの学習ができないため、このようなチェックポイントを名前で渡すと、トレーナーはpeft_configの有無にかかわらず、デクォアンタイズされた状態で読み込みます。その結果、モデルはデクォアンタイズされた重みのメモリを占有します。例えば、gpt-oss-20bの場合、bfloat16では約42 GB、一方そのMXFP4チェックポイントは13 GBです。bfloat16で読み込むには、他のモデルと同様に:

from trl import SFTConfig

training_args = SFTConfig(model_init_kwargs={"dtype": "bfloat16"})

FP8のチェックポイントには、transformers 5.0.0以降が必要です。

プロンプトチューニング

Prompt tuningは、モデル全体を凍結したまま、入力に前置するソフトプロンプト(連続埋め込み)を学習する別のPEFT手法です。これは大規模モデルに対して特に効果的です。

プロンプトチューニングの仕組み

  1. Virtual Tokens: 入力に学習可能な連続埋め込み(仮想トークン)を追加します
  2. Frozen Model: ベースモデル全体がフリーズされたままです
  3. タスク固有のプロンプト: 各タスクはそれぞれ固有のプロンプト埋め込みを学習します
  4. 極限の効率性: プロンプト埋め込みのみが学習されます(通常は8〜20トークン)

TRLでのPrompt Tuningの使用

from peft import PromptTuningConfig, PromptTuningInit, TaskType
from trl import SFTConfig, SFTTrainer

# Configure Prompt Tuning
peft_config = PromptTuningConfig(
    task_type=TaskType.CAUSAL_LM,
    prompt_tuning_init=PromptTuningInit.TEXT,
    num_virtual_tokens=8,
    prompt_tuning_init_text="Classify if the tweet is a complaint or not:",
    tokenizer_name_or_path="Qwen/Qwen2-0.5B",
)

# Configure training with higher learning rate for Prompt Tuning
training_args = SFTConfig(
    learning_rate=2.0e-2,  # Prompt Tuning typically uses 1e-2 to 3e-2
    ...
)

# Create trainer with PEFT config
trainer = SFTTrainer(
    model=model,
    args=training_args,
    train_dataset=dataset,
    peft_config=peft_config,  # pass PEFT config here
)

trainer.train()

Prompt Tuningの設定

from peft import PromptTuningConfig, PromptTuningInit, TaskType

peft_config = PromptTuningConfig(
    task_type=TaskType.CAUSAL_LM,  # Task type
    prompt_tuning_init=PromptTuningInit.TEXT,  # Initialize from text
    num_virtual_tokens=8,  # Number of virtual tokens
    prompt_tuning_init_text="Your initialization text here",
    tokenizer_name_or_path="model_name",
)

設定パラメータ:

  • task_type: タスクの種類(言語モデリングの場合はTaskType.CAUSAL_LM)
  • prompt_tuning_init: 初期化メソッド(TEXT、RANDOM)
  • num_virtual_tokens: 先頭に追加する仮想トークンの数(通常は8〜20)
  • prompt_tuning_init_text: 仮想トークンを初期化するためのテキスト(TEXT 初期化を使用する場合)
  • tokenizer_name_or_path: テキストから初期化するためのTokenizer

Prompt TuningとLoRA

機能プロンプトチューニングLoRA
学習されたパラメータ~0.001%~0.1-1%
メモリ使用量最小限低
学習速度最速高速
モデルの修正Noneアダプター層
最適な用途大規模モデル、多数のタスク一般的なファインチューニング
学習率高い(1e-2から3e-2)標準(1e-4から3e-4)

高度なPEFT設定

LoRA設定パラメータ

from peft import LoraConfig

peft_config = LoraConfig(
    r=16,  # LoRA rank
    lora_alpha=32,  # LoRA scaling factor
    lora_dropout=0.05,  # Dropout probability
    bias="none",  # Bias training strategy
    task_type="CAUSAL_LM",  # Task type
    target_modules=["q_proj", "v_proj"],  # Modules to apply LoRA
    modules_to_save=None,  # Additional modules to train
)

主要なパラメータ:

  • r: LoRAのランク(一般的な値: 8, 16, 32, 64)。ランクが高いほどパラメータ数は増加しますが、パフォーマンスが向上する可能性があります。
  • lora_alpha: スケーリング係数(通常はランクの2倍)。LoRA更新の大きさを制御します。
  • lora_dropout: LoRA層のDropout確率(典型的な値: 0.05-0.1)。
  • target_modules: LoRA を適用するモジュールです。一般的な選択肢:
    • ["q_proj", "v_proj"]: Attention のクエリとバリュー(メモリ効率重視)
    • ["q_proj", "k_proj", "v_proj", "o_proj"]: すべてのアテンションの射影
    • ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]: すべての線形層
  • modules_to_save: 完全に学習する追加のモジュール(例: ["embed_tokens", "lm_head"])

ターゲットモジュールの選択

LoRAを適用するモジュールを指定できます。一般的なパターン:

# Minimal (most memory efficient)
target_modules=["q_proj", "v_proj"]

# Attention only
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"]

# All linear layers (best performance, more memory)
target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]

コマンドライン引数の使用

TRLのスクリプトは、コマンドライン経由でPEFTのパラメータを受け入れます:

python trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16 \
    --lora_dropout 0.05 \
    --lora_target_modules q_proj v_proj \
    --output_dir output

利用可能なフラグ:

  • --use_peft: PEFTを有効にする
  • --lora_r: LoRA のランク(デフォルト: 16)
  • --lora_alpha: LoRA alpha (デフォルト: 32)
  • --lora_dropout: LoRA dropout(デフォルト: 0.05)
  • --lora_target_modules: 対象モジュール(スペース区切り)
  • --lora_modules_to_save: 追加で学習するモジュール
  • --use_rslora: Rank-Stabilized LoRA を有効にします
  • --use_dora: Weight-Decomposed LoRA (DoRA) を有効にします
  • --load_in_4bit: 4ビット量子化(QLoRA)を有効にします
  • --load_in_8bit: 8ビット量子化を有効にします

PEFTモデルの保存と読み込み

保存

学習後、PEFTアダプターを保存します:

# Save the adapters
trainer.save_model("path/to/adapters")

# Or manually
model.save_pretrained("path/to/adapters")

これにより、完全なモデル(数GB)ではなく、アダプター重み(数MB)のみが保存されます。

読み込み中

推論用にPEFTモデルを読み込む:

from transformers import AutoModelForCausalLM
from peft import PeftModel

# Load base model
base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-0.5B")

# Load PEFT adapters
model = PeftModel.from_pretrained(base_model, "path/to/adapters")

# Optionally merge adapters into base model for faster inference
model = model.merge_and_unload()

Hubへのプッシュ

Hugging Face HubでPEFTアダプターを簡単に共有できます:

# Push adapters to Hub
model.push_to_hub("username/model-name-lora")

# Load from Hub
from peft import PeftModel
model = PeftModel.from_pretrained(base_model, "username/model-name-lora")

マルチGPUトレーニング

PEFTはaccelerateを介してTRLのマルチGPUサポートとシームレスに連携します:

# Configure accelerate
accelerate config

# Launch training
accelerate launch trl/scripts/sft.py \
    --model_name_or_path Qwen/Qwen2-0.5B \
    --dataset_name trl-lib/Capybara \
    --use_peft \
    --lora_r 32 \
    --lora_alpha 16

複数GPUでのQLoRAでは、ベースモデルは自動的にシャードされます:

accelerate launch trl/scripts/sft.py \
    --model_name_or_path meta-llama/Llama-2-70b-hf \
    --load_in_4bit \
    --use_peft \
    --lora_r 32

大規模モデル向けのNaive Pipeline Parallelism (NPP)

非常に大規模なモデル(>60Bパラメータ)の場合、TRLはNaive Pipeline Parallelism (NPP)をサポートしています。NPPはモデルとアダプタを複数のGPUに分散配置します。アクティベーションと勾配はGPU間で通信され、int8およびその他のデータ型をサポートしています。

NPP

NPPの使用方法

カスタムのdevice_mapを指定してモデルを読み込み、複数のデバイスに分割します:

from transformers import AutoModelForCausalLM
from peft import LoraConfig

# Create custom device map (see accelerate documentation)
device_map = {
    "model.embed_tokens": 0,
    "model.layers.0": 0,
    # ... distribute layers across GPUs
    "lm_head": 0,  # Must be on GPU 0
}

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-70b-hf",
    device_map=device_map,
    peft_config=lora_config,
)
  • エラーを回避するために、lm_headモジュールを最初のGPU(デバイス0)に保持してください
  • 適切な設定については、デバイスマップに関するチュートリアルを参照してください
  • トレーニングスクリプトを直接実行する(accelerate launch を使用しない): python script.py
  • Data Parallelism は NPP ではまだサポートされていません

リソース

TRLの例とノートブック

ドキュメント

研究論文

  • LoRA論文 - 元のLoRA手法と結果
  • QLoRA論文 - 4ビット量子化による効率的なファインチューニング
  • Prompt Tuning の論文 - パラメータ効率の良いプロンプトチューニングにおけるスケールの力
Update on GitHub