Skip to content
Published on

[深層強化学習] 20. 深層強化学習総まとめ:アルゴリズム比較と選択ガイド

Authors

概要

このシリーズで多様な深層強化学習アルゴリズムを見てきました。最後の記事では、すべての手法を体系的に整理し、どのような状況でどのアルゴリズムを選択すべきかのガイドを提供します。また現在活発に研究されている最新分野と学習リソースも紹介します。


アルゴリズム分類体系

全体の分類図

深層強化学習アルゴリズムは大きく4つの軸で分類できます:

1. 価値ベース(Value-Based)

  • 状態または行動の価値を学習
  • 価値から方策を導出(通常は貪欲選択)
  • 代表:DQN、Double DQN、Dueling DQN、Rainbow

2. 方策ベース(Policy-Based)

  • 方策を直接パラメータ化して学習
  • REINFORCE、進化戦略、遺伝的アルゴリズム

3. Actor-Critic

  • 方策(Actor)と価値(Critic)を同時に学習
  • A2C、A3C、PPO、TRPO、ACKTR、DDPG、SAC

4. モデルベース(Model-Based)

  • 環境モデルを学習して計画に活用
  • I2A、World Models、Dreamer、MuZero

価値ベース手法の整理

DQN系列

# DQN系列アルゴリズムの核心的な違いを示す疑似コード

def dqn_target(reward, next_state, done, gamma, q_network, target_network):
    """基本DQN:ターゲットネットワークで最大Q値を計算"""
    with torch.no_grad():
        max_q = target_network(next_state).max(dim=-1)[0]
        target = reward + gamma * (1 - done) * max_q
    return target

def double_dqn_target(reward, next_state, done, gamma,
                       q_network, target_network):
    """Double DQN:行動選択と評価を分離"""
    with torch.no_grad():
        # メインネットワークで行動選択
        best_actions = q_network(next_state).argmax(dim=-1)
        # ターゲットネットワークで価値評価
        q_values = target_network(next_state)
        max_q = q_values.gather(1, best_actions.unsqueeze(1)).squeeze()
        target = reward + gamma * (1 - done) * max_q
    return target

def dueling_network_forward(features, advantage_stream, value_stream):
    """Dueling DQN:価値とアドバンテージを分離"""
    value = value_stream(features)        # V(s)
    advantage = advantage_stream(features) # A(s,a)
    # Q(s,a) = V(s) + A(s,a) - mean(A)
    q_values = value + advantage - advantage.mean(dim=-1, keepdim=True)
    return q_values

価値ベース手法の比較

アルゴリズム核心改善離散/連続主な長所
DQN経験リプレイ + ターゲットネットワーク離散安定した学習
Double DQN過大推定バイアスの低減離散正確なQ値
Dueling DQNVとAの分離離散状態価値学習の効率
Prioritized ER重要経験の優先学習離散サンプル効率
Noisy DQNパラメータノイズ探索離散適応的探索
Categorical DQNリターン分布の学習離散安定性、豊富な信号
Rainbow上記すべての技法の統合離散最高性能

方策ベース手法の整理

REINFORCEと変形

import torch

def reinforce_loss(log_probs, returns):
    """基本REINFORCE:高分散"""
    return -(log_probs * returns).mean()

def reinforce_with_baseline(log_probs, returns, values):
    """ベースラインREINFORCE:分散低減"""
    advantages = returns - values.detach()
    policy_loss = -(log_probs * advantages).mean()
    value_loss = (returns - values).pow(2).mean()
    return policy_loss + 0.5 * value_loss

def ppo_clipped_loss(log_probs, old_log_probs, advantages,
                     clip_epsilon=0.2):
    """PPO:安定した方策更新"""
    ratio = torch.exp(log_probs - old_log_probs)
    surr1 = ratio * advantages
    surr2 = torch.clamp(ratio, 1 - clip_epsilon,
                         1 + clip_epsilon) * advantages
    return -torch.min(surr1, surr2).mean()

Actor-Critic手法の整理

On-Policy vs Off-Policy

属性On-PolicyOff-Policy
データ使用現在の方策からのみ収集過去データの再利用が可能
サンプル効率低い高い
安定性高い比較的低い
代表アルゴリズムA2C, PPO, TRPODDPG, SAC, TD3

SAC(Soft Actor-Critic)

SACはエントロピーを最大化して探索と活用を自動的にバランスするアルゴリズムです:

import torch
import torch.nn as nn
import copy

