资讯详情

PyTorch强化学习实战——进化策略的高效并行化

📅 2026/10/9 2:04:57 | 华诺云谱 👁 阅读
PyTorch强化学习实战——进化策略的高效并行化
PyTorch强化学习实战——进化策略的高效并行化0. 前言1. 共享种子2. 在 HalfCheetah 环境中实现进化策略3. 运行结果相关链接0. 前言进化策略 (Evolution Strategies, ES) 的核心瓶颈在于训练批次的收集速度——每次迭代需采样大量噪声并评估对应策略的适应度。传统并行化方案要求工作节点向主节点传输完整的噪声向量(规模与策略参数相同)通信开销巨大。Salimans等人提出的“共享种子”策略巧妙解决了这一问题工作节点仅需发送用于生成噪声的随机种子主节点即可通过相同的伪随机数生成器重建噪声大幅降低通信负载。本节将在HalfCheetah环境中实现这一并行化方案并探讨中心化排序变换、优化器使用等关键技术细节。1. 共享种子在本节中我们将研究如何使用Salimans等人提出的共享种子 (shared seed) 策略高效地并行化进化策略方法。为演示此方法我们将使用 MuJoCo 物理仿真器的 HalfCheetah 环境。首先我们讨论共享种子的概念。进化策略 (Evolution Strategies, ES) 算法的性能主要取决于我们收集训练批次的速度包含噪声采样和扰动噪声总奖励评估。由于我们的训练批次项是独立的因此我们可以轻松地将这一步骤并行化到大量的工作节点上(这些工作节点可以是远程机器上的进程)。这类似于从异步优势演员-评论家 (Asynchronous Advantage Actor-Critic, A3C) 工作节点收集梯度。然而直接实现这种并行化需要从工作进程向中央主节点传输大量数据而主节点负责合并工作节点检验的噪声并执行策略更新。这些数据主要是噪声向量其大小等于策略参数的规模。为了避免此开销Salimans等人提出了一个非常巧妙的解决方案由于工作节点上的噪声由伪随机数生成器产生(允许通过设置随机种子重现随机序列)工作节点只需向主节点传输用于生成噪声的种子值主节点即可利用该种子重新生成相同的噪声向量。当然每个工作节点的种子仍需随机生成以保持优化过程的随机性。这种方法极大减少了从工作节点到主节点的数据传输量显著提升了方法的可扩展性。在本节中我们将使用相同方法实现本地并行化。2. 在 HalfCheetah 环境中实现进化策略完整代码位于 cheetah_es.py 中代码与 CartPole 版本存在大量相同部分我们将仅重点讨论差异部分。首先从工作进程 (worker) 开始该进程通过PyTorch多进程包装器以独立进程方式启动。工作进程的职责很简单每次迭代时从主进程获取网络参数然后执行固定次数的噪声采样和奖励评估。带有随机种子的结果数据通过队列发送给主进程。(1)以下数据类用于工作进程向主进程发送扰动策略评估结果dataclass(frozenTrue)classRewardsItem:seed:intpos_reward:floatneg_reward:floatsteps:int该数据类包含随机种子、正负噪声对应的奖励值以及两次测试中执行的总步数。(2)在每次训练迭代中工作进程等待主进程广播网络参数defworker_func(params_queue:mp.Queue,rewards_queue:mp.Queue,device:torch.device,noise_std:float):envmake_env()netNet(env.observation_space.shape[0],env.action_space.shape[0]).to(device)net.eval()whileTrue:paramsparams_queue.get()ifparamsisNone:breaknet.load_state_dict(params)值为None表示主进程要求停止工作进程。(3)其余部分几乎与 CartPole 版本相同主要的区别在于噪声生成之前生成并分配的随机种子。这使得主进程仅通过种子就能重新生成相同的噪声for_inrange(ITERS_PER_UPDATE):seednp.random.randint(low0,high65535)np.random.seed(seed)noise,neg_noisecommon.sample_noise(net,devicedevice)pos_reward,pos_stepscommon.eval_with_noise(env,net,noise,noise_std,get_max_actionFalse,devicedevice)neg_reward,neg_stepscommon.eval_with_noise(env,net,neg_noise,noise_std,get_max_actionFalse,devicedevice)rewards_queue.put(RewardsItem(seedseed,pos_rewardpos_reward,neg_rewardneg_reward,stepspos_stepsneg_steps))(4)另一个区别在于主进程执行训练步骤时使用的函数deftrain_step(optimizer:optim.Optimizer,net:Net,batch_noise:tt.List[common.TNoise],batch_reward:tt.List[float],writer:SummaryWriter,step_idx:int,noise_std:float):weighted_noiseNonenorm_rewardcompute_centered_ranks(np.array(batch_reward))在 CartPole 示例中我们通过减去均值并除以标准差来归一化奖励批次。根据Salimans等人的研究使用排序值而非实际奖励能获得更好结果。由于ES对适应度函数(本节中即奖励)没有假设我们可以对奖励进行任意调整——这在深度Q网络 (Deep Q-Network, DQN) 等方法中是不可能的。此处的数组排序变换是指用排序后的索引值替换原数组。例如数组[0.1, 10, 0.5]将获得排序数组[0, 2, 1]。compute_centered_ranks函数接收批次总奖励数组计算每个元素的排序值然后对这些排序值进行归一化。例如输入数组[21.0, 5.8, 7.0]将获得排序值[2, 0, 1]最终中心化排序值为[0.5, -0.5, 0.0]。(5)训练函数中的另一个主要区别是使用了PyTorch优化器fornoise,rewardinzip(batch_noise,norm_reward):ifweighted_noiseisNone:weighted_noise[reward*p_nforp_ninnoise]else:forw_n,p_ninzip(weighted_noise,noise):w_nreward*p_n m_updates[]optimizer.zero_grad()forp,p_updateinzip(net.parameters(),weighted_noise):updatep_update/(len(batch_reward)*noise_std)p.grad-update m_updates.append(torch.norm(update))writer.add_scalar(update_l2,np.mean(m_updates),step_idx)optimizer.step()接下来解释为何使用优化器以及如何在无需反向传播的情况下实现这一点。首先Salimans等人研究表明ES算法使用的优化方法非常类似于对适应度函数的梯度上升区别在于梯度的计算方式。随机梯度下降 (Stochastic Gradient Descent,SGD) 方法通常通过计算网络参数对损失值的导数来从损失函数获取梯度这要求网络和损失函数必须可微分——但并非总是如此例如ES方法执行的排序变换就不可微分。另一方面ES执行的优化采用不同方式我们通过添加噪声来随机采样当前参数邻域并计算适应度函数值。根据适应度函数的变化调整参数从而将参数推向适应度函数更高的方向。其结果与基于梯度的方法非常相似但对适应度函数的要求宽松得多——唯一要求是能够计算函数值。然而如果我们通过随机采样适应度函数来估计某种梯度就可以使用PyTorch的标准优化器。通常优化器利用累积在参数grad字段中的梯度来调整网络参数。这些梯度是在反向传播步骤后累积的但由于PyTorch的灵活性优化器并不关心梯度的来源。因此我们只需将估计的参数更新量(带负号)复制到grad字段中然后要求优化器执行更新。注意更新量需带负号因为优化器通常执行梯度下降(常规操作中我们最小化损失函数)而此处我们需要执行梯度上升。这与演员-评论家方法非常相似当时估计的策略梯度也带负号因其指示了策略改进的方向。(6)代码中最后一部分差异体现在主进程的训练循环中。主进程负责等待工作进程的数据执行参数训练更新并将结果广播给工作进程。主进程与工作进程之间通过两组队列进行通信第一组是每个工作进程专属的队列用于主进程发送当前策略参数第二组是工作进程共享的队列用于发送前述包含随机种子和奖励的RewardItem结构params_queues[mp.Queue(maxsize1)for_inrange(PROCESSES_COUNT)]rewards_queuemp.Queue(maxsizeITERS_PER_UPDATE)workers[]forparams_queueinparams_queues:p_args(params_queue,rewards_queue,device,args.noise_std)procmp.Process(targetworker_func,argsp_args)proc.start()workers.append(proc)print(All started!)optimizeroptim.Adam(net.parameters(),lrargs.lr)在主进程初始阶段我们创建所有队列、启动工作进程并初始化优化器。(7)每次训练迭代开始时首先将网络参数广播给工作进程forstep_idxinrange(args.iters):# broadcasting network paramsparamsnet.state_dict()forqinparams_queues:q.put(params)(8)随后在循环中主进程等待从工作进程获取足够数据t_starttime.time()batch_noise[]batch_reward[]results0batch_steps0whileTrue:whilenotrewards_queue.empty():rewardrewards_queue.get_nowait()np.random.seed(reward.seed)noise,neg_noisecommon.sample_noise(net)batch_noise.append(noise)batch_reward.append(reward.pos_reward)batch_noise.append(neg_noise)batch_reward.append(reward.neg_reward)results1batch_stepsreward.stepsifresultsPROCESSES_COUNT*ITERS_PER_UPDATE:breaktime.sleep(0.01)每当新结果到达时我们使用随机种子重新生成噪声。(9)训练循环的最后一步调用train_step()函数train_step(optimizer,net,batch_noise,batch_reward,writer,step_idx,args.noise_std)函数根据噪声和奖励计算更新量并调用优化器调整权重。3. 运行结果代码支持可选的--dev标志实验表明启用GPU反而会降低速度未使用GPU时平均速度为每秒20-21k次观测而使用CUDA时仅为9k。这看似违反直觉但可以通过网络规模过小和单次观测的批次大小来解释。理论上增大批次规模可能缩小性能差距(甚至获得加速)但这会使代码复杂化。训练过程中我们会显示平均奖励、训练速度(以每秒观测次数计)以及两个时间指标(分别显示收集数据和执行训练步骤所耗时长)$ python3 cheetah_es.py训练动态显示策略在初期快速提升仅经过100次更新智能体就获得了1500-1600分的成绩后续峰值奖励达到2833分但随着训练继续策略性能出现退化。奖励的最大值、均值和标准差如下图所示。相关链接PyTorch强化学习实战1——强化学习Reinforcement LearningRL详解PyTorch强化学习实战2——强化学习环境库GymnasiumPyTorch强化学习实战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步DQNN-step DQNPyTorch强化学习实战12——Double DQNDDQNPyTorch强化学习实战13——噪声网络NoisyNet-DQNPyTorch强化学习实战14——优先经验回放机制PyTorch强化学习实战15——Dueling DQNPyTorch强化学习实战16——Categorical DQNPyTorch强化学习实战17——强化学习训练加速PyTorch强化学习实战18——基于DQN处理股票交易问题PyTorch强化学习实战19——策略梯度法PyTorch强化学习实战20——优势演员-评论家Advantage Actor-Critic, A2CPyTorch强化学习实战21——异步优势演员-评论家Asynchronous Advantage Actor-Critic, A3CPyTorch强化学习实战22——将强化学习应用于TextWorld互动小说游戏PyTorch强化学习实战23——强化学习在网页导航中的应用PyTorch强化学习实战24——连续动作空间中的强化学习PyTorch强化学习实战25——深度确定性策略梯度DDPGPyTorch强化学习实战26——提升随机策略梯度稳定性PyTorch强化学习实战27——进化策略在强化学习中的应用
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