Skip to content
Published on

強化学習完全ガイド: DQN・PPOからRLHF・DPOによるLLMアライメントまで

Authors

はじめに

強化学習(Reinforcement Learning, RL)は、エージェントが環境と相互作用しながら報酬を最大化する方策を自律的に学習する機械学習のパラダイムです。AlphaGoの囲碁制覇からChatGPTのRLHFアライメントまで、現代AIのコア技術として確立されています。

この記事では、MDPの数学的基礎から最新のDPOまでを一度に解説します。


1. 強化学習の基礎: MDP

マルコフ決定過程 (Markov Decision Process)

強化学習はMDPとして定式化されます。MDPは5タプル (S,A,P,R,γ)(S, A, P, R, \gamma) で定義されます:

  • SS: 状態空間 (State space)
  • AA: 行動空間 (Action space)
  • P(ss,a)P(s'|s, a): 遷移確率 (Transition probability)
  • R(s,a,s)R(s, a, s'): 報酬関数 (Reward function)
  • γ[0,1)\gamma \in [0, 1): 割引率 (Discount factor)

マルコフ性質: 将来の状態は現在の状態のみで決まります。

P(st+1st,at,st1,at1,)=P(st+1st,at)P(s_{t+1} | s_t, a_t, s_{t-1}, a_{t-1}, \ldots) = P(s_{t+1} | s_t, a_t)

方策 (Policy)

方策 π\pi は状態から行動へのマッピングです:

  • 決定論的方策: a=π(s)a = \pi(s)
  • 確率的方策: aπ(as)a \sim \pi(a|s)

価値関数 (Value Function)

状態価値関数: 方策 π\pi に従うときの状態 ss における期待累積報酬

Vπ(s)=Eπ[t=0γtrts0=s]V^\pi(s) = \mathbb{E}_\pi \left[ \sum_{t=0}^{\infty} \gamma^t r_t \,\Big|\, s_0 = s \right]

行動価値関数 (Q関数): 状態 ss で行動 aa を取った後に方策 π\pi に従うときの期待報酬

Qπ(s,a)=Eπ[t=0γtrts0=s,a0=a]Q^\pi(s, a) = \mathbb{E}_\pi \left[ \sum_{t=0}^{\infty} \gamma^t r_t \,\Big|\, s_0 = s, a_0 = a \right]

ベルマン方程式 (Bellman Equation)

価値関数の再帰的分解:

Vπ(s)=aπ(as)sP(ss,a)[R(s,a,s)+γVπ(s)]V^\pi(s) = \sum_a \pi(a|s) \sum_{s'} P(s'|s,a) \left[ R(s,a,s') + \gamma V^\pi(s') \right]

ベルマン最適方程式:

V(s)=maxasP(ss,a)[R(s,a,s)+γV(s)]V^*(s) = \max_a \sum_{s'} P(s'|s,a) \left[ R(s,a,s') + \gamma V^*(s') \right]

Q(s,a)=sP(ss,a)[R(s,a,s)+γmaxaQ(s,a)]Q^*(s, a) = \sum_{s'} P(s'|s,a) \left[ R(s,a,s') + \gamma \max_{a'} Q^*(s', a') \right]


2. モデルフリー強化学習

Q学習 (オフポリシー)

Q学習はオフポリシー手法です。TD更新則:

Q(st,at)Q(st,at)+α[rt+γmaxaQ(st+1,a)Q(st,at)]Q(s_t, a_t) \leftarrow Q(s_t, a_t) + \alpha \left[ r_t + \gamma \max_{a'} Q(s_{t+1}, a') - Q(s_t, a_t) \right]

ターゲット: rt+γmaxaQ(st+1,a)r_t + \gamma \max_{a'} Q(s_{t+1}, a') (greedy方策を使用)

SARSA (オンポリシー)

SARSAはオンポリシー手法です:

Q(st,at)Q(st,at)+α[rt+γQ(st+1,at+1)Q(st,at)]Q(s_t, a_t) \leftarrow Q(s_t, a_t) + \alpha \left[ r_t + \gamma Q(s_{t+1}, a_{t+1}) - Q(s_t, a_t) \right]

ターゲット: rt+γQ(st+1,at+1)r_t + \gamma Q(s_{t+1}, a_{t+1}) (実際の次の行動 at+1a_{t+1} を使用)

比較項目Q学習SARSA
方策タイプオフポリシーオンポリシー
更新基準greedy行動実際の行動
崖問題最適経路安全な経路

DQN (Deep Q-Network)

DQNはニューラルネットワークでQ関数を近似します。2つの主要安定化技術:

  1. 経験リプレイ (Experience Replay): リプレイバッファからミニバッチをサンプリング
  2. ターゲットネットワーク: 定期的にコピーされる別ネットワークで安定したターゲットを提供
import torch
import torch.nn as nn
import numpy as np
from collections import deque
import random

class DQN(nn.Module):
    def __init__(self, state_dim, action_dim):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(state_dim, 128),
            nn.ReLU(),
            nn.Linear(128, 128),
            nn.ReLU(),
            nn.Linear(128, action_dim)
        )

    def forward(self, x):
        return self.net(x)

class ReplayBuffer:
    def __init__(self, capacity=10000):
        self.buffer = deque(maxlen=capacity)

    def push(self, state, action, reward, next_state, done):
        self.buffer.append((state, action, reward, next_state, done))

    def sample(self, batch_size):
        batch = random.sample(self.buffer, batch_size)
        states, actions, rewards, next_states, dones = zip(*batch)
        return (
            torch.FloatTensor(np.array(states)),
            torch.LongTensor(actions),
            torch.FloatTensor(rewards),
            torch.FloatTensor(np.array(next_states)),
            torch.FloatTensor(dones)
        )

    def __len__(self):
        return len(self.buffer)

def train_dqn_step(online_net, target_net, optimizer, buffer,
                   batch_size=64, gamma=0.99):
    if len(buffer) < batch_size:
        return
    states, actions, rewards, next_states, dones = buffer.sample(batch_size)

    # 現在のQ値
    current_q = online_net(states).gather(1, actions.unsqueeze(1)).squeeze(1)

    # ターゲットQ値 (ターゲットネットワーク使用)
    with torch.no_grad():
        max_next_q = target_net(next_states).max(1)[0]
        target_q = rewards + gamma * max_next_q * (1 - dones)

    loss = nn.MSELoss()(current_q, target_q)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    return loss.item()

Double DQN

DQNの過大評価問題を解決。行動選択と価値評価を分離:

Q(st,at)rt+γQtarget ⁣(st+1,  argmaxaQonline(st+1,a))Q(s_t, a_t) \leftarrow r_t + \gamma Q_{\text{target}}\!\left(s_{t+1},\; \arg\max_{a'} Q_{\text{online}}(s_{t+1}, a')\right)

Dueling DQN

Q値を価値関数 V(s)V(s) とアドバンテージ関数 A(s,a)A(s,a) に分解:

Q(s,a)=V(s)+A(s,a)1AaA(s,a)Q(s, a) = V(s) + A(s, a) - \frac{1}{|A|} \sum_{a'} A(s, a')

class DuelingDQN(nn.Module):
    def __init__(self, state_dim, action_dim):
        super().__init__()
        self.feature = nn.Sequential(
            nn.Linear(state_dim, 128), nn.ReLU()
        )
        self.value_stream = nn.Sequential(
            nn.Linear(128, 64), nn.ReLU(), nn.Linear(64, 1)
        )
        self.advantage_stream = nn.Sequential(
            nn.Linear(128, 64), nn.ReLU(), nn.Linear(64, action_dim)
        )

    def forward(self, x):
        feat = self.feature(x)
        value = self.value_stream(feat)
        advantage = self.advantage_stream(feat)
        return value + advantage - advantage.mean(dim=1, keepdim=True)

3. 方策勾配法 (Policy Gradient)

REINFORCE

方策を直接パラメータ化し、勾配を推定します:

θJ(θ)=Eτπθ[t=0Tθlogπθ(atst)Gt]\nabla_\theta J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta} \left[ \sum_{t=0}^{T} \nabla_\theta \log \pi_\theta(a_t|s_t) \cdot G_t \right]