class SACAgent:
    """SAC:最大エントロピー強化学習"""

    def __init__(self, obs_size, act_size, hidden=256,
                 lr=3e-4, gamma=0.99, tau=0.005):
        self.gamma = gamma
        self.tau = tau
        self.q1 = self._make_q(obs_size, act_size, hidden)
        self.q2 = self._make_q(obs_size, act_size, hidden)
        self.q1_target = copy.deepcopy(self.q1)
        self.q2_target = copy.deepcopy(self.q2)
        self.actor = self._make_actor(obs_size, act_size, hidden)
        self.log_alpha = torch.zeros(1, requires_grad=True)
        self.target_entropy = -act_size
        self.q1_opt = torch.optim.Adam(self.q1.parameters(), lr=lr)
        self.q2_opt = torch.optim.Adam(self.q2.parameters(), lr=lr)
        self.actor_opt = torch.optim.Adam(self.actor.parameters(), lr=lr)
        self.alpha_opt = torch.optim.Adam([self.log_alpha], lr=lr)

    def _make_q(self, obs_size, act_size, hidden):
        return nn.Sequential(
            nn.Linear(obs_size + act_size, hidden), nn.ReLU(),
            nn.Linear(hidden, hidden), nn.ReLU(),
            nn.Linear(hidden, 1),
        )

    def _make_actor(self, obs_size, act_size, hidden):
        return GaussianActor(obs_size, act_size, hidden)

    @property
    def alpha(self):
        return self.log_alpha.exp()

    def update(self, batch):
        states, actions, rewards, next_states, dones = batch

        with torch.no_grad():
            next_actions, next_log_probs = self.actor.sample(next_states)
            q1_next = self.q1_target(torch.cat([next_states, next_actions], -1))
            q2_next = self.q2_target(torch.cat([next_states, next_actions], -1))
            q_next = torch.min(q1_next, q2_next)
            target = rewards + self.gamma * (1 - dones) * (
                q_next - self.alpha * next_log_probs
            )

        q1_val = self.q1(torch.cat([states, actions], -1))
        q2_val = self.q2(torch.cat([states, actions], -1))
        q1_loss = (q1_val - target).pow(2).mean()
        q2_loss = (q2_val - target).pow(2).mean()

        self.q1_opt.zero_grad(); q1_loss.backward(); self.q1_opt.step()
        self.q2_opt.zero_grad(); q2_loss.backward(); self.q2_opt.step()

        new_actions, log_probs = self.actor.sample(states)
        q1_new = self.q1(torch.cat([states, new_actions], -1))
        q2_new = self.q2(torch.cat([states, new_actions], -1))
        q_new = torch.min(q1_new, q2_new)
        actor_loss = (self.alpha.detach() * log_probs - q_new).mean()

        self.actor_opt.zero_grad(); actor_loss.backward(); self.actor_opt.step()

        alpha_loss = -(self.log_alpha * (log_probs.detach() + self.target_entropy)).mean()
        self.alpha_opt.zero_grad(); alpha_loss.backward(); self.alpha_opt.step()

        self._soft_update(self.q1, self.q1_target)
        self._soft_update(self.q2, self.q2_target)

    def _soft_update(self, source, target):
        for s, t in zip(source.parameters(), target.parameters()):
            t.data.copy_(self.tau * s.data + (1 - self.tau) * t.data)

class GaussianActor(nn.Module):
    def __init__(self, obs_size, act_size, hidden):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(obs_size, hidden), nn.ReLU(),
            nn.Linear(hidden, hidden), nn.ReLU(),
        )
        self.mu = nn.Linear(hidden, act_size)
        self.log_std = nn.Linear(hidden, act_size)

    def forward(self, obs):
        features = self.net(obs)
        return self.mu(features), self.log_std(features).clamp(-20, 2)

    def sample(self, obs):
        mu, log_std = self.forward(obs)
        std = log_std.exp()
        dist = torch.distributions.Normal(mu, std)
        z = dist.rsample()
        action = torch.tanh(z)
        log_prob = (dist.log_prob(z) - torch.log(1 - action.pow(2) + 1e-6)).sum(dim=-1, keepdim=True)
        return action, log_prob

総合比較表

アルゴリズム選択ガイド

状況推奨アルゴリズム理由
離散行動、オフラインデータありDQN/Rainbowリプレイバッファ活用
離散行動、高速プロトタイピングA2C実装簡単、高速実験
連続行動、安定性重視PPO実装簡単で安定的
連続行動、サンプル効率重視SACOff-policy + 自動探索
連続行動、決定的方策が必要DDPG/TD3決定的方策
ボードゲームAlphaZeroMCTS + 自己対局
微分不可の報酬ES/GA勾配不要
シミュレータあり、サンプル制限Dreamer/MuZeroモデルベースの効率性

ハイパーパラメータ感度

# 各アルゴリズムの主要ハイパーパラメータと一般的な値

hyperparams = {
    'DQN': {
        'lr': 1e-4,
        'batch_size': 32,
        'buffer_size': 1000000,
        'target_update_freq': 1000,
        'epsilon_decay': 'linear to 0.01 over 1M steps',
        'sensitivity': 'medium',
    },
    'PPO': {
        'lr': 3e-4,
        'clip_epsilon': 0.2,
        'num_epochs': 10,
        'batch_size': 64,
        'gae_lambda': 0.95,
        'entropy_coef': 0.01,
        'sensitivity': 'low',
    },
    'SAC': {
        'lr': 3e-4,
        'batch_size': 256,
        'buffer_size': 1000000,
        'tau': 0.005,
        'auto_alpha': True,
        'sensitivity': 'low',
    },
    'DDPG': {
        'lr_actor': 1e-4,
        'lr_critic': 1e-3,
        'batch_size': 256,
        'tau': 0.005,
        'noise_type': 'OU or Gaussian',
        'sensitivity': 'high',
    },
}

