- Authors

- Name
- Youngju Kim
- @fjvbn20031
- はじめに
- 1. 強化学習の基礎: MDP
- 2. モデルフリー強化学習
- 3. 方策勾配法 (Policy Gradient)
- 4. 高度な手法
- 5. RLHF: 強化学習によるLLMアライメント
- 6. マルチエージェント強化学習
- 7. 実践的な学習環境
- クイズ: 強化学習の理解度チェック
- アルゴリズム比較まとめ
- まとめ
はじめに
強化学習(Reinforcement Learning, RL)は、エージェントが環境と相互作用しながら報酬を最大化する方策を自律的に学習する機械学習のパラダイムです。AlphaGoの囲碁制覇からChatGPTのRLHFアライメントまで、現代AIのコア技術として確立されています。
この記事では、MDPの数学的基礎から最新のDPOまでを一度に解説します。
1. 強化学習の基礎: MDP
マルコフ決定過程 (Markov Decision Process)
強化学習はMDPとして定式化されます。MDPは5タプル で定義されます:
- : 状態空間 (State space)
- : 行動空間 (Action space)
- : 遷移確率 (Transition probability)
- : 報酬関数 (Reward function)
- : 割引率 (Discount factor)
マルコフ性質: 将来の状態は現在の状態のみで決まります。
方策 (Policy)
方策 は状態から行動へのマッピングです:
- 決定論的方策:
- 確率的方策:
価値関数 (Value Function)
状態価値関数: 方策 に従うときの状態 における期待累積報酬
行動価値関数 (Q関数): 状態 で行動 を取った後に方策 に従うときの期待報酬
ベルマン方程式 (Bellman Equation)
価値関数の再帰的分解:
ベルマン最適方程式:
2. モデルフリー強化学習
Q学習 (オフポリシー)
Q学習はオフポリシー手法です。TD更新則:
ターゲット: (greedy方策を使用)
SARSA (オンポリシー)
SARSAはオンポリシー手法です:
ターゲット: (実際の次の行動 を使用)
| 比較項目 | Q学習 | SARSA |
|---|---|---|
| 方策タイプ | オフポリシー | オンポリシー |
| 更新基準 | greedy行動 | 実際の行動 |
| 崖問題 | 最適経路 | 安全な経路 |
DQN (Deep Q-Network)
DQNはニューラルネットワークでQ関数を近似します。2つの主要安定化技術:
- 経験リプレイ (Experience Replay): リプレイバッファからミニバッチをサンプリング
- ターゲットネットワーク: 定期的にコピーされる別ネットワークで安定したターゲットを提供
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の過大評価問題を解決。行動選択と価値評価を分離:
Dueling DQN
Q値を価値関数 とアドバンテージ関数 に分解:
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
方策を直接パラメータ化し、勾配を推定します:
ここで は時刻 からの累積報酬です。
Actor-Critic
REINFORCEの高分散問題を解決するため、ベースラインとして価値関数を使用:
アドバンテージ関数:
TDエラーで近似:
A3C / A2C
A3C (Asynchronous Advantage Actor-Critic): 複数ワーカーが非同期で並列学習
A2C (Advantage Actor-Critic): 同期的に全ワーカーの勾配を平均してから更新
PPO (Proximal Policy Optimization)
現在最も広く使われている方策勾配アルゴリズム。コアアイデア: 方策更新幅の制限による安定学習。
クリップされた目的関数:
ここで は確率比です。
PPOの完全な目的関数:
- : 価値関数損失 (MSE)
- : エントロピーボーナス (探索を促進)
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は最大エントロピー強化学習フレームワークです。報酬最大化とエントロピー最大化を同時に追求:
は探索の程度を制御する温度パラメータです。
ソフトQ関数ベルマン方程式:
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つの手法:
- Twin Critics: 2つのQ-ネットワークの最小値を選択
- Delayed Policy Updates: クリティックより低い頻度でアクターを更新
- Target Policy Smoothing: ターゲット行動にノイズを追加
HER (Hindsight Experience Replay)
疎な報酬環境で失敗した経験を再利用します。目標を実際に到達した状態に事後的に置き換えて学習:
- 元の経験: — 目標 に失敗
- HER変換: — (実際の最終状態)
目標置き換え戦略:
- 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つの応答を比較し、より良い方を選択 (選好データ収集)
- 選好データで報酬モデルを学習
は選好された応答、 は選好されない応答です。
段階3: PPOによるLLMファインチューニング
- 報酬モデルを環境として、LLMをエージェントとしてPPOを適用
- KLペナルティで元のモデルから大きく離れないように制御
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ループをシンプルな分類損失に置き換えます:
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 + PPO | DPO |
|---|---|---|
| 報酬モデル | 別途訓練が必要 | 不要 |
| 必要モデル数 | アクター + クリティック + RM + 参照 | 学習モデル + 参照モデル |
| 学習安定性 | RL固有の不安定さあり | 教師あり学習レベルで安定 |
| 実装複雑度 | 高い | 低い |
6. マルチエージェント強化学習
環境タイプ
| 環境タイプ | 説明 | 例 |
|---|---|---|
| 完全協力 | 共有報酬、チーム目標 | ロボットチーム作業 |
| 完全競争 | ゼロサムゲーム | チェス、囲碁 |
| 混合 | 協力+競争 | サッカー、MOBA |
MADDPG (Multi-Agent DDPG)
分散実行 + 中央集権学習 (CTDE) パラダイム:
- 実行時: 各エージェントは自身の観測のみで行動を決定
- 学習時: クリティックは全エージェントの観測と行動を活用
は全体観測、 はエージェント の行動です。
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万ステップでのベンチマーク性能:
| 環境 | SAC | TD3 | PPO |
|---|---|---|---|
| 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デプロイの考慮事項
- 安全制約 (Safe RL): 学習中の危険な行動を防止 — CPO、TRPO-Lagrangian
- サンプル効率: 実世界データは高価かつ低速 — オフラインRL、モデルベースRL
- Sim-to-Real転移: ドメインランダム化とアダプテーション (RMA) でリアリティギャップを縮小
- オフラインRL: 事前収集データのみで学習 — Conservative Q-Learning (CQL)、IQL
クイズ: 強化学習の理解度チェック
Q1. Q学習とSARSAのオンポリシー vs オフポリシーの違いを説明してください。
答え: Q学習はオフポリシー、SARSAはオンポリシー
解説: Q学習の更新ターゲットは で、実際の行動とは無関係にgreedy最大値を使います。一方SARSAは において が実際に取った行動です。CliffWalking問題では、Q学習は崖際の最適経路を学習しますが探索中によく落下し、SARSAはより安全な迂回経路を学習します。
Q2. PPOにおけるクリップ比率ハイパーパラメータepsilonが学習安定性に与える役割は?
答え: epsilonは方策更新の保守性を制御
解説: が の範囲を外れると勾配がブロックされます。 が小さすぎると学習が遅くなり局所最小値に陥りやすくなります。逆に大きすぎると方策が急激に変化して不安定になります。一般的に が良いデフォルト値で、学習後半に徐々に減少させるスケジューリングも効果的です。
Q3. RLHFで報酬モデルの訓練データを収集する方法は?
答え: 人間のアノテーターが2つの応答ペアを比較して選好を示す
解説: 同じプロンプトに対する2つの応答 を人間のアノテーターに見せ、より良い応答を選択させます。絶対評価 (1-5点) よりもペアワイズ比較のほうが一貫性があり信頼性が高いです。収集した選好データ で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の目的関数にエントロピー項 を追加すると、エージェントは報酬を最大化しながら同時に行動のランダム性を維持しようとします。これは自動的な探索メカニズムを提供し、局所最小値からの脱出に役立ちます。また、同等に良い複数の行動がある場合に均等に選択するロバストな方策を学習します。温度パラメータ は目標エントロピーに合わせて自動チューニング (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研究者にとって必須のスキルとなっています。
推奨学習ロードマップ:
- Gymnasium + Q学習/DQNを自分で実装
- Stable-Baselines3でPPO/SACを実験
- TRLライブラリでRLHF/DPOを実践
- 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 公式ドキュメント