ここで Gt=k=tTγktrkG_t = \sum_{k=t}^{T} \gamma^{k-t} r_k は時刻 tt からの累積報酬です。

Actor-Critic

REINFORCEの高分散問題を解決するため、ベースラインとして価値関数を使用:

θJ(θ)=E[θlogπθ(atst)A(st,at)]\nabla_\theta J(\theta) = \mathbb{E} \left[ \nabla_\theta \log \pi_\theta(a_t|s_t) \cdot A(s_t, a_t) \right]

アドバンテージ関数: A(st,at)=Q(st,at)V(st)A(s_t, a_t) = Q(s_t, a_t) - V(s_t)

TDエラーで近似: A(st,at)rt+γV(st+1)V(st)A(s_t, a_t) \approx r_t + \gamma V(s_{t+1}) - V(s_t)

A3C / A2C

A3C (Asynchronous Advantage Actor-Critic): 複数ワーカーが非同期で並列学習

A2C (Advantage Actor-Critic): 同期的に全ワーカーの勾配を平均してから更新

PPO (Proximal Policy Optimization)

現在最も広く使われている方策勾配アルゴリズム。コアアイデア: 方策更新幅の制限による安定学習。

クリップされた目的関数:

LCLIP(θ)=Et[min ⁣(rt(θ)At,  clip(rt(θ),1ϵ,1+ϵ)At)]L^{CLIP}(\theta) = \mathbb{E}_t \left[ \min\!\left( r_t(\theta) A_t,\; \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) A_t \right) \right]