現在の研究最前線

オフラインRL(バッチ強化学習)

事前に収集された固定データセットのみで学習する方法。追加の環境相互作用なしに既存データを最大限活用します。

class ConservativeQLearning:
    """CQL:保守的Q学習の核心アイデア"""

    def compute_cql_loss(self, q_network, states, actions, alpha=1.0):
        td_loss = self.compute_td_loss(q_network, states, actions)
        random_actions = torch.rand_like(actions) * 2 - 1
        random_q = q_network(states, random_actions)
        data_q = q_network(states, actions)
        cql_penalty = (
            torch.logsumexp(random_q, dim=0).mean() - data_q.mean()
        )
        return td_loss + alpha * cql_penalty

核心アルゴリズム:CQL、IQL、Decision Transformer、Diffusion Policy

マルチエージェントRL(多重エージェント)

複数のエージェントが同時に学習する環境:

  • 協力(Cooperative):チームメイトが共通目標を追求
  • 競争(Competitive):エージェント間の競争
  • 混合(Mixed):協力と競争が混在

核心課題:非定常性(non-stationarity)、通信、クレジット割当

安全なRL(Safe RL)

報酬最大化と同時に安全制約を満たす方法:

class SafeRLObjective:
    """制約ベースの安全強化学習の目的"""

    def compute_objective(self, policy, states):
        expected_reward = self.estimate_reward(policy, states)
        expected_cost = self.estimate_cost(policy, states)
        cost_limit = 25.0
        lagrangian = (expected_reward
                      - self.lambda_multiplier
                      * (expected_cost - cost_limit))
        return lagrangian

核心アルゴリズム:CPO(Constrained Policy Optimization)、WCSAC、SafeOpt

その他の研究方向

  • メタ強化学習(Meta-RL):新しいタスクに素早く適応するエージェント
  • 階層的強化学習(Hierarchical RL):高レベル/低レベルの方策を分離して長期計画を立てる
  • 表現学習:良い状態表現を自動的に学習
  • 大規模言語モデル + RL:LLMの推論能力をRLに活用

学習ロードマップ

推奨学習順序

  1. 基礎(1〜2週間)

    • MDP、ベルマン方程式の理解
    • 動的プログラミング(方策/価値反復)
    • 探索と活用のジレンマ
  2. 価値ベース(2〜3週間)

    • Q-learningの実装
    • DQNの実装とAtari実験
    • Double/Dueling DQNの理解
  3. 方策ベース(2〜3週間)

    • REINFORCEの実装
    • A2C/A3Cの理解と実装
    • PPOの実装(最も重要)
  4. 連続行動(1〜2週間)

    • DDPGの実装
    • SACの実装
    • MuJoCo/PyBullet実験
  5. 発展(2〜4週間)

    • モデルベースRL(Dreamer)
    • マルチエージェントRL
    • オフラインRL
    • 実践プロジェクト

核心実装フレームワーク

# 主要RLライブラリ

# 1. Stable-Baselines3: 検証済み実装、高速実験
# pip install stable-baselines3
from stable_baselines3 import PPO, SAC, DQN

model = PPO("MlpPolicy", "CartPole-v1", verbose=1)
model.learn(total_timesteps=100000)

# 2. CleanRL: 単一ファイル実装、教育用に最高
# 各アルゴリズムが1つのファイルに完全実装

# 3. RLlib (Ray): 分散学習、プロダクションレベル
# pip install ray[rllib]

# 4. Tianshou: PyTorchベース、柔軟な構造
# pip install tianshou

シリーズ回顧

このシリーズで扱った内容を時系列で整理すると:

記事番号テーマ核心アルゴリズム/概念
11A3C非同期並列学習、データ/勾配並列化
12チャットボットRLSeq2Seq、SCST、報酬設計
13ウェブナビゲーションMiniWoB、グリッド行動空間、人間のデモンストレーション
14連続行動DDPG、OUノイズ、分布方策(D4PG)
15Trust RegionPPO、TRPO、ACKTR
16Black-Box進化戦略(ES)、遺伝的アルゴリズム(GA)
17モデルベースI2A、環境モデル、ロールアウトエンコーダ
18AlphaGo ZeroMCTS、自己対局、Connect4実装
19応用事例ロボット、自律走行、推薦、RLHF
20総まとめアルゴリズム比較、選択ガイド

終わりに

深層強化学習は急速に発展している分野です。このシリーズで扱った基本アルゴリズムは現在の最新研究を理解するための必須の土台となります。

最も重要なアドバイス3つ:

  1. 自分で実装すること:コードを自分で書いてこそアルゴリズムを真に理解できる
  2. 簡単な環境から始めること:CartPoleで動かないものは複雑な環境でも動かない
  3. 常にベースラインと比較すること:新しい方法がシンプルな方法より本当に良いか確認すること

強化学習の旅に終わりはありません。このシリーズが出発点となることを願います。