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

强化学习:策略梯度定理与 REINFORCE 算法

介绍强化学习中的策略学习方法,对比策略学习与价值学习的区别。详细阐述了策略梯度定理及其证明过程,核心在于最大化期望回报。重点讲解了蒙特卡洛 REINFORCE 算法的实现流程,包括轨迹采样、梯度计算及参数更新。此外,还讨论了使用 Gt 替代 R(tau) 的改进方案,通过引入折扣回报估计来降低方差并提高训练稳定性。提供了基于 PyTorch 的策略网络代码示例及完整的训练循环实现。

蜜桃汽水发布于 2026/3/28更新于 2026/7/2340 浏览
强化学习:策略梯度定理与 REINFORCE 算法

策略学习方法

策略参数化: The idea is to parameterize the policy. For instance, using a neural network π(θ), this policy will output a probability distribution over actions (stochastic policy).

在这里插入图片描述

接受一个状态网络输出的是动作的分布。

在这里插入图片描述

策略学习 vs 价值学习

策略梯度方法能够学习出一种随机策略,而价值函数则无法做到这一点。这会产生两个后果:

  • 我们无需手动进行探索与利用之间的权衡。由于我们输出的是针对行动的概率分布,因此智能体能够在探索状态空间时避免总是遵循相同的路径。

我们还解决了感知混叠的问题。感知混叠指的是当两种状态看起来(或实际上是)相同,但需要采取不同的行动时的情况。

在这里插入图片描述

当然,策略梯度方法也存在一些缺点:

  • 通常,策略梯度方法会收敛到局部最大值而非全局最优值。
  • 策略梯度方法进展较为缓慢,是逐步进行的:训练过程可能会更耗时(效率低下)。
  • 策略梯度方法可能会存在高方差。我们将在'演员 - 评论家'单元中了解其原因以及如何解决这一问题。

偏差和方差的概念:偏差一般指的是预测误差,如果偏差比较低,说明方差一般比较高;

策略梯度方法

目标函数

对于给定参数化策略,我们希望在这个策略下,最大化所有轨迹的期望均值。

在这里插入图片描述

这个等价于:

在这里插入图片描述

其中,每一个轨迹给定的概率分布为 (全概率公式):

在这里插入图片描述

策略梯度定理

揭示了目标函数的梯度等价于以下公式:

在这里插入图片描述

证明过程
  • 首先将梯度提进去,然后提出一个 P(τ;θ),拼凑一个 log f(x) 求导的公式

在这里插入图片描述

  • 根据期望定义将上面的公式重新还原为期望

我们带入 P(τ;θ) 的定义,然后老老实实求梯度,发现除了 π(at|st) 之外,所有项不包含 θ,因此直接消去。

在这里插入图片描述

对于这个期望,我们可以利用大数定理对其采样求解其均值。

在这里插入图片描述

在这里插入图片描述

蒙特卡洛 MC Reinforce 算法

我们得到了目标函数的梯度,然后运行梯度上升来最优化我们的策略函数。

在这里插入图片描述

一般来说收集多个轨迹来计算平均梯度。

在这里插入图片描述

策略梯度方法流程:

  • 经历一次完整的动作序列后才能开始更新。

对于好的动作序列,增加其动作选择的概率,对于不好的动作,降低其动作选择的概率。

在这里插入图片描述

实现

我们需要的是: ∑t ∇θ log πθ(at(i)|st(i)) R(τ(i)) 然后用其进行梯度上升。 这转换为利用 torch 对以下函数进行优化 (会自动求梯度并且执行梯度下降)

−∑t log πθ(at(i)|st(i)) R(τ(i))

Reinforce 算法的改进:使用 Gt 替代准确的 R(τ)
  • 公平性:R(τ) 表示某轨迹的累积折扣奖励,对于所有的状态的动作都给相同的 R(τ) 是不公平的,因为前面的动作更加重要,因此采用 Gt 为每个动作概率根据执行顺序赋予不同的权重进行优化。
  • 方差改进:R(τ) 偏差为 0,所以方差必然很大。Gt 作为当前动作的一种估计,以提高偏差为代价降低方差,进而增强稳定性。

我们最终需要优化的方程为: ∑t log πθ(at(i)|st(i)) Gt

在这里插入图片描述

参数化策略代码
class Policy(nn.Module):
    def __init__(self, s_size, a_size, h_size):
        super(Policy, self).__init__()
        self.fc1 = nn.Linear(s_size, h_size)
        self.fc2 = nn.Linear(h_size, a_size)

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

    def act(self, state):
        state = torch.from_numpy(state).float().unsqueeze(0).to(device)
        probs = self.forward(state).cpu()
        m = Categorical(probs)  # torch.distribution 的对象
        action = m.sample()  # idx, log_prob[idx]
        return action.item(), m.log_prob(action)
