PyTorch强化学习实战(27)——进化策略在强化学习中的应用

发布时间:2026/10/2 2:03:03

PyTorch强化学习实战(27)——进化策略在强化学习中的应用 PyTorch强化学习实战27——进化策略在强化学习中的应用0. 前言1. 黑盒优化方法2. 进化策略3. 在 CartPole 环境中实现进化策略小结系列链接0. 前言在本节中我们将改变对强化学习 (Reinforcement Learning, RL) 训练的视角转而讨论黑盒优化方法它们在大规模RL问题中具有适用性并能与价值迭代和策略梯度方法竞争。尽管存在时间较长这类方法在某些情境下仍然更具效率。具体而言本节将介绍黑盒优化方法进化策略。1. 黑盒优化方法首先我们探讨整个黑盒方法类别及其与其他方法的区别。黑盒优化方法是解决优化问题的通用途径它将待优化目标视为黑盒无需考虑可微性、价值函数、目标平滑度等任何假设。这类方法唯一的要求是能够计算适应度函数该函数应能评估当前优化实体特定实例的适用性。此类方法中最简单的例子是随机搜索随机采样寻找目标(在强化学习 (Reinforcement Learning, RL) 中即策略π ( a ∣ s ) π(a|s)π(a∣s))检验该候选方案的适应度若结果足够好(符合某些奖励标准)则完成优化否则持续重复此过程。尽管这种方法简单甚至略显朴素——尤其与复杂方法相比——但它能很好地阐释黑盒方法的核心思想。更重要的是通过一些改进这种简单方法在效率与最终策略质量方面可与深度深度Q网络 (Deep Q-Network, DQN) 和策略梯度方法相媲美。此外黑盒方法还具有若干显著优势速度快速度至少比基于梯度的方法快两倍因为无需执行反向传播计算梯度对优化目标和策略的假设非常少对被视为黑盒的优化目标和策略几乎不做任何假设传统方法难以处理奖励函数非平滑或策略包含随机选择步骤的情况而这对黑盒方法完全不构成问题因为它们对黑盒内部机制没有要求易于并行化例如前述随机搜索能轻松扩展到数千个中央处理器 (Central Processing Unit,CPU) 或图形处理器 (Graphics Processing Unit,GPU) 并行工作且彼此间无任何依赖。相比之下DQN或策略梯度方法需要累积梯度并将当前策略传播至所有并行工作节点这会降低并行效率前述方法的主要缺点通常是样本效率较低。特别是对于参数规模达50万的神经网络策略而言朴素随机搜索的成功概率极低。2. 进化策略进化策略 (Evolution Strategies,ES) 是黑盒优化方法的一个子集其灵感源于进化过程。在ES中最成功的个体对整体搜索方向具有最大影响力。该类包含多种不同方法本节我们将重点讨论Salimans等人于2017年发表的论文《Evolution strategies as a scalable alternative to reinforcement learning》中采用的方法。ES方法的基本思想是在每次迭代中对当前策略参数执行随机扰动并评估所得策略的适应度函数值。然后根据相对适应度函数值按比例调整策略权重。Salimans等人采用的具体方法称为协方差矩阵自适应进化策略 (Covariance Matrix Adaptation Evolution Strategy,CMA-ES)。该方法通过从均值为零、方差为单位矩阵的正态分布中采样随机噪声作为扰动计算原始策略权重加上缩放噪声后的新策略适应度函数值随后根据所得值调整原始策略权重——将噪声乘以适应度函数值后加至原权重使策略向适应度函数值更高的权重方向移动。为了提高稳定性权重的更新通过对包含不同随机噪声的批次步骤取平均值来实现。更形式化地该方法可表述为以下步骤初始化学习率α αα、噪声标准差σ σσ和初始策略参数 0 _00​对于t 0, 1, … 循环执行从均值为0、方差为1的正态分布中采样与权重形状相同的噪声批次ε 1 , … , ε n ∼ N ( 0 , 1 ) ε_1, …, ε_n\sim N(0, 1)ε1​,…,εn​∼N(0,1)计算返回值F i F ( θ t σ ε i ) F_i F(θ_t σε_i)Fi​F(θt​σεi​)其中i 1 , … , n i 1, …, ni1,…,n更新权重θ t 1 ← θ t α 1 n σ ∑ i 1 n F i ε i \theta_{t1}\leftarrow\theta_t\alpha\frac 1{n\sigma}\sum_{i1}^nF_iε_iθt1​←θt​αnσ1​i1∑n​Fi​εi​该算法是论文所述方法的核心但正如RL领域的常见情况仅靠算法本身不足以获得良好结果。因此论文还包含若干改进技巧但核心思想保持不变。3. 在 CartPole 环境中实现进化策略接下来我们在CartPole环境中实现并测试论文中的方法。完整代码参见 cartpole_es.py。本节将使用单一环境来检验扰动后网络权重的适应度。我们的适应度函数将采用回合的未折扣总奖励。(1)首先导入必要的库importgymnasiumasgymimporttimeimportnumpyasnpimporttypingasttimporttorchimporttorch.nnasnnfromtorch.utils.tensorboard.writerimportSummaryWriterimportcommon由于完全不执行反向传播我们不需要使用PyTorch优化器。事实上我们完全可以避免使用PyTorch而仅依赖NumPy因为使用PyTorch的唯一目的是执行前向传播和计算网络输出。(2)接下来定义超参数MAX_BATCH_EPISODES100MAX_BATCH_STEPS10000NOISE_STD0.001LEARNING_RATE0.001TNoisett.List[torch.Tensor]超参数数量也很少包含以下值MAX_BATCH_EPISODES和MAX_BATCH_STEPS训练使用的回合数和步数上限NOISE_STD用于权重扰动的噪声标准差σ σσLEARNING_RATE训练步骤中调整权重的系数我们还为包含权重噪声的张量列表定义了类型别名这将简化代码处理噪声的逻辑。(3)定义网络classNet(nn.Module):def__init__(self,obs_size:int,action_size:int):super(Net,self).__init__()self.netnn.Sequential(nn.Linear(obs_size,32),nn.ReLU(),nn.Linear(32,action_size),nn.Softmax(dim1))defforward(self,x:torch.Tensor)-torch.Tensor:returnself.net(x)我们使用的模型是一个简单的单隐藏层神经网络它根据观测状态给出要采取的动作。此处使用PyTorch神经网络模块仅出于便利性考虑因为我们只需要前向传播过程但这完全可以被矩阵乘法和非线性变换所替代。(3)evaluate()函数使用给定策略运行完整回合并返回总奖励和步数defevaluate(env:gym.Env,net:nn.Module,get_max_action:boolTrue,device:torch.devicetorch.device(cpu))-tt.Tuple[float,int]:obs,_env.reset()reward0.0steps0whileTrue:obs_vtorch.FloatTensor(np.expand_dims(obs,0)).to(device)act_vnet(obs_v)ifget_max_action:actact_v.max(dim1)[1].data.numpy()[0]else:actact_v.data.cpu().numpy()[0]obs,r,done,is_tr,_env.step(act)rewardr steps1ifdoneoris_tr:breakreturnreward,steps奖励值将作为适应度值使用而步数计数用于限制我们组建批次所花费的时间。动作选择通过计算网络输出的argmax以确定性方式执行。原则上我们可以从分布中进行随机采样但通过对网络参数添加噪声已经实现了探索过程因此这里使用确定性动作选择是可行的。(4)在sample_noise()函数中我们创建与网络参数形状相同的零均值单位方差随机噪声defsample_noise(net:nn.Module,device:torch.devicetorch.device(cpu))-tt.Tuple[TNoise,TNoise]:pos[]neg[]forpinnet.parameters():noisenp.random.normal(sizep.data.size())pos.append(torch.FloatTensor(noise).to(device))neg.append(torch.FloatTensor(-noise).to(device))returnpos,neg该函数返回两组噪声张量一组为正噪声另一组为相同随机值但取负号。这两个样本将作为独立样本在批次中使用。这种技术称为镜像采样用于提高收敛稳定性。事实上若没有负噪声收敛会变得非常不稳定因为正噪声会将权重推向单一方向。(5)eval_with_noise()函数接收由sample_noise()创建的噪声数组并评估添加噪声后的网络表现defeval_with_noise(env:gym.Env,net:nn.Module,noise:TNoise,noise_std:float,get_max_action:boolTrue,device:torch.devicetorch.device(cpu))-tt.Tuple[float,int]:old_paramsnet.state_dict()forp,p_ninzip(net.parameters(),noise):p.datanoise_std*p_n r,sevaluate(env,net,get_max_actionget_max_action,devicedevice)net.load_state_dict(old_params)returnr,s为实现这一目标我们将噪声添加到网络参数中并调用evaluate函数获取奖励值和所采取步数。此后需要通过加载网络的状态字典将权重恢复至原始状态。(6)该方法最后也是核心的函数是train_step()它接收包含噪声和对应奖励的批次并通过以下公式计算网络参数的更新θ t 1 ← θ t α 1 n σ ∑ i 1 n F i ε i \theta_{t1}\leftarrow\theta_t\alpha\frac 1{n\sigma}\sum_{i1}^nF_iε_iθt1​←θt​αnσ1​i1∑n​Fi​εi​具体实现如下deftrain_step(net:Net,batch_noise:tt.List[common.TNoise],batch_reward:tt.List[float],writer:SummaryWriter,step_idx:int):weighted_noiseNonenorm_rewardnp.array(batch_reward)norm_reward-np.mean(norm_reward)snp.std(norm_reward)ifabs(s)1e-6:norm_reward/s首先我们对奖励进行归一化处理(使其具有零均值和单位方差)这有助于提升方法的稳定性。接着遍历批次中的每对(噪声奖励)数据将噪声值与归一化后的奖励相乘并对策略中每个参数的对应噪声进行累加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[]forp,p_updateinzip(net.parameters(),weighted_noise):updatep_update/(len(batch_reward)*NOISE_STD)p.dataLEARNING_RATE*update m_updates.append(torch.norm(update))writer.add_scalar(update_l2,np.mean(m_updates),step_idx)从技术角度看我们执行的是梯度上升操作尽管梯度并非通过反向传播获得而是通过随机采样(也称为蒙特卡洛采样)得到。Salimans等人也证实了这一事实他们指出CMA-ES与策略梯度方法非常相似区别仅在于获取梯度估计的方式。(7)创建环境和网络if__name____main__:writerSummaryWriter(comment-cartpole-es)envgym.make(CartPole-v1)netNet(env.observation_space.shape[0],env.action_space.n)print(net)**(8)**训练循环的每次迭代从创建批次开始我们在此过程中采样噪声并获取正向和负向噪声对应的奖励step_idx0whileTrue:t_starttime.time()batch_noise[]batch_reward[]batch_steps0for_inrange(MAX_BATCH_EPISODES):noise,neg_noisecommon.sample_noise(net)batch_noise.append(noise)batch_noise.append(neg_noise)reward,stepscommon.eval_with_noise(env,net,noise,NOISE_STD)batch_reward.append(reward)batch_stepssteps reward,stepscommon.eval_with_noise(env,net,neg_noise,NOISE_STD)batch_reward.append(reward)batch_stepsstepsifbatch_stepsMAX_BATCH_STEPS:break当达到批次中的回合数上限或总步数上限时我们停止收集数据并执行训练更新。**(9)**为了执行网络的更新调用train_step()函数step_idx1m_rewardfloat(np.mean(batch_reward))ifm_reward199:print(Solved in %d steps%step_idx)breaktrain_step(net,batch_noise,batch_reward,writer,step_idx)train_step()函数的目标是根据总奖励对噪声进行缩放然后沿着平均噪声的方向调整策略权重。**(10)**训练循环中的最后指标写入TensorBoard并在控制台显示训练进度writer.add_scalar(reward_mean,m_reward,step_idx)writer.add_scalar(reward_std,np.std(batch_reward),step_idx)writer.add_scalar(reward_max,np.max(batch_reward),step_idx)writer.add_scalar(batch_episodes,len(batch_reward),step_idx)writer.add_scalar(batch_steps,batch_steps,step_idx)speedbatch_steps/(time.time()-t_start)writer.add_scalar(speed,speed,step_idx)print(%d: reward%.2f, speed%.2f f/s%(step_idx,m_reward,speed))直接运行程序(无需参数)即可开始训练$ python3 cartpole_es.pyES通常需要40-60个批次才能解决CartPole问题。上述运行的收敛动态如下图所示可以看到智能体能够在30秒内解决环境问题这与交叉熵方法性能相当。小结本节介绍了进化策略 (Evolution Strategies,ES) 这一黑盒优化方法在强化学习中的应用。与传统梯度方法不同ES通过对策略参数添加随机噪声并评估适应度来估计更新方向无需计算梯度因此具有速度快、假设少、易于并行化等优势。我们在CartPole环境中实现了镜像采样与奖励归一化等改进技巧实验表明ES能够在30秒内稳定解决该任务效率与交叉熵方法相当。系列链接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——提升随机策略梯度稳定性
延伸阅读

