影响PPO算法性能的10个关键技巧(附PPO算法简洁Pytorch ...
0.引言PPO算法(Proximal Policy Optimization)是目前深度强化学习(DRL)领域,最广泛应用的算法之一。然而才实际应用的过程中,PPO算法的性能却受到多种因素的影响。本文总结了影响PPO算法性能的10个关键技巧,并通过实验结果的对比,来探究各个trick对PPO算法性能的影响。同时,我们将代码开源在了github上,分别提供了PPO算法的离散动作空间实现和连续动作空间实现(见下面github链接中的4.PPO-discrete和5.PPO-continuous(包括了Gaussian分布和Beta分布))
1.PPO算法概述
PPO算法的核心是使用如下策略损失函数:
https://www.zhihu.com/equation?tex=L%5E%7BC+L+I+P%7D%28%5Ctheta%29%3D%5Chat%7B%5Cmathbb%7BE%7D%7D_%7Bt%7D%5Cleft%5B%5Cmin+%5Cleft%28r_%7Bt%7D%28%5Ctheta%29+%5Chat%7BA%7D_%7Bt%7D%2C+%5Coperatorname%7Bclip%7D%5Cleft%28r_%7Bt%7D%28%5Ctheta%29%2C+1-%5Cepsilon%2C+1%2B%5Cepsilon%5Cright%29+%5Chat%7BA%7D_%7Bt%7D%5Cright%29%5Cright%5D%5Ctag%7B1%7D
其中,
https://www.zhihu.com/equation?tex=r_%7Bt%7D%28%5Ctheta%29%3D%5Cfrac%7B%5Cpi_%7B%5Ctheta%7D%5Cleft%28a_%7Bt%7D+%5Cmid+s_%7Bt%7D%5Cright%29%7D%7B%5Cpi_%7B%5Ctheta_%7B%5Cmathrm%7Bold%7D%7D%7D%5Cleft%28a_%7Bt%7D+%5Cmid+s_%7Bt%7D%5Cright%29%7D%5Ctag%7B2%7D
表示新旧策略之间的比率。为一个超参数,用来确保当利用同一批数据进行多次策略更新时,“新旧策略之间的差距不要太大”。一般情况下,我们设置 https://www.zhihu.com/equation?tex=%5Cepsilon%3D0.2 。
(1)式中, https://www.zhihu.com/equation?tex=+%5Chat%7BA%7D_%7Bt%7D 为优势函数的估计,根据PPO的原始论文建议,我们一般使用GAE(generalized advantage estimation)来计算优势函数
https://www.zhihu.com/equation?tex=%5Chat%7BA%7D_%7Bt%7D%5E%7BG+A+E%28%5Cgamma%2C+%5Clambda%29%7D%3D%5Csum_%7Bl%3D0%7D%5E%7B%5Cinfty%7D%28%5Cgamma+%5Clambda%29%5E%7Bl%7D+%5Cdelta_%7Bt%2Bl%7D%5E%7BV%7D%5Ctag%7B3%7D
其中, https://www.zhihu.com/equation?tex=%5Cdelta_%7Bt%7D%5E%7BV%7D为:
https://www.zhihu.com/equation?tex=%5Cdelta_%7Bt%7D%5E%7BV%7D%3Dr_%7Bt%7D%2B%5Cgamma+V_%7B%5Comega%7D%5Cleft%28s_%7Bt%2B1%7D%5Cright%29-V_%7B%5Comega%7D%5Cleft%28s_%7Bt%7D%5Cright%29%5Ctag%7B4%7D
以上便是PPO原始论文的核心内容。其实在PPO的原始论文中,除了利用GAE计算优势函数外,并没有提到其他的实现细节和技巧。但是在实际的各种代码实现,例如Open AI Baseline、Open AI Spinning Up中,却包括了许许多多的“trick”,实验表明,这些trick都会在一定程度上影响PPO算法的性能。我在参考了《PPO-Implementation matters in deep policy gradients A case study on PPO and TRPO》这篇论文,以及下面这篇博客后
通过自己的亲身实践,总结了影响PPO算法性能最关键的10个trick,如下表所示:
Trick 1Advantage NormalizationTrick 2State NormalizationTrick 3 & Trick 4Reward Normalization & Reward ScalingTrick 5Policy EntropyTrick 6Learning Rate DecayTrick 7Gradient clipTrick 8Orthogonal InitializationTrick 9Adam Optimizer Epsilon ParameterTrick 10Tanh Activation Function我们把集成了上述10个trick后的PPO算法命名为PPO-max,而不使用这10个trick的最基础的PPO算法命名为PPO-min。我们在gym中的四个连续动作空间环境下(BipedalWalker-v3、HalfCheetah-v2、Hopper-v2、Walker2d-v2)分别进行了实验,训练结果对比如图1所示。
注:
1.关于Trick 3 & Trick 4,由于只能对reward进行一种操作,我们默认选择使用Reward Scaling。
2.因为是连续动作空间,因此我们默认使用Gaussian分布来输出动作。
3.我们在每个环境中都使用了3个随机种子进行实验,并使用seaborn画图,采用“滑动平均”的方法来平滑训练曲线,后文的实验结果图同理。
图1 PPO-max vs PPO-min
通过对比可以看出,不使用上述10个trick的PPO-min在四个gym环境上几乎无法训练,而PPO-max均可以到达非常理想的训练效果。在3M steps内,PPO-max在HalfCheetah-v2环境上reward可以达到6700,在Hopper-v2环境下可以达到3600,Walker2d-v2环境下可以达到5500。对比https://iclr-blog-track.github.io/2022/03/25/ppo-implementation-details/这篇博客中给出的各个强化学习算法库的训练效果,除了“Tianshou”外,我们的实验结果均更胜一筹。
图2 各种强化学习算法库的PPO训练结果
我们将代码开源在了github上,分别提供了PPO算法的离散动作空间实现和连续动作空间实现(见下面github链接中的4.PPO-discrete和5.PPO-continuous(包括了Gaussian分布和Beta分布),如果这份代码对您有帮助,欢迎您给一个star~)
2. 探究影响PPO算法性能的10个关键技巧
在这一节中,我们将逐一介绍上述PPO-max中10个trick的具体实现细节,并通过对比实验来探究这些trick究竟对PPO算法的性能有什么影响。(注:下面的实验讨论均已连续动作空间下Gaussian分布为例)
Trick 1—Advantage Normalization
在论文《The Mirage of Action-Dependent Baselines in Reinforcement Learning》中提出了对advangate进行normalization的操作,可以提升PG算法的性能。具体代码实现层面,对advantage做normalization的方式主要有两种:
(1)batch adv norm:使用GAE计算完一个batch中的advantage后,计算整个batch中所有advantage的mean和std,然后减均值再除以标准差。
(2)minibatch adv norm:使用GAE计算完一个batch中的advantage后,不是直接对整个batch的advangate做normalization,而是在用每次利用minibatch更新策略之前,对当前这个minibatch中的advangate做normalization。(https://iclr-blog-track.github.io/2022/03/25/ppo-implementation-details/ 这篇博客中使用的就是minibatch adv norm)
是否使用advantage normalization,以及batch adv norm和minibatch adv norm的对比如图3所示。在我们的PPO-max中,默认使用的是batch adv norm(红色曲线);如果关闭batch adv norm(棕色曲线),PPO算法几乎无法训练,由此可见advantage normalization对PPO算法的性能有非常重要的影响。如果把batch adv norm替换成minibatch adv norm(黑色曲线),训练性能会有一定程度的下降。
图3 batch adv norm VS minibatch dv norm
从原理角度分析,我个人认为如果是对每一个minibatch中的advangate单独做normalization,可能会导致每一次计算的mean和std有较大的波动,从而对算法的训练带来一定负面影响。因此,我们在这里建议使用batch adv norm的方式。
Trick 2—State Normalization
state normalization的核心在于,与环境交互的过程中,维护一个动态的关于所有经历过的所有state的mean和std, 然后对当前的获得的state做normalization。经过normalization后的state符合mean=0,std=1的正态分布,用这样的状态作为神经网络的输入,更有利于神经网络的训练。
具体实现方式如下:
(1)首先定义一个动态计算mean和std的class,名为RunningMeanStd。这个class中的方法的核心思想是已知n个数据的mean和std,如何计算n+1个数据的mean和std
注:这种方法计算的mean是准确的,但是std只是估计值,与真实std有一点微小偏差。使用这种方法计算mean和std的主要原因是,我们不可能事先初始化一个无限大的buffer,每获得一个新的状态数据后都重新计算buffer中所有数据的mean和std,这样太浪费计算资源和时间,也不现实。class RunningMeanStd:
# Dynamically calculate mean and std
def __init__(self, shape):# shape:the dimension of input data
self.n = 0
self.mean = np.zeros(shape)
self.S = np.zeros(shape)
self.std = np.sqrt(self.S)
def update(self, x):
x = np.array(x)
self.n += 1
if self.n == 1:
self.mean = x
self.std = x
else:
old_mean = self.mean.copy()
self.mean = old_mean + (x - old_mean) / self.n
self.S = self.S + (x - old_mean) * (x - self.mean)
self.std = np.sqrt(self.S / (self.n - 1))(2)定义一个名叫Normalization的类,其中实例化上面的RunningMeanStd,需要传入的参数shape代表当前环境的状态空间的维度。训练过程中,每次得到一个state,都要把这个state传到Normalization这个类中,然后更新mean和std,再返回normalization后的state。
class Normalization:
def __init__(self, shape):
self.running_ms = RunningMeanStd(shape=shape)
def __call__(self, x, update=True):
# Whether to update the mean and std,during the evaluating,update=Flase
if update:
self.running_ms.update(x)
x = (x - self.running_ms.mean) / (self.running_ms.std + 1e-8)
return x是否使用state noramalization的对比如图4所示,红色曲线为PPO-max,蓝色曲线为在PPO-max的基础上关闭state normalization。通过对比可以看出,state normalization这个trick对PPO算法的整体性能有一定提升。
图4 是否使用state normalization
Trick 3 & Trick 4—— Reward Normalization & Reward Scaling
对reward的处理,目前有reward normalization和reward scaling两种方式:这两种处理方式的目的都是希望调整reward的尺度,避免因过大或过小的reward对价值函数的训练产生负面影响。
(1)reward normalization:与state normalization的操作类似,也是动态维护所有获得过的reward的mean和std,然后再对当前的reward做normalization。
(2)reward scaling:在《PPO-Implementation matters in deep policy gradients A case study on PPO and TRPO》这篇论文中,作者中提出了一种名叫reward scaling的方法,如图5所示。reward scaling与reward normalization的区别在于,reward scaling是动态计算一个standard deviation of a rolling discounted sum of the rewards,然后只对当前的reward除以这个std。
图5 PPO reward scaling
reward scaling的代码实现被集成在了RewardScaling这个class中,具体代码如下:
class RewardScaling:
def __init__(self, shape, gamma):
self.shape = shape# reward shape=1
self.gamma = gamma# discount factor
self.running_ms = RunningMeanStd(shape=self.shape)
self.R = np.zeros(self.shape)
def __call__(self, x):
self.R = self.gamma * self.R + x
self.running_ms.update(self.R)
x = x / (self.running_ms.std + 1e-8)# Only divided std
return x
def reset(self):# When an episode is done,we should reset 'self.R'
self.R = np.zeros(self.shape)reward norm和reward scaling的对比如图6所示。图中,PPO-max(红色)中默认使用的是reward scaling,去掉reward scaling后(橙色),性能有一定程度下降;如果把PPO-max中的reward scaling 换成reward norm(紫色),在HalfCheetah-v2、Hopper-v2和Walker-v2这三个环境下,对训练性能的伤害非常严重。因此,我们建议使用reward scaling而不是reward normalization。
图6 reward scaling or reward normalization
Trick 5—Policy Entropy
在信息论与概率统计中,熵(entropy)是表示随机变量不确定性的度量。在强化学习中,策略的熵可以表示为:
https://www.zhihu.com/equation?tex=%5Cmathcal%7BH%7D%5Cleft%28%5Cpi%5Cleft%28%5Ccdot+%5Cmid+s_%7Bt%7D%5Cright%29%5Cright%29%3D-%5Csum_%7Ba_%7Bt%7D%7D+%5Cpi%5Cleft%28a_%7Bt%7D+%5Cmid+s_%7Bt%7D%5Cright%29+%5Clog+%5Cleft%28%5Cpi%5Cleft%28a_%7Bt%7D+%5Cmid+s_%7Bt%7D%5Cright%29%5Cright%29%3D%5Cmathbb%7BE%7D_%7Ba_%7Bt%7D+%5Csim+%5Cpi%7D%5Cleft%5B-%5Clog+%5Cleft%28%5Cpi%5Cleft%28a_%7Bt%7D+%5Cmid+s_%7Bt%7D%5Cright%29%5Cright%29%5Cright%5D%5Ctag%7B5%7D
一个策略的熵越大,意味着这个策略选择各个动作的概率更加“平均”。在PPO中,为了提高算法的探索能力,我们一般在actor的loss中增加一项策略熵,并乘以一个系数entropy_coef,使得在优化actor_loss的同时,让策略的熵尽可能大。一般我们设置entropy_coef=0.01。
是否使用策略熵的对比如图7所示,通过对比可以看出,使用策略熵可以一定程度提高训练效果,如果在PPO-max(红色)的基础上不适用策略熵(即令entropy_coef=0,图中粉色),reward往往会收敛到次优解。
图7 是否使用策略熵
Trick 6—Learning Rate Decay
学习率衰减可以一定程度增强训练后期的平稳性,提高训练效果。这里我们采用线性衰减学习率的方式,使lr从初始的3e-4,随着训练步数线性下降到0,具体代码如下:
def lr_decay(self, total_steps):
lr_a_now = self.lr_a * (1 - total_steps / self.max_train_steps)
lr_c_now = self.lr_c * (1 - total_steps / self.max_train_steps)
for p in self.optimizer_actor.param_groups:
p['lr'] = lr_a_now
for p in self.optimizer_critic.param_groups:
p['lr'] = lr_c_now是否使用学习率衰减的对比如图8所示,通过对比可以看出,学习率衰减这一trick的确对训练效果有一定帮助。
图8 是否使用学习率衰减
Trick 7—Gradient clip
梯度剪裁是为了防止训练过程中梯度爆炸从而引入的一项trick,同样可以起到稳定训练过程的作用。在Pytorch中,梯度剪裁只需要在更新actor和critic时增加一条语句即可实现。
# Update actor
self.optimizer_actor.zero_grad()
actor_loss.mean().backward()
if self.use_grad_clip: # Trick 7: Gradient clip
torch.nn.utils.clip_grad_norm_(self.actor.parameters(), 0.5)
self.optimizer_actor.step()
# Update critic
self.optimizer_critic.zero_grad()
critic_loss.backward()
if self.use_grad_clip: # Trick 7: Gradient clip
torch.nn.utils.clip_grad_norm_(self.critic.parameters(), 0.5)
self.optimizer_critic.step()是否增加gradient clip的对比如图9所示,通过对比可以看出,gradient clip对训练效果有一定提升。
图9 是否增加gradient clip
Trick 8—Orthogonal Initialization
正交初始化(Orthogonal Initialization)是为了防止在训练开始时出现梯度消失、梯度爆炸等问题所提出的一种神经网络初始化方式。具体的方法分为两步:
(1)用均值为0,标准差为1的高斯分布初始化权重矩阵,
(2)对这个权重矩阵进行奇异值分解,得到两个正交矩阵,取其中之一作为该层神经网络的权重矩阵。
使用正交初始化的Actor和Critic实现如下面的代码所示:
注:
1. 我们一般在初始化actor网络的输出层时,会把gain设置成0.01,actor网络的其他层和critic网络都使用Pytorch中正交初始化默认的gain=1.0。
2. 在我们的实现中,actor网络的输出层只输出mean,同时采用nn.Parameter的方式来训练一个“状态独立”的log_std,这往往比直接让神经网络同时输出mean和std效果好。(之所以训练log_std,是为了保证std=exp(log_std)>0)# orthogonal init
def orthogonal_init(layer, gain=1.0):
nn.init.orthogonal_(layer.weight, gain=gain)
nn.init.constant_(layer.bias, 0)
class Actor_Gaussian(nn.Module):
def __init__(self, args):
super(Actor_Gaussian, self).__init__()
self.max_action = args.max_action
self.fc1 = nn.Linear(args.state_dim, args.hidden_width)
self.fc2 = nn.Linear(args.hidden_width, args.hidden_width)
self.mean_layer = nn.Linear(args.hidden_width, args.action_dim)
self.log_std = nn.Parameter(torch.zeros(1, args.action_dim))# We use 'nn.Paremeter' to train log_std automatically
if args.use_orthogonal_init:
print("------use_orthogonal_init------")
orthogonal_init(self.fc1)
orthogonal_init(self.fc2)
orthogonal_init(self.mean_layer, gain=0.01)
def forward(self, s):
s = torch.tanh(self.fc1(s))
s = torch.tanh(self.fc2(s))
mean = self.max_action * torch.tanh(self.mean_layer(s))# [-1,1]->[-max_action,max_action]
return mean
def get_dist(self, s):
mean = self.forward(s)
log_std = self.log_std.expand_as(mean)# To make 'log_std' have the same dimension as 'mean'
std = torch.exp(log_std)# The reason we train the 'log_std' is to ensure std=exp(log_std)>0
dist = Normal(mean, std)# Get the Gaussian distribution
return dist
class Critic(nn.Module):
def __init__(self, args):
super(Critic, self).__init__()
self.fc1 = nn.Linear(args.state_dim, args.hidden_width)
self.fc2 = nn.Linear(args.hidden_width, args.hidden_width)
self.fc3 = nn.Linear(args.hidden_width, 1)
if args.use_orthogonal_init:
print("------use_orthogonal_init------")
orthogonal_init(self.fc1)
orthogonal_init(self.fc2)
orthogonal_init(self.fc3)
def forward(self, s):
s = torch.tanh(self.fc1(s))
s = torch.tanh(self.fc2(s))
v_s = self.fc3(s)
return v_s是否使用正交初始化的对比如图所10示,通过对比可以看出,正交初始化对训练性能有一定提高。
图10 是否使用正交初始化
Trick 9—Adam Optimizer Epsilon Parameter
pytorch中Adam优化器默认的eps=1e-8,它的作用是提高数值稳定性(pytorch官方文档中对Adam优化器的介绍如图11,eps即红框中的)
图11 Pytorch官方文档中Adam优化器介绍
在Open AI的baseline,和MAPPO的论文里,都单独设置eps=1e-5,这个特殊的设置可以在一定程度上提升算法的训练性能。
是否设置Adam优化器中eps参数的对比如图10所示,通过对比可以看出,单独设置Adam优化器的eps=1e-5可以一定程度提升算法性能。
图12 是否设置Adam eps
Trick10—Tanh Activation Function
一般的强化学习算法,例如DDPG TD3 SAC等算法,都默认使用relu激活函数,但是经过实验表明,PPO算法更适合使用Tanh激活函数。在论文《PPO-Implementation matters in deep policy gradients A case study on PPO and TRPO》中,作者也建议使用tanh激活函数。
使用tanh和relu激活函数的对比如图13所示,在PPO-max中我们默认使用的是tanh激活函数,把PPO-max中的激活函数替换成relu后(actor网络的最后一层mean_layer依然使用tanh),算法性能有了一定程度的下降。因此我们建议PPO算法默认使用tanh激活函数。
图13 激活函数tanh or relu
3.关于PPO算法的一些补充
3.1关于GAE的计算,以及done信号的区分
在gym的环境中,done=True有三种情况:
[*]游戏胜利(win)
2. 游戏失败(dead)
3. 达到最大步长
对于前两种情况,即dead or win的时候,我们可以认为当前的状态s就是终止状态,没有下一个状态s'的(例如BipedalWalker-v3这个环境,就会出现智能体通关或者摔倒的情形)。而对于第三种情况,即达到最大步长,这时本质上是人为“截断”了当前的回合,事实上当前的状态s并不是终止状态。因此我们在主循环中,需要对env.step()返回的done进行区分。为了区分前两种情况和第三种情况,我在程序中做了如下处理:
if done and episode_steps != args.max_episode_steps:
dw = True
else:
dw = False我用dw这个变量来表示dead or win这两种情况,然后同时向Buffer中存储dw和done。在计算GAE时,对dw和done进行区分:
if dw=True: deltas=r-v(s)
if dw=False:deltas=r+gamma*v(s')-v(s)
当done=True时,说明出现了上述三种情况的其中之一,即意味着一个episode的结束。在逆序计算adv时,遇到done=True,就要重新计算。使用GAE计算advangate的具体代码如下
s, a, a_logprob, r, s_, dw, done = replay_buffer.numpy_to_tensor()# Get training data
"""
Calculate the advantage using GAE
'dw=True' means dead or win, there is no next state s'
'done=True' represents the terminal of an episode(dead or win or reaching the max_episode_steps). When calculating the adv, if done=True, gae=0
"""
adv = []
gae = 0
with torch.no_grad():# adv and v_target have no gradient
vs = self.critic(s)
vs_ = self.critic(s_)
deltas = r + self.gamma * (1.0 - dw) * vs_ - vs
for delta, d in zip(reversed(deltas.flatten().numpy()), reversed(done.flatten().numpy())):
gae = delta + self.gamma * self.lamda * gae * (1.0 - d)
adv.insert(0, gae)
adv = torch.tensor(adv, dtype=torch.float).view(-1, 1)
v_target = adv + vs
if self.use_adv_norm:# Trick 1:advantage normalization
adv = ((adv - adv.mean()) / (adv.std() + 1e-5))3.2 Guassian分布与Beta分布
一般的连续动作空间版本的PPO算法,都默认使用Gaussian分布来输出动作。在《Improving Stochastic Policy Gradients in Continuous Control with Deep Reinforcement Learning using the Beta Distribution 》指出,由于Gaussian分布是一个无界的分布,我们在采样动作后往往需要clip操作来把动作限制在有效动作范围内,这个clip的操作往往会给算法性能带来负面影响。因此这篇论文提出采用一个有界的Beta分布来代替Guassain分布,通过Beta分布采样的动作一定在区间内(Beta分布的概率密度函数曲线如图14所示),因此我们可以把采样到的区间内的动作映射到任何我们想要的动作区间。
图14 Beta分布的概率密度函数曲线
在PPO中采用Beta分布的主要改动在于actor网络的定义,代码如下:
class Actor_Beta(nn.Module):
def __init__(self, args):
super(Actor_Beta, self).__init__()
self.fc1 = nn.Linear(args.state_dim, args.hidden_width)
self.fc2 = nn.Linear(args.hidden_width, args.hidden_width)
self.alpha_layer = nn.Linear(args.hidden_width, args.action_dim)
self.beta_layer = nn.Linear(args.hidden_width, args.action_dim)
if args.use_orthogonal_init:
print("------use_orthogonal_init------")
orthogonal_init(self.fc1, gain=1.0)
orthogonal_init(self.fc2, gain=1.0)
orthogonal_init(self.alpha_layer, gain=0.01)
orthogonal_init(self.beta_layer, gain=0.01)
def forward(self, s):
s = torch.tanh(self.fc1(s))
s = torch.tanh(self.fc2(s))
# alpha and beta need to be larger than 1,so we use 'softplus' as the activation function and then plus 1
alpha = F.softplus(self.alpha_layer(s)) + 1.0
beta = F.softplus(self.beta_layer(s)) + 1.0
return alpha, beta
def get_dist(self, s):
alpha, beta = self.forward(s)
dist = Beta(alpha, beta)
return dist
def mean(self, s):
alpha, beta = self.forward(s)
mean = alpha / (alpha + beta)# The mean of the beta distribution
return mean在一些环境下,例如HalfCheetah-v2,采用Beta有时会比Gaussian获得更好的效果,如图15所示。
图15 Gaussian VS Beta
因此,我们在PPO算法的实现中,集成了Beta分布,可以通过设置'policy_dist'参数来实现Gaussian分布和Beta分布之间的切换。
4. 总结
在这篇文章中,我根据自己个人的实际经验,列出了影响PPO算法性能的10个关键技巧,并通过对比实验来探究这些技巧对PPO算法性能的具体影响,同时给出了完整的PPO算法的pytorch实现(包括了离散动作版本和连续动作版本(集成Gaussian分布和Beta分布))。
同时,我想额外指出的是,我上面列出的这10条trick,也不一定在所有的情况下都有效。很多时候,深度强化学习算法的训练是一件很“玄”的事情,不同的环境,不同的状态空间、动作空间和奖励函数的设计,都会对算法的性能产生不同的影响。同样的一个trick,可能在一个任务中效果很好,在另一个任务中却完全不work。我总结这10条trick,更多的是希望给正在学习和使用PPO算法的朋友提供一个整体方向上的引导,当你在用PPO算法解决一个实际任务但是效果不理想时,或许可以尝试一下我列出的这几条trick。当然,过渡迷恋于调参往往是不可取的,我们应该把更多的注意力放在模型算法本身的改进上。
最后,由于本人水平有限,上述文章内容和代码中难免存在错误,欢迎大家与我交流,批评指正!
参考
[*]^Schulman J, Wolski F, Dhariwal P, et al. Proximal policy optimization algorithms. arXiv preprint arXiv:1707.06347, 2017.
[*]^Schulman J, Moritz P, Levine S, et al. High-dimensional continuous control using generalized advantage estimation. arXiv preprint arXiv:1506.02438, 2015.
[*]^abcEngstrom L, Ilyas A, Santurkar S, et al. Implementation matters in deep policy gradients: A case study on PPO and TRPO. arXiv preprint arXiv:2005.12729, 2020.
[*]^Tucker G, Bhupatiraju S, Gu S, et al. The mirage of action-dependent baselines in reinforcement learning//International conference on machine learning. PMLR, 2018: 5015-5024.
[*]^Chou P W, Maturana D, Scherer S. Improving stochastic policy gradients in continuous control with deep reinforcement learning using the beta distribution//International conference on machine learning. PMLR, 2017: 834-843.
太强了 [开心]
页:
[1]