跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

强化学习:演员评论家 Actor-Critic 算法原理与实战

演员评论家(Actor-Critic)算法通过结合策略梯度与值函数估计,有效降低了强化学习中的方差问题。Actor 负责动作决策,Critic 评估状态价值并提供 TD 误差指导更新。该框架在 A3C、PPO 等现代算法中广泛应用。解析其数学原理,提供基于 PyTorch 的完整实现及 CartPole 环境训练示例,帮助理解核心机制与工程落地细节。

道系青年发布于 2026/3/16更新于 2026/9/1158 浏览
强化学习:演员评论家 Actor-Critic 算法原理与实战

演员评论家 Actor-Critic 算法

Actor-Critic 算法是强化学习中一种结合了策略梯度(Policy Gradient)和值函数估计(Value Function Estimation)的方法。它通过'演员'(Actor)负责决策动作,'评论家'(Critic)评估状态价值,两者协作以降低方差并加速收敛。

核心概念与角色设定

想象一个学习爬山的机器人,目标是找到山顶(最高奖励):

  • Actor(行动者):像冒险家,根据当前策略决定下一步怎么走(左或右)。它不总是聪明,可能会选错方向。
  • Critic(评论者):像导师,观察冒险家的表现,评价这一步的好坏。它会告诉 Actor:'这一步走得好,接近山顶了'或者'走错了'。

协作机制:

  1. Actor 观察环境,根据策略选择一个动作。
  2. Critic 根据动作和环境反馈计算'价值',表示该动作的优劣。
  3. Actor 利用 Critic 的评价调整策略,使未来选择更优。

这种分工使得 Actor 专注于优化策略,而 Critic 专注于准确评估,两者互补。

背景与动机

为什么需要 Actor-Critic?

强化学习主要有三类方法:值函数法(如 Q-Learning)、策略法、以及结合两者的 Actor-Critic。

纯策略梯度方法存在明显局限:

  1. 高方差:直接使用环境反馈计算梯度会导致更新不稳定。
  2. 低效率:奖励信号稀疏且传递慢,采样成本高。

引入 Critic 后,通过估算值函数来计算优势函数(Advantage Function),可以显著降低策略梯度的方差,同时保留策略方法的灵活性。

数学推导基础

1. 优化目标

最大化累积折扣奖励的期望: $$J(\theta) = \mathbb{E}{\pi\theta} \left[ \sum_{t=0}^\infty \gamma^t r_t \right]$$

2. 策略梯度定理

为了优化策略参数 $\theta$,计算目标函数的梯度: $$\nabla_\theta J(\theta) = \mathbb{E}{\pi\theta} \left[ \nabla_\theta \log \pi_\theta(a|s) \cdot A^\pi(s, a) \right]$$ 其中 $A^\pi(s, a)$ 是优势函数,衡量动作的相对好坏。

3. Critic 的作用

