RLHF とアラインメント ── 「役に立つ AI」への調整
LLM との関係:事前学習だけの LLM は「次の単語を予測する」だけ。人間の指示に従い、有用で安全な応答をするように調整するのが RLHF。ChatGPT の「対話が自然に感じる」理由がここにある。

この章で何ができるようになるか:事前学習済みモデルがなぜそのままでは「使いにくい」のかを説明でき、RLHF の3ステップ(SFT → Reward Model → PPO)を理解できる。
なぜ事前学習だけでは不十分か
プロンプト: 「フランスの首都は?」
事前学習のみの GPT の出力(ありがちな例):
「フランスの首都は? イタリアの首都は? ドイツの首都は?」
→ 次の単語として「質問を続ける」のが確率的に自然だと学習した
または:
「フランスの首都はパリです。パリはセーヌ川のほとりにあり、
エッフェル塔は1889年に...(延々と続く)」
→ 「止め方」を知らない
RLHF 後の出力:
「パリです。」
→ 簡潔に質問に答え、適切なところで止まる
事前学習モデルは「テキストの続き」を生成するが、「ユーザーの質問に答える」ことは直接学習していない。
RLHF の3ステップ
Step 1: SFT (Supervised Fine-Tuning)
→ 人間が書いた「良い応答」の例で教師ありファインチューニング
Step 2: Reward Model の訓練
→ 「どちらの応答が良いか」の人間の判断を学習するモデルを作る
Step 3: PPO (Proximal Policy Optimization)
→ Reward Model のフィードバックで LLM を強化学習的に最適化
Step 1: SFT(Supervised Fine-Tuning)
# SFT 用の訓練データの形式
sft_data = [
{
"prompt": "フランスの首都は?",
"response": "フランスの首都はパリです。"
},
{
"prompt": "PythonでフィボナッチのXX番目を求める関数を書いて",
"response": "```python\ndef fibonacci(n):\n if n <= 1:\n return n\n return fibonacci(n-1) + fibonacci(n-2)\n```"
},
# ... 数万〜数十万件
]
# 訓練は通常の CLM と同じ(プロンプト部分の損失は無視)
def compute_sft_loss(model, prompt_ids, response_ids):
full_ids = torch.cat([prompt_ids, response_ids], dim=1)
logits = model(full_ids)
# プロンプト部分のラベルは -100(損失計算で無視)
labels = full_ids.clone()
labels[:, :prompt_ids.size(1)] = -100
return nn.CrossEntropyLoss(ignore_index=-100)(
logits[:, :-1].reshape(-1, logits.size(-1)),
labels[:, 1:].reshape(-1)
)
Step 2: Reward Model の訓練
人間が2つの応答を比較し、「どちらが良いか」を判定する。
# 比較データの形式
comparison_data = [
{
"prompt": "量子コンピュータとは?",
"chosen": "量子コンピュータは量子力学の原理を利用した...", # 人間が選んだ良い応答
"rejected": "量子コンピュータは超すごいコンピュータで...", # 人間が選ばなかった応答
},
]
class RewardModel(nn.Module):
def __init__(self, base_model):
super().__init__()
self.base = base_model # 事前学習済み LLM
self.reward_head = nn.Linear(base_model.config.hidden_size, 1)
def forward(self, input_ids):
hidden = self.base(input_ids).last_hidden_state
# 最後のトークンの隠れ状態からスカラー報酬を出力
reward = self.reward_head(hidden[:, -1, :])
return reward.squeeze(-1)
def reward_model_loss(model, chosen_ids, rejected_ids):
"""
Bradley-Terry モデル: chosen のスコアが rejected より高くなるように訓練
"""
r_chosen = model(chosen_ids)
r_rejected = model(rejected_ids)
# r_chosen > r_rejected となる確率を最大化
return -torch.log(torch.sigmoid(r_chosen - r_rejected)).mean()
Step 3: PPO(Proximal Policy Optimization)
Reward Model のスコアを使って LLM を最適化する。
def rlhf_training_step(policy_model, ref_model, reward_model,
prompt_ids, optimizer):
"""PPO の1ステップ(簡略化)"""
# 1. 現在のポリシー(LLM)で応答を生成
with torch.no_grad():
response_ids = policy_model.generate(prompt_ids, max_length=256)
# 2. Reward Model でスコアを取得
full_ids = torch.cat([prompt_ids, response_ids], dim=1)
reward = reward_model(full_ids)
# 3. KL ペナルティ(元のモデルから離れすぎないように)
with torch.no_grad():
ref_logprobs = compute_logprobs(ref_model, full_ids)
policy_logprobs = compute_logprobs(policy_model, full_ids)
kl_penalty = (policy_logprobs - ref_logprobs).sum(dim=1)
# 4. 報酬 = Reward Model のスコア - β × KL ペナルティ
beta = 0.1 # KL ペナルティの強さ
total_reward = reward - beta * kl_penalty
# 5. PPO の目的関数で更新
loss = -total_reward.mean()
optimizer.zero_grad()
loss.backward()
optimizer.step()
KL ペナルティがなぜ必要か:Reward Model を「ハック」してしまうのを防ぐ。KL ペナルティなしだと、モデルは Reward Model のスコアだけを最大化しようとし、意味不明だが高スコアな出力を生成する(Reward Hacking)。
DPO(Direct Preference Optimization)
RLHF の Step 2, 3 を1つに統合した効率的な手法(2023年、Stanford)。
def dpo_loss(policy_model, ref_model, chosen_ids, rejected_ids, beta=0.1):
"""
Reward Model を明示的に訓練せず、
人間の選好データから直接 LLM を最適化する
"""
# 各応答の対数確率を計算
pi_chosen = compute_logprobs(policy_model, chosen_ids).sum(dim=1)
pi_rejected = compute_logprobs(policy_model, rejected_ids).sum(dim=1)
with torch.no_grad():
ref_chosen = compute_logprobs(ref_model, chosen_ids).sum(dim=1)
ref_rejected = compute_logprobs(ref_model, rejected_ids).sum(dim=1)
# 暗黙的な報酬の差
logits = beta * ((pi_chosen - ref_chosen) - (pi_rejected - ref_rejected))
return -torch.nn.functional.logsigmoid(logits).mean()
DPO の利点:Reward Model の訓練が不要。PPO の複雑さ(クリッピング・GAE・バリューネットワーク)が不要。実装がシンプルで安定。
Constitutional AI(CAI)
Anthropic(Claude の開発元)が提唱。人間のフィードバックをAIのフィードバックで一部代替する。
CAI のプロセス:
1. LLM に「この応答は有害か?」と自己評価させる
2. 「有害でない版に書き直して」と自己修正させる
3. 元の応答 vs 修正版 の比較データを生成
4. このデータで RLHF を実行
利点:
- 人間のアノテーターの負担を軽減
- 一貫した評価基準(人間の評価者によるばらつきを減らせる)
- スケーラブル(AI が AI を評価する)
まとめ
| 手法 | 何をするか | コスト |
|---|---|---|
| SFT | 良い応答例で教師あり学習 | 中(データ作成が主) |
| RLHF (PPO) | Reward Model + 強化学習 | 高(3段階の訓練) |
| DPO | 選好データから直接最適化 | 中(RM不要) |
| CAI | AI による自己評価・自己修正 | 低(人間の評価を削減) |
次章では、訓練後のモデルを実際にユーザーにサーブするための推論の高速化──KV Cache、量子化、投機的デコーディングを見ていく。