ここで rt(θ)=πθ(atst)πθold(atst)r_t(\theta) = \frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{old}}(a_t|s_t)} は確率比です。

PPOの完全な目的関数:

L(θ)=LCLIP(θ)c1LVF(θ)+c2H[πθ]L(\theta) = L^{CLIP}(\theta) - c_1 L^{VF}(\theta) + c_2 H[\pi_\theta]

  • LVFL^{VF}: 価値関数損失 (MSE)
  • H[πθ]H[\pi_\theta]: エントロピーボーナス (探索を促進)
from stable_baselines3 import PPO
import gymnasium as gym

env = gym.make("CartPole-v1")
model = PPO(
    "MlpPolicy",
    env,
    learning_rate=3e-4,
    n_steps=2048,
    batch_size=64,
    n_epochs=10,
    gamma=0.99,
    gae_lambda=0.95,
    clip_range=0.2,       # epsilon: クリップ比率
    ent_coef=0.01,        # エントロピーボーナス係数
    verbose=1
)
model.learn(total_timesteps=100_000)

obs, _ = env.reset()
for _ in range(1000):
    action, _ = model.predict(obs, deterministic=True)
    obs, reward, terminated, truncated, info = env.step(action)
    if terminated or truncated:
        obs, _ = env.reset()

4. 高度な手法

SAC (Soft Actor-Critic)

SACは最大エントロピー強化学習フレームワークです。報酬最大化とエントロピー最大化を同時に追求:

π=argmaxπE[tγt(rt+αH[π(st)])]\pi^* = \arg\max_\pi \mathbb{E} \left[ \sum_t \gamma^t \left( r_t + \alpha \mathcal{H}[\pi(\cdot|s_t)] \right) \right]

α\alpha は探索の程度を制御する温度パラメータです。

ソフトQ関数ベルマン方程式:

Q(st,at)=rt+γEst+1[V(st+1)]Q(s_t, a_t) = r_t + \gamma \mathbb{E}_{s_{t+1}} \left[ V(s_{t+1}) \right]

V(st)=Eaπ[Q(st,a)αlogπ(ast)]V(s_t) = \mathbb{E}_{a \sim \pi} \left[ Q(s_t, a) - \alpha \log \pi(a|s_t) \right]

SACは連続行動空間問題に優れており、自動温度調整でハイパーパラメータ感度が低いです。

from stable_baselines3 import SAC
import gymnasium as gym

env = gym.make("HalfCheetah-v4")
model = SAC(
    "MlpPolicy", env,
    learning_rate=3e-4,
    buffer_size=1_000_000,
    learning_starts=10_000,
    batch_size=256,
    tau=0.005,
    gamma=0.99,
    train_freq=1,
    gradient_steps=1,
    verbose=1
)
model.learn(total_timesteps=1_000_000)