Critic 通过最小化均方误差来学习状态值函数 $V^\pi(s)$: $$L(w) = \frac{1}{2} \mathbb{E} \left[ (r + \gamma V^\pi(s') - V^\pi(s))^2 \right]$$ 这里 $\delta = r + \gamma V^\pi(s') - V^\pi(s)$ 即为时间差分(TD)误差,用于指导 Actor 更新。

算法流程

完整的 Actor-Critic 迭代过程如下:

  1. 初始化 Actor 和 Critic 网络参数。
  2. 在状态 $s$ 下,Actor 根据策略 $\pi_\theta(a|s)$ 采样动作 $a$。
  3. 执行动作,获得奖励 $r$ 和下一状态 $s'$。
  4. Critic 计算 TD 误差 $\delta$。
  5. Critic 利用 $\delta$ 更新值函数参数,减小预测误差。
  6. Actor 利用 $\delta$ 更新策略参数,向更优方向移动。
  7. 重复直至收敛。

PyTorch 实现

下面是一个基于 PyTorch 的完整实现示例。我们定义两个网络:PolicyNet 作为 Actor,ValueNet 作为 Critic。

网络结构

import torch
from torch import nn
from torch.nn import functional as F
import numpy as np

class PolicyNet(nn.Module):
    """Actor: 策略网络,输出动作概率分布"""
    def __init__(self, n_states, n_hiddens, n_actions):
        super(PolicyNet, self).__init__()
        self.fc1 = nn.Linear(n_states, n_hiddens)
        self.fc2 = nn.Linear(n_hiddens, n_actions)

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

class ValueNet(nn.Module):
    """Critic: 值函数网络,输出状态价值"""
    def __init__(self, n_states, n_hiddens):
        super(ValueNet, self).__init__()
        self.fc1 = nn.Linear(n_states, n_hiddens)
        self.fc2 = nn.Linear(n_hiddens, 1)

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

训练逻辑

class ActorCritic:
    def __init__(self, n_states, n_hiddens, n_actions, actor_lr, critic_lr, gamma):
        self.gamma = gamma
        self.actor = PolicyNet(n_states, n_hiddens, n_actions)
        self.critic = ValueNet(n_states, n_hiddens)
        
        # 注意:Actor 和 Critic 使用不同的学习率通常效果更好
        self.actor_optimizer = torch.optim.Adam(self.actor.parameters(), lr=actor_lr)
        self.critic_optimizer = torch.optim.Adam(self.critic.parameters(), lr=critic_lr)

    def take_action(self, state):
        """根据当前策略采样动作"""
        state = torch.tensor(state[np.newaxis, :], dtype=torch.float)
        probs = self.actor(state)
        action_dist = torch.distributions.Categorical(probs)
        action = action_dist.sample().item()
        return action

    def update(self, transition_dict):
        """批量更新 Actor 和 Critic"""
        states = torch.tensor(transition_dict['states'], dtype=torch.float)
        actions = torch.tensor(transition_dict['actions']).view(-1, 1)
        rewards = torch.tensor(transition_dict['rewards'], dtype=torch.float).view(-1, 1)
        next_states = torch.tensor(transition_dict['next_states'], dtype=torch.float)
        dones = torch.tensor(transition_dict['dones'], dtype=torch.float).view(-1, 1)

        # Critic 更新:最小化 TD 误差
        td_value = self.critic(states)
        td_target = rewards + self.gamma * self.critic(next_states) * (1 - dones)
        td_delta = td_target - td_value
        critic_loss = torch.mean(F.mse_loss(td_value, td_target.detach()))

        # Actor 更新:最大化优势函数
        log_probs = torch.log(self.actor(states).gather(1, actions))
        actor_loss = torch.mean(-log_probs * td_delta.detach())

        # 反向传播与参数更新
        self.actor_optimizer.zero_grad()
        self.critic_optimizer.zero_grad()
        actor_loss.backward()
        critic_loss.backward()
        self.actor_optimizer.step()
        self.critic_optimizer.step()

环境测试(CartPole)

使用 OpenAI Gym 的 CartPole-v1 环境进行验证:

import gym
import matplotlib.pyplot as plt

env_name = 'CartPole-v1'
env = gym.make(env_name)
n_states = env.observation_space.shape[0]
n_actions = env.action_space.n

# 实例化 Agent
agent = ActorCritic(
    n_states=n_states,
    n_hiddens=16,
    n_actions=n_actions,
    actor_lr=1e-3,
    critic_lr=1e-2,
    gamma=0.9
)

return_list = []
for i in range(100):  # 100 个回合
    state = env.reset()[0]
    done = False
    episode_return = 0
    transition_dict = {'states': [], 'actions': [], 'next_states': [], 'rewards': [], 'dones': []}

    while not done:
        action = agent.take_action(state)
        next_state, reward, done, _, _ = env.step(action)
        
        transition_dict['states'].append(state)
        transition_dict['actions'].append(action)
        transition_dict['next_states'].append(next_state)
        transition_dict['rewards'].append(reward)
        transition_dict['dones'].append(done)
        
        state = next_state
        episode_return += reward

    return_list.append(episode_return)
    agent.update(transition_dict)
    print(f'Iter {i}, Avg Return: {np.mean(return_list[-10:])}')

plt.plot(return_list)
plt.title('Training Returns')
plt.show()

关键点总结

  1. 稳定性:Critic 的误差直接影响 Actor 的梯度更新,因此 Critic 的学习率通常设置得比 Actor 稍大或相当。
  2. 探索性:如果训练陷入局部最优,可以考虑对 Actor 加入熵正则化项鼓励探索。
  3. 扩展性:此框架是 A3C、PPO 等现代算法的基础,理解其核心有助于掌握更复杂的强化学习模型。

环境配置建议

  • Python 3.8+
  • PyTorch 1.10+
  • Gym 0.21+

确保依赖库版本兼容,避免运行时出现张量维度不匹配的问题。

目录

  1. 演员评论家 Actor-Critic 算法
  2. 核心概念与角色设定
  3. 背景与动机
  4. 为什么需要 Actor-Critic?
  5. 数学推导基础
  6. 1. 优化目标
  7. 2. 策略梯度定理
  8. 3. Critic 的作用
  9. 算法流程
  10. PyTorch 实现
  11. 网络结构
  12. 训练逻辑
  13. 环境测试(CartPole)
  14. 实例化 Agent
  15. 关键点总结
  16. 环境配置建议

更多推荐文章

查看全部
  • 单链表核心操作全实现:查找、插入与删除的深度解析
  • macOS 指定版本升级指南:从 15.3 升级至 15.4 而非最新版
  • Stable Diffusion 秋叶整合包 v4.7 本地部署与入门指南
  • GitHub Copilot 学生认证指南:免费获取 Pro 版权限
  • Rust WebAssembly 与 Three.js 结合的高性能 3D 粒子系统
  • eBay API 授权码无效或过期错误排查指南
  • 利用闲置安卓手机搭建复古掌机及天马 G 前端配置
  • WebAssembly 结合 RustFS:浏览器端高性能文件管理方案
  • Streamlit 实战指南:用 Python 快速构建数据 Web 应用
  • OpenClaw 龙虾机器人本地部署与进阶配置指南
  • AI 大模型赋能专利翻译:核心功能与应用场景解析
  • 与模型对话:理解与预防 ChatGPT 中的常见误解
  • 前端调试实战:VSCode 动态审查与性能优化技巧
  • C++ map 与 set 容器详解:从原理到实战
  • 竞争自适应重加权采样(CARS)算法在光谱数据变量选择中的应用
  • 2025 年秋招 LLM 及多模态模型面试精华
  • RAG 系统实现指南:Langchain 与纯手搓方案对比
  • RunningHub 平台架构与创作流程拆解
  • 在 Cursor 中配置和使用 MCP 服务
  • Copilot Cowork 核心逻辑与 Kotlin AI Agent 实现

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online