更多相关文章

2026/10/2 2:03:03

电赛智能送药小车硬件全解析:主控、驱动与抗干扰实战经验

作为一个带队参加过三届电赛的老油条,21年这道智能送药小车的控制类题目,说实话,难度不算顶天,但极其考验团队的硬件基本功和系统稳定性。当年我们实验室两支队伍都选了这道题,最后成绩却差了一截,拉开的差…

2026/10/2 2:03:03

纯CSS美食网站源码拆解:从布局到动效的完整实战指南

简介:基于CSS的美食网站设计源码是一套面向网页设计初学者的完整前端练习项目,核心价值在于用纯HTML与CSS搭建一个展示美食信息、兼顾视觉与交互体验的静态站点。压缩包共21个文件,体积786KB,包含4个CSS样式表、2个HTML页面、1个P…

2026/10/2 2:53:06

GMSK仿真全链路解析:原理、MATLAB实现与误码率避坑

简介:一份基于MATLAB的GMSK调制解调仿真报告,面向无线通信、信号处理方向的在校学生、课程设计人员及工程师,用于理解GMSK原理并掌握仿真实现方法。报告以GSM系统为背景,系统讲述GMSK作为连续相位调制的特点,重点分析高…

2026/10/2 2:53:06

软件工程论文排版总被打回?智能排版把格式整理从两天缩到一小时

