PyTorch强化学习实战——分布式策略梯度

PyTorch强化学习实战------分布式策略梯度

    • [0. 前言](#0. 前言)
    • [1. 分布式策略梯度](#1. 分布式策略梯度)
    • [2. 架构设计](#2. 架构设计)
    • [3. 算法实现](#3. 算法实现)
    • [4. 结果](#4. 结果)
    • 相关链接

0. 前言

深度确定性策略梯度 (Deep Deterministic Policy Gradient, DDPG)虽然在连续控制任务上取得了比优势演员-评论家 (Advantage Actor-Critic, A2C) 方法更优的效果,但其训练稳定性仍有提升空间。本节将介绍分布式分布深度确定性策略梯度 (Distributed Distributional Deep Deterministic Policy Gradient, D4PG) 算法,它从四个关键维度对 DDPG 进行了改进:用概率分布替代评论家的单一Q值输出,引入 n 步贝尔曼方程加速收敛,采用优先经验回放提升样本效率,并简化探索机制。这些改进使 D4PG 在四足机器人任务上的平均奖励从 DDPG4.5 跃升至近 18,性能提升近 4 倍。本文将解析 D4PG 的核心设计原理与实现细节。

1. 分布式策略梯度

在本节中,我们将探讨 Barth-Maron 等人 2018 年发表的《Distributed distributional deterministic policy gradients》论文,论文中提出了分布式分布深度确定性策略梯度 (Distributed Distributional Deep Deterministic Policy Gradient, D4PG) 方法。作者针对深度确定性策略梯度 (Deep Deterministic Policy Gradient, DDPG)方法提出多项改进以提升稳定性、收敛性和样本效率:

  • 首先,采用了 Bellemare 等人中提出的Q值分布式表示,核心思想是用概率分布替代评论家的单一Q值,贝尔曼方程被贝尔曼算子取代(以类似方式转换分布表示)
  • 第二项改进是使用n 步贝尔曼方程(通过展开加速收敛)
  • 与原始 DDPG 方法的另一区别是使用优先回放缓冲池替代均匀采样缓冲池

2. 架构设计

分布式分布深度确定性策略梯度 (Distributed Distributional Deep Deterministic Policy Gradient, D4PG) 与深度确定性策略梯度 (Deep Deterministic Policy Gradient, DDPG)最显著的差异在于评论家的输出:不再返回给定状态和动作的单一Q值,而是返回 N_ATOMS 个值(对应预定义范围内值的概率分布)。代码使用 N_ATOMS=51,分布范围 Vmin=-10Vmax=10,因此评论家返回 51 个数字,表示折扣奖励落在区间边界 [-10, -9.6, -9.2, ..., 9.6, 10] 内各个区段的概率。

D4PGDDPG 的另一区别是探索机制:DDPG 使用 OU 过程进行探索,但 D4PG 作者表示经过实验表明 OU 和简单随机噪声添加两种方式结果相同。因此论文最终采用更简单的探索方法。

最后一项重要差异涉及训练过程------D4PG 使用交叉熵损失计算两个概率分布之间的差异(一个来自评论家输出,另一个通过贝尔曼算子获得)。为使两个分布对齐到相同的支撑原子,采用与原论文相同的分布投影方法。

3. 算法实现

完整源代码位于train_d4pg.py、model.py 和 common.py

(1) 我们首先从模型类开始。演员网络 (actor) 结构与 DDPG 完全一致,因此训练过程中直接使用 DDPGActor 类。评论家网络隐藏层规模和数量保持不变,但输出层不再是单个数值,而是生成 N_ATOMS 个值:

python 复制代码
class D4PGCritic(nn.Module):
    def __init__(self, obs_size: int, act_size: int,
                 n_atoms: int, v_min: float, v_max: float):
        super(D4PGCritic, self).__init__()

        self.obs_net = nn.Sequential(
            nn.Linear(obs_size, 400),
            nn.ReLU(),
        )

        self.out_net = nn.Sequential(
            nn.Linear(400 + act_size, 300),
            nn.ReLU(),
            nn.Linear(300, n_atoms)
        )

        delta = (v_max - v_min) / (n_atoms - 1)
        self.register_buffer("supports", torch.arange(v_min, v_max + delta, delta))

(2) 我们还创建了一个包含奖励支撑的 PyTorch 辅助缓冲区,用于从概率分布获取单一平均Q值:

python 复制代码
    def forward(self, x: torch.Tensor, a: torch.Tensor):
        obs = self.obs_net(x)
        return self.out_net(torch.cat([obs, a], dim=1))

    def distr_to_q(self, distr: torch.Tensor):
        weights = F.softmax(distr, dim=1) * self.supports
        res = weights.sum(dim=1)
        return res.unsqueeze(dim=-1)

可以看到,softmax() 应用并非网络 forward() 方法的一部分,因为我们将在训练中使用更稳定的 log_softmax() 函数。因此当需要获取实际概率时,需额外应用 softmax()

(3) D4PG 的智能体类更为简单(无需状态跟踪):

python 复制代码
class AgentD4PG(lib.agent.BaseAgent):
    """
    Agent implementing noisy agent
    """
    def __init__(self, net: DDPGActor, device: torch.device = torch.device("cpu"),
                 epsilon: float = 0.3):
        self.net = net
        self.device = device
        self.epsilon = epsilon

    def __call__(self, states: lib.agent.States, agent_states: lib.agent.AgentStates):
        states_v = lib.agent.float32_preprocessor(states)
        states_v = states_v.to(self.device)
        mu_v = self.net(states_v)
        actions = mu_v.data.cpu().numpy()
        actions += self.epsilon * np.random.normal(size=actions.shape)
        actions = np.clip(actions, -1, 1)
        return actions, agent_states

(4) 对于每个需转换为动作的状态,智能体应用演员网络并向动作添加高斯噪声(按 epsilon 值缩放)。训练代码使用以下超参数:

python 复制代码
GAMMA = 0.99
BATCH_SIZE = 64
LEARNING_RATE = 1e-4
REPLAY_SIZE = 100000
REPLAY_INITIAL = 10000
REWARD_STEPS = 5

TEST_ITERS = 1000

Vmax = 10
Vmin = -10
N_ATOMS = 51
DELTA_Z = (Vmax - Vmin) / (N_ATOMS - 1)

本节使用了较小的 10 万条回放缓存(效果良好)。作者在 D4PG 论文中使用了 100 万条转移数据。缓存预先填充来自环境的 1 万个样本后开始训练。

(5) 每次训练循环中,训练评论家和演员。差异在于评论家损失的计算方式:

python 复制代码
                batch = buffer.sample(BATCH_SIZE)
                states_v, actions_v, rewards_v, dones_mask, last_states_v = \
                    common.unpack_batch_ddqn(batch, device)

                # train critic
                crt_opt.zero_grad()
                crt_distr_v = crt_net(states_v, actions_v)
                last_act_v = tgt_act_net.target_model(last_states_v)
                last_distr_v = F.softmax(
                    tgt_crt_net.target_model(last_states_v, last_act_v), dim=1)

(6) 在评论家训练的第一步,我们要求其返回状态和已执行动作的概率分布。该概率分布将作为交叉熵损失计算的输入。为了得到目标概率分布,我们需要从批次中最后的状态计算概率分布,然后执行分布的贝尔曼投影 (Bellman projection):

python 复制代码
                proj_distr = distr_projection(
                    last_distr_v.detach().cpu().numpy(), rewards_v.detach().cpu().numpy(),
                    dones_mask.detach().cpu().numpy(), gamma=GAMMA**REWARD_STEPS)
                proj_distr_v = torch.tensor(proj_distr).to(device)

(7)投影函数稍显复杂,简单来说,该函数通过对最后状态概率分布进行变换实现,根据即时奖励进行偏移并按折扣因子缩放。最终得到的就是我们希望网络生成的目标概率分布。由于 PyTorch 没有通用的交叉熵损失函数,我们通过将输入概率的对数与目标概率相乘来计算损失值:

python 复制代码
                prob_dist_v = -F.log_softmax(crt_distr_v, dim=1) * proj_distr_v
                critic_loss_v = prob_dist_v.sum(dim=1).mean()
                critic_loss_v.backward()
                crt_opt.step()

(8) 演员的训练与 DDPG 方法唯一的区别在于使用模型的 distr_to_q() 方法,通过支撑原子点将概率分布转换为单一的平均Q值:

python 复制代码
                act_opt.zero_grad()
                cur_actions_v = act_net(states_v)
                crt_distr_v = crt_net(states_v, cur_actions_v)
                actor_loss_v = -crt_net.distr_to_q(crt_distr_v)
                actor_loss_v = actor_loss_v.mean()
                actor_loss_v.backward()
                act_opt.step()

4. 结果

D4PG 方法在收敛速度和奖励获取方面表现优异,其平均测试奖励能够达到 17.912。而且这个结果还有提升空间,因为步数计数低于 1000 (环境的时间限制),意味着模型因内部环境检查而提前终止。下图展示了训练与测试指标:

比较优势演员-评论家 (Advantage Actor-Critic, A2C) 方法深度确定性策略梯度 (Deep Deterministic Policy Gradient, DDPG)D4PG 方法,下图展示了三种方法的测试集指标:

要查看模型的实际运行效果,可以使用 play_ddpg.py (因为演员网络结构与 DDPG 相同)。

相关链接

PyTorch强化学习实战(1)------强化学习(Reinforcement Learning,RL)详解

PyTorch强化学习实战(2)------强化学习环境库Gymnasium

PyTorch强化学习实战(3)------Gymnasium API扩展功能

PyTorch强化学习实战(4)------PyTorch基础

PyTorch强化学习实战(5)------PyTorch Ignite 事件驱动机制与实践

PyTorch强化学习实战(6)------交叉熵方法详解与实现

PyTorch强化学习实战(7)------表格学习与贝尔曼方程

PyTorch强化学习实战(8)------Q学习详解与实现

PyTorch强化学习实战(9)------深度Q学习

PyTorch强化学习实战(10)------强化学习高级组件

PyTorch强化学习实战(11)------N步DQN(N-step DQN)

PyTorch强化学习实战(12)------Double DQN(DDQN)

PyTorch强化学习实战(13)------噪声网络(NoisyNet-DQN)

PyTorch强化学习实战(14)------优先经验回放机制

PyTorch强化学习实战(15)------Dueling DQN

PyTorch强化学习实战(16)------Categorical DQN

PyTorch强化学习实战(17)------强化学习训练加速

PyTorch强化学习实战(18)------基于DQN处理股票交易问题

PyTorch强化学习实战(19)------策略梯度法

PyTorch强化学习实战(20)------优势演员-评论家(Advantage Actor-Critic, A2C)

PyTorch强化学习实战(21)------异步优势演员-评论家(Asynchronous Advantage Actor-Critic, A3C)

PyTorch强化学习实战(22)------将强化学习应用于TextWorld互动小说游戏

PyTorch强化学习实战(23)------强化学习在网页导航中的应用

PyTorch强化学习实战(24)------连续动作空间中的强化学习

PyTorch强化学习实战(25)------深度确定性策略梯度(DDPG)

相关推荐
qq7422349841 小时前
OpenCV 之外的另一半工具箱:Supervision 视觉工程实战
人工智能·opencv·计算机视觉
doiito(Do It Together)1 小时前
【Agent Harness】Gliding Horse 最新进化:从“能学习”到“可验证的自主进化”
人工智能·rust·系统架构·开源
weixin_511840471 小时前
2026年9月19日 NVIDIA H200 企业级AI服务器学习
人工智能
wshzd1 小时前
LLM之Agent(八十五)|PI(二十四)RPC 模式与 JSON 事件流
人工智能
禁默1 小时前
没有公网 IP 怎么远程抓取服务器指标?node_exporter + Prometheus + cpolar 实战
人工智能·cpolar
汽车网络安全爱好者1 小时前
AI应用(四)之 AI 编程全流程
大数据·人工智能·elasticsearch
PPIO派欧云1 小时前
PPIO沙箱支持接入OpenAI Agents API,一键托管Agent Harness
人工智能
阿里云大数据AI技术1 小时前
千问 APP × 阿里云:MaxCompute 向量检索重构 RAG 数据收录评估链路,一条SQL将性能提速 11 倍
人工智能·阿里云·maxcompute·rag·千问
智慧物业老杨6 小时前
物业数字化落地思考:真正的转型,是底层数据秩序的重构
java·大数据·人工智能·微服务·系统架构