28. Llama 3をQLoRAでファインチューニング!完全なトレーニングパイプライン解説
ついに来ました!これまで学んできたすべてを統合して、実際にモデルをファインチューニングする時です。
今回は、QLoRA(4ビット量子化とLoRAアダプターの組み合わせ)を使って、SAMSum対話要約データセットでLlama 3.2 1B-Instructをトレーニングします。
以前のレッスンで構築したすべてを再利用します。データセットのロード、設定管理、評価関数。そこにトレーニングパイプラインを追加します。マスキングロジック、Trainerのセットアップ、モデルチェックポイント作成、すべてです!
最後には、再現可能なトレーニングスクリプト、LoRAアダプターのセット、ベースラインに対する測定可能なパフォーマンス向上が得られます。
注意:このレッスンは、メカニクスを正しく理解することに焦点を当てています。エンドツーエンドで動作するパイプラインの構築です。まだピークパフォーマンスの最適化は行いません。それは次で、実験追跡とハイパーパラメーター検索を追加するときです。
ベースラインからカスタムモデルのトレーニングへ
これまでに、SAMSumをロード・キャッシュし、ベースモデルで推論を実行し、ベースライン評価のROUGEメトリクスを計算しました。
今度はこれらのコンポーネントを再利用し、新しいことに焦点を当てます。モデルのファインチューニングです!
このワークフローは、ノートブックではなくモジュール式のPythonスクリプトで実装されています。スケールし、実行間で再現可能であるように設計されています。プロフェッショナルな開発環境ですね。
このレッスンで行うこと:
- アシスタントのみのマスキングを適用して要約にトレーニングを集中
- QLoRA固有の設定でTrainer APIを設定
- 最初の完全なトレーニングループを実行
- LoRAアダプターを保存して評価
QLoRA Training Pipeline:全体像
トレーニングの背後にあるツール
このワークフローは、以前のレッスンで使用してきた同じスタックに依存しています:
- transformers:モデルとトークナイザーをロードし、Trainer APIを介してトレーニングループを処理
- PEFT:パラメーター効率的なファインチューニングのためのLoRA/QLoRA機能を提供
- bitsandbytes:4ビット量子化と8ビットオプティマイザーを可能にする
- datasets:SAMSumのロード、キャッシング、前処理を処理
- accelerate:デバイス配置と分散トレーニングセットアップを管理
これらのツールはすでに評価に使用していますよね。今回は、それらをトレーニングに使用します!
再利用するコンポーネント
以前のレッスンで構築したこれらのユーティリティが、今まとまります:
config.yaml:すべてのパラメーターを一箇所で管理load_and_prepare_dataset():データセットのロードとサンプリングcompute_rouge():評価メトリクスの計算setup_model_and_tokenizer():モデルとトークナイザーのセットアップ
これらはデータセット、設定、モデルのセットアップを処理します。私たちはトレーニングロジックに純粋に焦点を当てられるんです。
Configuration:トレーニングの青写真
トレーニングコードに入る前に、それを駆動するものを見てみましょう。config.yamlファイルです。
以前のレッスンでデータセットセクションをすでに見ました。今度は設定の残りの部分を使用します。量子化設定、LoRAパラメーター、トレーニングハイパーパラメーター。
重要な設定項目
モデル設定:
base_model: meta-llama/Llama-3.2-1B-Instruct
tokenizer_type: meta-llama/Llama-3.2-1B-Instruct
量子化設定:
quantization:
use_4bit: true
bnb_4bit_compute_dtype: bfloat16
bnb_4bit_quant_type: nf4
bnb_4bit_use_double_quant: true
これは、前回学んだNF4量子化とダブル量子化の設定ですね!
LoRA設定:
lora:
r: 8
lora_alpha: 16
target_modules: ["q_proj", "v_proj"]
lora_dropout: 0.05
これも前回学んだ推奨設定です。ランク8、アルファ16、q_projとv_projをターゲットにします。
トレーニングハイパーパラメーター:
training:
num_train_epochs: 1
per_device_train_batch_size: 4
gradient_accumulation_steps: 4
learning_rate: 0.0002
warmup_steps: 50
logging_steps: 10
save_strategy: "steps"
save_steps: 100
これらのパラメーターがトレーニングの挙動を決定します。
データ前処理:アシスタントのみのマスキング
ファインチューニングで最も重要な部分の1つが、アシスタントのみのマスキングです。
通常、モデルは入力全体から学習しますが、要約タスクでは、対話部分は学習せず、要約部分だけを学習させたいんです。
これを実現するために、対話部分のトークンをマスク(-100に設定)します。こうすると、損失計算時にその部分が無視されます。
前処理の流れ
- プロンプトの作成:対話をユーザープロンプトとして構造化
- トークン化:プロンプトと要約をトークンに変換
- マスキング:ユーザープロンプト部分のラベルを-100に設定
- パディング:バッチ処理のために長さを揃える
def preprocess_function(examples):
# プロンプト作成
prompts = [build_prompt(dialogue) for dialogue in examples['dialogue']]
summaries = examples['summary']
# トークン化
model_inputs = tokenizer(prompts, max_length=max_length, truncation=True)
labels = tokenizer(summaries, max_length=max_length, truncation=True)
# マスキング適用
for i in range(len(model_inputs['input_ids'])):
prompt_len = len(model_inputs['input_ids'][i])
labels['input_ids'][i] = [-100] * prompt_len + labels['input_ids'][i]
model_inputs['labels'] = labels['input_ids']
return model_inputs
これで、モデルは要約部分だけから学習するようになります!
モデルとLoRAアダプターのセットアップ
次に、量子化されたモデルをロードし、LoRAアダプターを追加します。
ステップ1:量子化設定
from transformers import BitsAndBytesConfig
import torch
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
)
ステップ2:モデルのロード
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.2-1B-Instruct",
quantization_config=bnb_config,
device_map="auto",
)
ステップ3:LoRAアダプターの追加
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
# トレーニング用にモデルを準備
model = prepare_model_for_kbit_training(model)
# LoRA設定
lora_config = LoraConfig(
r=8,
lora_alpha=16,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
# アダプターを適用
model = get_peft_model(model, lora_config)
# 訓練可能なパラメーター確認
model.print_trainable_parameters()
# 出力例: trainable params: 4,194,304 || all params: 1,235,814,400 || trainable%: 0.34
わずか0.34%のパラメーターだけを訓練します!効率的ですね。
トレーニングの実行
いよいよトレーニングです!Hugging FaceのTrainer APIを使用します。
TrainingArguments の設定
from transformers import TrainingArguments
training_args = TrainingArguments(
output_dir="./outputs/llama-3.2-1b-samsum",
num_train_epochs=1,
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
learning_rate=2e-4,
warmup_steps=50,
logging_steps=10,
save_strategy="steps",
save_steps=100,
evaluation_strategy="steps",
eval_steps=100,
fp16=False,
bf16=torch.cuda.is_available(),
optim="paged_adamw_8bit",
)
Trainerのセットアップと実行
from transformers import Trainer
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_train,
eval_dataset=tokenized_val,
data_collator=DataCollatorForLanguageModeling(tokenizer, mlm=False),
)
# トレーニング開始!
trainer.train()
トレーニングが始まると、ログが表示されます:
Step 10: loss=2.45, learning_rate=0.0001
Step 20: loss=2.12, learning_rate=0.0002
Step 30: loss=1.89, learning_rate=0.0002
...
損失が下がっていくのを見るのは気持ちいいですよね!
アダプターの保存と評価
トレーニングが完了したら、LoRAアダプターを保存します。
# アダプターを保存
model.save_pretrained("./outputs/llama-3.2-1b-samsum/adapter")
tokenizer.save_pretrained("./outputs/llama-3.2-1b-samsum/adapter")
アダプターは通常10~50MB程度で、とても小さいです。元のモデル全体を保存する必要がないんですね!
評価
前回作成した評価関数を使って、ファインチューニング済みモデルを評価します:
# ベースモデルとアダプターをロード
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.2-1B-Instruct",
quantization_config=bnb_config,
device_map="auto",
)
from peft import PeftModel
model = PeftModel.from_pretrained(model, "./outputs/llama-3.2-1b-samsum/adapter")
# 評価実行
scores = evaluate_model(model, tokenizer, val_data)
print(f"ROUGE-1: {scores['rouge1']:.2%}")
print(f"ROUGE-2: {scores['rouge2']:.2%}")
print(f"ROUGE-L: {scores['rougeL']:.2%}")
期待される結果
ファインチューニング後、ROUGEスコアは通常以下のように改善します:
| メトリック | ベースライン | ファインチューニング後 | 改善 |
|---|---|---|---|
| ROUGE-1 | 約30-35% | 約40-45% | +10%程度 |
| ROUGE-2 | 約15-20% | 約25-30% | +10%程度 |
| ROUGE-L | 約25-30% | 約35-40% | +10%程度 |
数字で改善が見えるって、本当に嬉しいですよね!
まとめ
今回は、完全なQLoRAトレーニングパイプラインを構築しました!
重要なポイントを振り返りましょう:
1. 設定管理
– config.yamlですべてのパラメーターを一元管理
– 再現可能で、実験間で変更が追跡しやすい
2. データ前処理
– アシスタントのみのマスキングで効率的な学習
– 対話部分は学習せず、要約部分だけを学習
3. QLoRAセットアップ
– 4ビット量子化でメモリ効率的
– LoRAアダプターでパラメーター効率的
– わずか0.34%のパラメーターだけを訓練
4. トレーニング実行
– Hugging Face Trainer APIで簡単にトレーニング
– ログで進捗を監視
– チェックポイントを定期的に保存
5. 評価と保存
– 小さなアダプターファイル(10~50MB)を保存
– ROUGEスコアで測定可能な改善を確認
これで、あなたは完全なファインチューニングパイプラインを持っています。このパイプラインは、任意のモデルやタスクに再利用できます!
次回は、このパイプラインをクラウドGPUにスケールして、より速くトレーニングする方法を学びます。楽しみにしていてくださいね!

コメント