Chuyển đến nội dung chính

レッスン 6: ポリシーの勾配 — REINFORCE とアクター - 批評家

政策勾配定理。 REINFORCE アルゴリズム。ベースラインと分散の削減。俳優兼評論家。 A2C。 CartPole、LunarLander を実際に体験してみませんか。

🧠 AI と ML — レッスン 5 レッスン 6: ポリシーの勾配 — 強化と 俳優・評論家

強化学習: 基礎から高度まで

パート 2: 深層強化学習 — ニューラル ネットワークと RL の出会い

xdev.asia

はじめに

ポリシー勾配 メソッドは、値関数を学習してポリシーを導出する代わりに、ポリシー π(a|s;θ) を直接最適化します。利点: 継続的なアクション、確率的ポリシー、および収束保証を処理します。


1. ポリシー勾配定理

$$\nabla_\theta J(\theta) = \mathbb{E}{\pi\theta}[\nabla_\theta \log \pi_\theta(a|s) \cdot G_t]$$

直感: アクションの確率を高めると高いリターンが得られ、アクションの確率を下げると低いリターンが得られます。


2. REINFORCE アルゴリズム

import torch
import torch.nn as nn
from torch.distributions import Categorical

class PolicyNetwork(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, action_dim),
            nn.Softmax(dim=-1),
        )
    
    def forward(self, x):
        return self.net(x)

def reinforce(env, policy_net, optimizer, num_episodes, gamma=0.99):
    for episode in range(num_episodes):
        log_probs = []
        rewards = []
        state, _ = env.reset()
        done = False
        
        while not done:
            probs = policy_net(torch.FloatTensor(state))
            dist = Categorical(probs)
            action = dist.sample()
            log_probs.append(dist.log_prob(action))
            
            state, reward, terminated, truncated, _ = env.step(action.item())
            rewards.append(reward)
            done = terminated or truncated
        
        # Compute discounted returns
        returns = []
        G = 0
        for r in reversed(rewards):
            G = r + gamma * G
            returns.insert(0, G)
        returns = torch.FloatTensor(returns)
        returns = (returns - returns.mean()) / (returns.std() + 1e-8)
        
        # Policy gradient loss
        loss = sum(-lp * G for lp, G in zip(log_probs, returns))
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

3. ベースラインと分散の削減

ベースライン b(s) を使用して、予想される勾配を変更せずに分散を削減します。

$$\nabla_\theta J(\theta) = \mathbb{E}[\nabla_\theta \log \pi_\theta(a|s) \cdot (G_t - b(s))]$$


4. 俳優兼批評家

class ActorCritic(nn.Module):
    def __init__(self, state_dim, action_dim):
        super().__init__()
        self.shared = nn.Sequential(nn.Linear(state_dim, 128), nn.ReLU())
        self.actor = nn.Sequential(nn.Linear(128, action_dim), nn.Softmax(dim=-1))
        self.critic = nn.Linear(128, 1)
    
    def forward(self, x):
        feat = self.shared(x)
        return self.actor(feat), self.critic(feat)

def actor_critic_update(model, optimizer, state, action, reward, next_state, done, gamma):
    probs, value = model(torch.FloatTensor(state))
    _, next_value = model(torch.FloatTensor(next_state))
    
    # Advantage = TD error
    advantage = reward + gamma * next_value * (1 - done) - value
    
    # Actor loss
    dist = Categorical(probs)
    actor_loss = -dist.log_prob(torch.tensor(action)) * advantage.detach()
    
    # Critic loss
    critic_loss = advantage.pow(2)
    
    loss = actor_loss + 0.5 * critic_loss
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

5. A2C — アドバンテージアクター兼批評家

A2C = 同期、複数のワーカー → 差異の削減 + トレーニングの高速化。


概要

方法タイプ分散バイアスオンライン
補強するポリシー高なし❌
補強 + ベースラインポリシー中なし❌
俳優・評論家両方低いいくつか✅
A2C両方下いくつか✅