TD3 (Twin Delayed Deep Deterministic)

DDPGの過大評価問題を解決する3つの手法:

  1. Twin Critics: 2つのQ-ネットワークの最小値を選択
  2. Delayed Policy Updates: クリティックより低い頻度でアクターを更新
  3. Target Policy Smoothing: ターゲット行動にノイズを追加

y=r+γmini=1,2Qθi(s,a~),a~=clip(πϕ(s)+ϵ,alow,ahigh)y = r + \gamma \min_{i=1,2} Q_{\theta_i'}(s', \tilde{a}'), \quad \tilde{a}' = \text{clip}(\pi_{\phi'}(s') + \epsilon, a_{low}, a_{high})

HER (Hindsight Experience Replay)

疎な報酬環境で失敗した経験を再利用します。目標を実際に到達した状態に事後的に置き換えて学習:

  • 元の経験: (st,at,rt,st+1,g)(s_t, a_t, r_t, s_{t+1}, g) — 目標 gg に失敗
  • HER変換: (st,at,rt,st+1,g)(s_t, a_t, r'_t, s_{t+1}, g')g=sTg' = s_T (実際の最終状態)

目標置き換え戦略:

  • future: 同一エピソードのランダムな将来状態 (デフォルト)
  • episode: 同一エピソードの任意状態
  • final: エピソードの最後の状態
from stable_baselines3 import HerReplayBuffer, SAC

env = gym.make("FetchReach-v2")
model = SAC(
    "MultiInputPolicy",
    env,
    replay_buffer_class=HerReplayBuffer,
    replay_buffer_kwargs=dict(
        n_sampled_goal=4,
        goal_selection_strategy="future",
    ),
    verbose=1,
)
model.learn(total_timesteps=100_000)

5. RLHF: 強化学習によるLLMアライメント

InstructGPTパイプライン

ChatGPTの核心であるRLHF (Reinforcement Learning from Human Feedback) は3段階で構成されます:

段階1: SFT (Supervised Fine-Tuning)

  • 高品質なデモンストレーションデータでベースモデルをファインチューニング
  • 人間の専門家が理想的な応答を記述

段階2: 報酬モデルの訓練 (Reward Model Training)

  • 人間が2つの応答を比較し、より良い方を選択 (選好データ収集)
  • 選好データで報酬モデルを学習

LRM=E(x,yw,yl)[logσ ⁣(rϕ(x,yw)rϕ(x,yl))]\mathcal{L}_{RM} = -\mathbb{E}_{(x, y_w, y_l)} \left[ \log \sigma\!\left( r_\phi(x, y_w) - r_\phi(x, y_l) \right) \right]

ywy_w は選好された応答、yly_l は選好されない応答です。

段階3: PPOによるLLMファインチューニング

  • 報酬モデルを環境として、LLMをエージェントとしてPPOを適用
  • KLペナルティで元のモデルから大きく離れないように制御

reward(x,y)=rϕ(x,y)βKL ⁣[πθ(yx)πref(yx)]\text{reward}(x, y) = r_\phi(x, y) - \beta \cdot \text{KL}\!\left[\pi_\theta(y|x) \,\|\, \pi_{ref}(y|x)\right]

import torch
import torch.nn as nn

class RewardModel(nn.Module):
    def __init__(self, base_model_name="gpt2"):
        super().__init__()
        from transformers import AutoModel
        self.backbone = AutoModel.from_pretrained(base_model_name)
        hidden_size = self.backbone.config.hidden_size
        self.reward_head = nn.Linear(hidden_size, 1)

    def forward(self, input_ids, attention_mask):
        outputs = self.backbone(input_ids=input_ids, attention_mask=attention_mask)
        last_hidden = outputs.last_hidden_state[:, -1, :]
        return self.reward_head(last_hidden).squeeze(-1)

def compute_reward_model_loss(reward_model, chosen_ids, chosen_mask,
                               rejected_ids, rejected_mask):
    """Bradley-Terryモデルベースの選好損失"""
    chosen_reward = reward_model(chosen_ids, chosen_mask)
    rejected_reward = reward_model(rejected_ids, rejected_mask)
    loss = -torch.log(torch.sigmoid(chosen_reward - rejected_reward)).mean()
    return loss

TRLライブラリでのPPOファインチューニング:

from trl import PPOTrainer, PPOConfig, AutoModelForCausalLMWithValueHead
from transformers import AutoTokenizer

ppo_config = PPOConfig(
    model_name="gpt2",
    learning_rate=1.41e-5,
    batch_size=128,
    mini_batch_size=16,
    gradient_accumulation_steps=4,
    target_kl=0.1,
    kl_penalty="kl",
)

model = AutoModelForCausalLMWithValueHead.from_pretrained(ppo_config.model_name)
tokenizer = AutoTokenizer.from_pretrained(ppo_config.model_name)
ppo_trainer = PPOTrainer(ppo_config, model, ref_model=None, tokenizer=tokenizer)

for batch in dataloader:
    query_tensors = batch["input_ids"]
    response_tensors = ppo_trainer.generate(query_tensors, max_new_tokens=200)
    rewards = [reward_model(q, r) for q, r in zip(query_tensors, response_tensors)]
    stats = ppo_trainer.step(query_tensors, response_tensors, rewards)

DPO (Direct Preference Optimization)

DPOは報酬モデルなしに直接選好データでLLMをアライメントします。PPOの複雑なRLループをシンプルな分類損失に置き換えます:

LDPO(πθ;πref)=E(x,yw,yl)[logσ ⁣(βlogπθ(ywx)πref(ywx)βlogπθ(ylx)πref(ylx))]\mathcal{L}_{DPO}(\pi_\theta; \pi_{ref}) = -\mathbb{E}_{(x, y_w, y_l)} \left[ \log \sigma\!\left( \beta \log \frac{\pi_\theta(y_w|x)}{\pi_{ref}(y_w|x)} - \beta \log \frac{\pi_\theta(y_l|x)}{\pi_{ref}(y_l|x)} \right) \right]

import torch.nn.functional as F

def dpo_loss(pi_logps_chosen, pi_logps_rejected,
             ref_logps_chosen, ref_logps_rejected, beta=0.1):
    """
    DPO損失関数
    Args:
        pi_logps_chosen:    学習モデルの選好応答log-prob
        pi_logps_rejected:  学習モデルの非選好応答log-prob
        ref_logps_chosen:   参照モデルの選好応答log-prob
        ref_logps_rejected: 参照モデルの非選好応答log-prob
        beta: KLペナルティ強度
    """
    pi_log_ratio = pi_logps_chosen - pi_logps_rejected
    ref_log_ratio = ref_logps_chosen - ref_logps_rejected
    # 暗黙的な報酬の差
    logits = beta * (pi_log_ratio - ref_log_ratio)
    loss = -F.logsigmoid(logits).mean()
    return loss

DPO vs RLHF比較:

項目RLHF + PPODPO
報酬モデル別途訓練が必要不要
必要モデル数アクター + クリティック + RM + 参照学習モデル + 参照モデル
学習安定性RL固有の不安定さあり教師あり学習レベルで安定
実装複雑度高い低い

6. マルチエージェント強化学習

環境タイプ

環境タイプ説明
完全協力共有報酬、チーム目標ロボットチーム作業
完全競争ゼロサムゲームチェス、囲碁
混合協力+競争サッカー、MOBA

MADDPG (Multi-Agent DDPG)

分散実行 + 中央集権学習 (CTDE) パラダイム:

  • 実行時: 各エージェントは自身の観測のみで行動を決定
  • 学習時: クリティックは全エージェントの観測と行動を活用

Qiμ(x,a1,,aN)Q_i^\mu(x, a_1, \ldots, a_N)

x=(o1,,oN)x = (o_1, \ldots, o_N) は全体観測、aia_i はエージェント ii の行動です。

class MADDPGCritic(nn.Module):
    """全エージェントの情報を活用する中央集権クリティック"""
    def __init__(self, n_agents, obs_dim, action_dim):
        super().__init__()
        input_dim = n_agents * (obs_dim + action_dim)
        self.net = nn.Sequential(
            nn.Linear(input_dim, 256), nn.ReLU(),
            nn.Linear(256, 256), nn.ReLU(),
            nn.Linear(256, 1)
        )

    def forward(self, all_obs, all_actions):
        x = torch.cat([all_obs, all_actions], dim=-1)
        return self.net(x)

OpenSpiel

Google DeepMindのマルチエージェントRLフレームワーク:

import pyspiel

game = pyspiel.load_game("tic_tac_toe")
state = game.new_initial_state()

while not state.is_terminal():
    legal_actions = state.legal_actions()
    action = legal_actions[0]  # 実際には方策で選択
    state.apply_action(action)

returns = state.returns()
print(f"プレイヤー0の報酬: {returns[0]}")
print(f"プレイヤー1の報酬: {returns[1]}")

7. 実践的な学習環境

Gymnasium (OpenAI Gym後継)

import gymnasium as gym
import numpy as np

class NormalizedObsWrapper(gym.ObservationWrapper):
    """観測値を [-1, 1] に正規化するラッパー"""
    def __init__(self, env):
        super().__init__(env)
        self.obs_low = env.observation_space.low
        self.obs_high = env.observation_space.high

    def observation(self, obs):
        normalized = (
            2.0 * (obs - self.obs_low)
            / (self.obs_high - self.obs_low + 1e-8)
            - 1.0
        )
        return normalized.astype(np.float32)

class RewardShapingWrapper(gym.RewardWrapper):
    """報酬スケーリングラッパー"""
    def __init__(self, env, scale=0.01):
        super().__init__(env)
        self.scale = scale

    def reward(self, reward):
        return reward * self.scale

base_env = gym.make("LunarLander-v2")
env = RewardShapingWrapper(NormalizedObsWrapper(base_env))
obs, info = env.reset(seed=42)

MuJoCo

ロボティクス研究に不可欠な物理ベースの連続制御環境:

  • HalfCheetah-v4: チーターロボット走行 (17次元状態、6次元行動)
  • Humanoid-v4: 人型ロボット歩行 (376次元状態、17次元行動)
  • Ant-v4: 4足歩行ロボット (111次元状態、8次元行動)

100万ステップでのベンチマーク性能:

環境SACTD3PPO
HalfCheetah~12000~9000~3000
Ant~5500~4000~1500
Humanoid~5000~4500~600

Isaac Gym / Isaac Lab

NVIDIAのGPU加速物理シミュレーターで、数千の環境を並列実行:

  • CPU シミュレーションと比べて 2000倍高速な学習
  • ドメインランダム化でsim-to-real転移を向上
  • 4096環境の同時実行でロボット学習を数時間で完了
# Isaac Lab の例(簡略化)
from isaaclab.envs import DirectRLEnvCfg

class CartpoleEnvCfg(DirectRLEnvCfg):
    num_envs = 4096          # 4096個の並列環境
    episode_length_s = 5.0
    decimation = 2
    action_scale = 100.0

# GPU上で4096個のCartPoleを並列実行
# obs.shape: [4096, obs_dim]

実世界RLデプロイの考慮事項

  1. 安全制約 (Safe RL): 学習中の危険な行動を防止 — CPO、TRPO-Lagrangian
  2. サンプル効率: 実世界データは高価かつ低速 — オフラインRL、モデルベースRL
  3. Sim-to-Real転移: ドメインランダム化とアダプテーション (RMA) でリアリティギャップを縮小
  4. オフラインRL: 事前収集データのみで学習 — Conservative Q-Learning (CQL)、IQL

クイズ: 強化学習の理解度チェック

Q1. Q学習とSARSAのオンポリシー vs オフポリシーの違いを説明してください。

答え: Q学習はオフポリシー、SARSAはオンポリシー

解説: Q学習の更新ターゲットは r+γmaxaQ(s,a)r + \gamma \max_{a'} Q(s', a') で、実際の行動とは無関係にgreedy最大値を使います。一方SARSAは r+γQ(s,a)r + \gamma Q(s', a') において aa'実際に取った行動です。CliffWalking問題では、Q学習は崖際の最適経路を学習しますが探索中によく落下し、SARSAはより安全な迂回経路を学習します。

Q2. PPOにおけるクリップ比率ハイパーパラメータepsilonが学習安定性に与える役割は?

答え: epsilonは方策更新の保守性を制御

解説: rt(θ)=πθ/πoldr_t(\theta) = \pi_\theta / \pi_{old}[1ϵ,1+ϵ][1-\epsilon, 1+\epsilon] の範囲を外れると勾配がブロックされます。ϵ\epsilon が小さすぎると学習が遅くなり局所最小値に陥りやすくなります。逆に大きすぎると方策が急激に変化して不安定になります。一般的に ϵ=0.2\epsilon = 0.2 が良いデフォルト値で、学習後半に徐々に減少させるスケジューリングも効果的です。

Q3. RLHFで報酬モデルの訓練データを収集する方法は?

答え: 人間のアノテーターが2つの応答ペアを比較して選好を示す

解説: 同じプロンプトに対する2つの応答 (y1,y2)(y_1, y_2) を人間のアノテーターに見せ、より良い応答を選択させます。絶対評価 (1-5点) よりもペアワイズ比較のほうが一貫性があり信頼性が高いです。収集した選好データ (x,yw,yl)(x, y_w, y_l) でBradley-Terryモデルを学習します。AnthropicのConstitutional AIでは、AIが直接評価者の役割を担うRLAIFも使用されています。

Q4. DPOがPPOベースのRLHFより実装が簡単な理由は?

答え: 報酬モデルと強化学習ループが不要

解説: RLHF+PPOは3段階 (SFT、報酬モデル学習、PPOファインチューニング) が必要で、複数のモデル (アクター、クリティック、報酬モデル、参照モデル) を同時にGPUメモリに載せる必要があります。DPOは選好データから暗黙的な報酬を数式に直接統合し、シンプルなクロスエントロピースタイルの損失1つでファインチューニングします。学習モデルと参照モデルの2つだけが必要で、RL固有の不安定性がありません。

Q5. Soft Actor-Criticにおけるエントロピー正則化の役割は?

答え: 探索の促進 + 複数最適方策の学習

解説: SACの目的関数にエントロピー項 αH[π(s)]\alpha \mathcal{H}[\pi(\cdot|s)] を追加すると、エージェントは報酬を最大化しながら同時に行動のランダム性を維持しようとします。これは自動的な探索メカニズムを提供し、局所最小値からの脱出に役立ちます。また、同等に良い複数の行動がある場合に均等に選択するロバストな方策を学習します。温度パラメータ α\alpha は目標エントロピーに合わせて自動チューニング (automatic entropy tuning) で調整されます。


アルゴリズム比較まとめ

アルゴリズム方策タイプ行動空間主な特徴
Q学習オフポリシー離散シンプル、テーブルベース
DQNオフポリシー離散ニューラルネット + ER + TN
Double DQNオフポリシー離散過大評価の軽減
Dueling DQNオフポリシー離散V + A分解
REINFORCEオンポリシー離散/連続高分散
A2Cオンポリシー離散/連続Actor-Critic
PPOオンポリシー離散/連続安定的、汎用
SACオフポリシー連続最大エントロピー
TD3オフポリシー連続SACの決定論的バージョン
HERオフポリシー目標ベース疎な報酬

まとめ

強化学習はゲームAIを超えて、ロボティクス・LLMアライメント・自動運転・創薬まで応用範囲が爆発的に拡大しています。特にRLHFとDPOはChatGPT・Claude・GeminiといったLLMのコアアライメント技術として、RLを理解することが現代のAI研究者にとって必須のスキルとなっています。

推奨学習ロードマップ:

  1. Gymnasium + Q学習/DQNを自分で実装
  2. Stable-Baselines3でPPO/SACを実験
  3. TRLライブラリでRLHF/DPOを実践
  4. Isaac Labでロボティクスを探求

参考資料:

  • Sutton & Barto, "Reinforcement Learning: An Introduction" (2nd ed.)
  • Spinning Up in Deep RL (OpenAI)
  • Stable-Baselines3 公式ドキュメント
  • TRL (Transformer Reinforcement Learning) by Hugging Face
  • Isaac Lab 公式ドキュメント