写过软件工程毕业论文的人都懂那种绝望:代码截图对不齐、图表编号全乱、页眉奇偶页不同、参考文献格式被导师打回三次。内容早就写完了,排版却耗掉整整两天,而且每次改动正文,编号又得全部重来一遍。软工论文尤其惨——光是代码清…

2026/10/2 2:53:06

电脑没声音?Windows Audio服务0005与Realtek声卡排查全攻略

前阵子有个用华硕Z370-A主板的读者给我留言,说系统重装之后右下角的小喇叭变成了红叉,控制面板里的Realtek面板也打不开,折腾了一晚上都没声音。我远程一看,问题不在声卡,也不在驱动,而是Windows Audio服务…

2026/10/2 2:53:06

苍穹外卖day08提交订单:事务、多表写入与数据一致性实战解析

做了快十年的Java开发,带新人的时候总会遇到一个经典项目叫苍穹外卖。很多自学Java的朋友,从环境配置一路撸到购物车,前面都顺风顺水,结果一走到第8天的提交订单,就开始各种卡壳。这个模块在技术上不算难,但…

2026/10/2 2:53:06

基于Hadoop的电影推荐系统:伪分布式搭建与ALS协同过滤实战

简介:这份资源是基于Hadoop框架构建的电影推荐系统完整项目包,面向具备Java基础、希望实践大数据分布式计算与个性化推荐算法的开发者与学习者。项目以HDFS存储用户行为与评分数据,通过MapReduce完成数据清洗、相似度计算与推荐生成&#xff…

2026/10/2 2:48:06

单目3D目标检测与BEV可视化:Python源码实战指南

简介:一套基于Python实现的单目2D和3D目标检测及BEV可视化源码包,面向高校毕业设计、课程设计与项目开发场景,适合具备一定Python基础的学生、教师及科研人员学习借鉴。资源共包含70个文件,以46个Python源码文件为核心&#xff0c…

2026/10/1 5:21:14

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/10/1 17:09:46

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 10:48:55

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/2 0:02:57

PWN入门:从栈溢出原理到ROP链实战

1. 这不是“学PWN”,是重新理解你每天敲的每一行C代码我第一次在CTF赛场上写出能控制程序流的exp时,手抖得连gdb的c命令都输错三次。那道题只有23行C代码,一个gets()调用,一个printf(),一个return——它甚至没开NX&…

2026/10/2 0:02:57

Windows下cudaMallocHost显存占用之谜:WDDM与TCC模式差异及优化方案

1. 一个反直觉的显存占用现象第一次在 Windows 上看到cudaMallocHost把显存吃掉的时候,我的反应是打开任务管理器反复确认了三遍。明明调用的是主机端锁页内存分配,按 CUDA 文档的说法,这块内存应该落在系统 RAM 里,跟 GPU 的显存…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