Actor-Critic强化学习框架结构图解析:从理论到工程实践

1次阅读
没有评论

共计 3398 个字符,预计需要花费 9 分钟才能阅读完成。

image.webp

背景与痛点

强化学习中的策略梯度(Policy Gradient)方法直接优化策略,能够处理连续动作空间,但存在高方差问题,导致训练不稳定。而价值函数方法(如 Q -Learning)通过估计状态或状态 - 动作的价值函数来间接优化策略,方差较低但容易产生估计偏差。这两种方法各自存在明显的局限性,特别是在复杂环境中表现不佳。

Actor-Critic 强化学习框架结构图解析:从理论到工程实践

Actor-Critic 框架结合了两种方法的优点:Actor 负责策略优化,Critic 负责价值估计,两者相互促进,显著提升了训练稳定性和效率。

框架结构解析

Actor-Critic 框架的核心在于两个组件的协同工作:

  1. Actor(策略网络):输入当前状态,输出动作的概率分布。目标是最大化预期回报,通过策略梯度进行更新。
  2. Critic(价值网络):输入当前状态(或状态 - 动作对),输出价值估计。目标是减少价值估计的误差,通常通过时序差分(TD)误差更新。

两者的交互流程如下:

  1. Actor 根据当前策略选择动作。
  2. 环境执行动作并返回新状态和奖励。
  3. Critic 评估当前状态的价值,并计算 TD 误差。
  4. TD 误差用于调整 Actor 的策略梯度更新幅度(作为基线减少方差)。
  5. Critic 根据 TD 误差更新自身的价值估计。

这种交互使得 Actor 能够更稳定地优化策略,而 Critic 的价值估计则逐渐趋于准确。

PyTorch 实现

以下是基于 PyTorch 的 Actor-Critic 实现代码:

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F

# 定义 Actor 策略网络
class Actor(nn.Module):
    def __init__(self, state_dim, action_dim, hidden_dim=128):
        super(Actor, self).__init__()
        self.fc1 = nn.Linear(state_dim, hidden_dim)
        self.fc2 = nn.Linear(hidden_dim, hidden_dim)
        self.fc3 = nn.Linear(hidden_dim, action_dim)

    def forward(self, state):
        x = F.relu(self.fc1(state))
        x = F.relu(self.fc2(x))
        action_probs = F.softmax(self.fc3(x), dim=-1)
        return action_probs

# 定义 Critic 价值网络
class Critic(nn.Module):
    def __init__(self, state_dim, hidden_dim=128):
        super(Critic, self).__init__()
        self.fc1 = nn.Linear(state_dim, hidden_dim)
        self.fc2 = nn.Linear(hidden_dim, hidden_dim)
        self.fc3 = nn.Linear(hidden_dim, 1)

    def forward(self, state):
        x = F.relu(self.fc1(state))
        x = F.relu(self.fc2(x))
        value = self.fc3(x)
        return value

# 经验回放缓冲区
class ReplayBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.buffer = []

    def push(self, state, action, reward, next_state, done):
        if len(self.buffer) >= self.capacity:
            self.buffer.pop(0)
        self.buffer.append((state, action, reward, next_state, done))

    def sample(self, batch_size):
        return random.sample(self.buffer, batch_size)

# 训练过程示例
def train(env, actor, critic, buffer, batch_size=64, gamma=0.99):
    # 从缓冲区采样
    transitions = buffer.sample(batch_size)
    states, actions, rewards, next_states, dones = zip(*transitions)

    # 转换为张量
    states = torch.FloatTensor(states)
    actions = torch.LongTensor(actions)
    rewards = torch.FloatTensor(rewards)
    next_states = torch.FloatTensor(next_states)
    dones = torch.FloatTensor(dones)

    # Critic 更新
    current_values = critic(states)
    next_values = critic(next_states)
    target_values = rewards + gamma * next_values * (1 - dones)
    critic_loss = F.mse_loss(current_values, target_values.detach())

    critic_optimizer.zero_grad()
    critic_loss.backward()
    critic_optimizer.step()

    # Actor 更新
    action_probs = actor(states)
    selected_action_probs = action_probs.gather(1, actions.unsqueeze(1))
    advantages = target_values - current_values.detach()
    actor_loss = -torch.log(selected_action_probs) * advantages
    actor_loss = actor_loss.mean()

    actor_optimizer.zero_grad()
    actor_loss.backward()
    actor_optimizer.step()

调优技巧

  1. 学习率设置 :Actor 和 Critic 通常需要不同的学习率,Critic 的学习率可以略高于 Actor(如 0.001 vs 0.0001),以确保价值估计更快收敛。
  2. 折扣因子选择 :对于回合制任务,gamma 可以设置较高(0.99);对于连续任务,可能需要更低的值(0.9-0.95)。
  3. 探索策略 :初始阶段可以加入较高的随机探索(如 ε -greedy),随着训练逐渐降低。
  4. 批量大小 :较大的批量(128-256)有助于稳定训练,但会增加内存需求。
  5. 网络结构 :Critic 网络可以比 Actor 稍深一些,以更好地拟合价值函数。

避坑指南

  1. 梯度消失 :使用 ReLU 激活函数时,注意初始化权重,避免过小的梯度。可以尝试 LeakyReLU 或 ELU。
  2. 探索不足 :定期检查策略的熵,如果熵过低,说明探索不足,可以增加熵正则化项。
  3. 价值估计偏差 :使用多步 TD 或 Retrace 方法可以减少 Critic 的估计偏差。
  4. 训练不稳定 :定期保存模型检查点,使用梯度裁剪(clip_grad_norm_)防止梯度爆炸。
  5. 过拟合 :在 Critic 网络中加入 dropout 或 L2 正则化。

性能考量

  1. 计算资源 :对于图像输入的环境,可以考虑使用 CNN 作为特征提取器,这会显著增加 GPU 需求。
  2. 训练效率 :使用并行环境(如 VectorEnv)可以大幅提升样本收集效率。
  3. 内存管理 :经验回放缓冲区大小需要根据可用内存调整,通常 10000-100000 个样本为宜。
  4. 分布式训练 :对于大规模任务,可以考虑 A3C 或 IMPALA 等分布式框架。

思考题

  1. 如何修改当前框架使其支持连续动作空间?
  2. 在多智能体环境中,Actor-Critic 框架需要做哪些调整?
  3. 当 Critic 的价值估计持续偏高或偏低时,可能是什么原因导致的?如何解决?
  4. 如何设计一个自适应的探索策略,使其能够根据训练进度自动调整探索率?

希望这篇文章能帮助你理解 Actor-Critic 框架的核心思想并实现自己的强化学习模型。在实际应用中,可能需要根据具体问题调整网络结构和超参数,但理解基本原理是成功的关键。

正文完
 0
评论(没有评论)