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

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

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

道系青年发布于 2026/3/16更新于 2026/7/2332 浏览
强化学习:演员评论家 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. 环境配置建议
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • DocxFactory:基于 C++ 的 Word 文档生成库(无需 Office)
  • 微信小程序 Python 后端大学生心理健康服务系统设计
  • 2024 年人工智能全景报告深度解读与技术路径分析
  • Java Map 常用方法和实现类深度详解
  • Flutter 三方库 jwt_io 的鸿蒙化适配指南
  • 宇树 G1 人形机器人强化学习训练实战指南
  • Spring Cloud 微服务架构:网关 Zuul、链路追踪 Sleuth 与 Admin 健康检查
  • Python 文件写入方法示例
  • PEEK取代金属:精密注塑齿轮蜗杆驱动机器人灵巧手技术与成本革新
  • 飞书机器人对接 Claude Code:实现手机端 AI 编程助手
  • Git 安装流程与基础使用步骤
  • 从 Copilot 到 Agentic:重构人×AI×流程的研发范式实践
  • C++ 核心特性解析:引用、内联函数与 nullptr 用法
  • AI 原生重构低代码:开发行业迎来范式革命
  • C++ ODB ORM 框架入门与实战
  • Ambari Web 3.0.0 本地启动与二次开发环境搭建
  • Java 动态列表实现杨辉三角算法解析
  • HarmonyOS6 RcList 组件综合示例与尺寸计算
  • 前端实战:如何实现用户回到上次阅读位置
  • 从零卷积到艺术创作:ControlNet 如何重塑 AI 绘画的边界

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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