Reinforce 训练代码
def reinforce(policy, optimizer, n_training_episodes, max_t, gamma, print_every):
    # Help us to calculate the score during the training
    scores_deque = deque(maxlen=100)
    scores = []
    
    # Line 3 of pseudocode
    for i_episode in range(1, n_training_episodes + 1):
        saved_log_probs = []
        rewards = []
        state = env.reset()
        
        # Line 4 of pseudocode
        for t in range(max_t):
            action, log_prob = policy.act(state)
            saved_log_probs.append(log_prob)
            state, reward, done, _ = env.step(action)
            rewards.append(reward)
            if done:
                break
        
        scores_deque.append(sum(rewards))
        scores.append(sum(rewards))
        
        # Line 6 of pseudocode: calculate the return
        returns = deque(maxlen=max_t)
        n_steps = len(rewards)
        
        # Compute the discounted returns at each timestep,
        # as the sum of the gamma-discounted return at time t (G_t) + the reward at time t
        # In O(N) time, where N is the number of time steps
        # (this definition of the discounted return G_t follows the definition of this quantity 
        # shown at page 44 of Sutton&Barto 2017 2nd draft)
        # G_t = r_(t+1) + r_(t+2) + ...
        # Given this formulation, the returns at each timestep t can be computed 
        # by re-using the computed future returns G_(t+1) to compute the current return G_t
        # G_t = r_(t+1) + gamma*G_(t+1)
        # G_(t-1) = r_t + gamma* G_t
        # (this follows a dynamic programming approach, with which we memorize solutions in order 
        # to avoid computing them multiple times)
        # This is correct since the above is equivalent to (see also page 46 of Sutton&Barto 2017 2nd draft)
        # G_(t-1) = r_t + gamma*r_(t+1) + gamma*gamma*r_(t+2) + ...
        
        # Given the above, we calculate the returns at timestep t as: 
        # gamma[t] * return[t] + reward[t]
        
        # We compute this starting from the last timestep to the first, in order
        # to employ the formula presented above and avoid redundant computations that would be needed 
        # if we were to do it from first to last.
        
        # Hence, the queue "returns" will hold the returns in chronological order, from t=0 to t=n_steps
        # thanks to the appendleft() function which allows to append to the position 0 in constant time O(1)
        # a normal python list would instead require O(N) to do this.
        for t in range(n_steps)[::-1]:  # inverse order
            disc_return_t = (returns[0] if len(returns) > 0 else 0)
            returns.appendleft(gamma * disc_return_t + rewards[t])
        
        # standardization of the returns is employed to make training more stable
        eps = np.finfo(np.float32).eps.item()
        # eps is the smallest representable float, which is 
        # added to the standard deviation of the returns to avoid numerical instabilities
        returns = torch.tensor(returns)
        returns = (returns - returns.mean()) / (returns.std() + eps)
        
        # Line 7: policy_loss = []
        policy_loss = []
        for log_prob, disc_return in zip(saved_log_probs, returns):
            policy_loss.append(-log_prob * disc_return)  # G(tau)
        
        policy_loss = torch.cat(policy_loss).sum()
        
        # Line 8: PyTorch prefers gradient descent
        optimizer.zero_grad()
        policy_loss.backward()
        optimizer.step()
        
        if i_episode % print_every == 0:
            print('Episode {}\tAverage Score: {:.2f}'.format(i_episode, np.mean(scores_deque)))
    return scores

目录

  1. 策略学习方法
  2. 策略学习 vs 价值学习
  3. 策略梯度方法
  4. 目标函数
  5. 策略梯度定理
  6. 证明过程
  7. 蒙特卡洛 MC Reinforce 算法
  8. 策略梯度方法流程:
  9. 实现
  10. Reinforce 算法的改进:使用 Gt 替代准确的 R(τ)
  11. 参数化策略代码
  12. Reinforce 训练代码
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • ToDesk、顺网云与海马云部署 DeepSeek 实测对比
  • 本地部署 Llama3:使用 Ollama 与 AnythingLLM 快速搭建私有化 AI 助手
  • AI Agent 实战指南:从零搭建生产级框架与核心实现
  • SQLSugar 封装原理详解:架构与核心模块底层实现
  • Linux 基础:yum 包管理与 vim 编辑器使用
  • Spring Boot ResponseEntity 响应处理与文件下载实战
  • Eino ADK 核心 Agent 解析:ChatModelAgent 原理与实战
  • Windows 安装 OpenClaw 并配置 Qwen 及 Ollama 本地模型接入飞书机器人
  • Java 使用 MemCachedClient 遍历 Memcached 所有 Key 的方法
  • 前端请求后端 404/405/500 状态码排查与解决指南
  • ChatGPT 文本与数据结构化方法全解析
  • whisper.cpp 高性能语音识别推理实现
  • Spring AI 工具回调开发实战:文件操作、联网搜索与 PDF 生成
  • DCU BW1000 环境下 llama.cpp 推理 Qwen3-Coder 模型问题排查
  • whisper.cpp 完整使用指南:从安装到高级配置
  • 本地 AI 服务远程管理难题与加密隧道解决方案
  • MISRA C++静态分析报告解读与实战指南
  • SparkAi 渐进式 AIGC 系统:多模型集成与私有化部署
  • SQL Server 2025 数据库安装图文教程
  • Unix AI 发布第三代 Panther 机器人,聚焦真实场景交付能力

相关免费在线工具

  • 加密/解密文本

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