目录
一、PG(Policy Gradient)策略梯度算法(on-policy)
1、策略梯度公式推导
2、代码讲解/伪代码
3、改进
3.1Trick Baseline
3.2 Suitable Credit
二、Actor-Critic算法
三、A3C算法
四、DDPG算法
前言
我们都知道强化学习环境env的不确定性是比较突出的一个特点,那么有很多情况下时需要使用强化学习设计仿真实验的,经常会设置一些随即参数,比如随机正态分布或者一个随机的常量,这种我们就正常使用科学计算库numpy或者深度学习框架比如Tensorflow自带的随机就可以,但这种经常会遇到一个问题,包括我本人在最开始设计深度强化学习相关的仿真实验之后,假设每次都训练1000次,但是我运行多次之后发现结果参数(比如reward、loss、Q-value、V-value等)不一样,有几次巧合会是一致的,经查阅资料得出:
在设置参数时正常使用函数功能,只不过需要在导入库文件之后,设置随机种子seed(如下所示),这样就会使得实验结果可复现,也就是说每次运行相同的代码时,只要在相同实验中的随机种子保持一致,那么每次训练模型得到的随即结果将会是一致的,使得结果相对可靠些。并且即使是在不同的实验中,也建议把随机种子设置为一致的,这样可以确保对比的合理性。
# 用到哪个框架使用哪个框架设置随机种子
tf.random.set_seed(1)
np.random.seed(1)
简单介绍一下on-policy和off-policy的区别:对于on-policy算法,边交互边学习,即学习和评估是基于同一个策略进行的,智能体与环境交互的过程中,使用当前的策略生成数据,并利用这些数据来更新策略;而对于off-policy算法,则学习和评估可以基于不同的策略进行,智能体可以利用一个策略下探索环境,而在另一个策略下评估和学习。
一、PG(Policy Gradient)策略梯度算法(on-policy)
下面讲解一下策略梯度算法,PG是一种基于策略(policy-based)的算法它与传统的基于值的(value-based)算法最不一样的点就在于,PG算法依靠直接训练神经网络NN(网络参数即为策略)输入state输出action,过程中不需要计算Q值。而传统的基于值的算法需要使用Q-Table或Q-Network然后通过评判Critic值函数的方式反过来选择action。
若把DQN看成是TD+神经网络的算法,那么PG就是一个MC+神经网络的算法。利用reward奖励直接对选择动作的可能性干预,好的action会被增加下一次交互被选择的概率,而坏的action则会被减小下一次交互被选择的概率。
1、策略梯度公式推导
首先,PG直接使用Actor与环境env交互,每个episode回合最后可以加得一个total reward,
,由于PG目标就是最大化一整个回合之后的total reward。注意,由于NN中的参数一开始可能是随机的,但环境env肯定具有随机性,即使使用同一个Actor,在遇到同一环境中的相同场景时,也会有做出不同决策(action)的概率,故每次的total reward也大概率会不同。那如果这样的话,对于来说,它就是一个随机变量,我们的目标不能仅靠最大化某一次的,而是要最大化它的期望值,这样就可以从算法的角度(不包含实际应用问题)来衡量Actor决策的好坏。
接着 ,讨论一下该如何计算?
假设一个回合的轨迹如下,,故在这一回合的累计回报可以表示为,然后如果使用Actor与环境交互,每个回合都有被采样的概率,用表示在网络参数也就是策略下,轨迹的概率,这样的话,与环境交互N次的期望就可以表示为:
再然后,我们就可以进一步表示出最后的优化目标:
希望找到最优的策略使得最大,故这里可以通过表示。
再然后,很明显,作为最后的目标函数,并由于PG是策略梯度算法,则最后一定会用到梯度下降或梯度上升算法,由于是maximize,所以,对求导,做梯度上升更新网络参数即可最大化,详细过程如下,
然后,将
再然后,
综上,
这样理解起来就容易了,整体梳理一下,如下:
我们需要使用梯度上升法优化寻找函数的最大值,在本情况下,需要最大化期望回报然后分别需要先计算目标函数的梯度以及根据梯度策略更新参数如下公式,.由于上述求解出的可以看出,最后希望求得最大的期望回报,那么由于其是导函数只需要让其大于0使得单调递增即可。当大于0时,只需要让log p的导函数大于0即可,由下述推导1(将推导1中的x替换为)可得越大越好;反之,当小于0时,则是希望越小越好,也是得出的最后大于0。
推导1:,对于概率p(x)肯定是恒大于0的,因此也恒大于0,
那只有当p(x)随着x的增加而增加时,也就大于0,这样的话,也就大于0了,进而推导出log p(x)是随着x的增加而增加的;相反,当p(x)随着x的增加而减小时,也就小于0,进而可以推导出也就小于0了,也就是log p(x)是随着x的增加而减小的。
2、代码讲解/伪代码
初始化策略参数 θ
设置学习率 α
对于每个训练回合 do
初始化状态 s
初始化回合奖励 total_reward = 0
初始化存储的状态、动作和奖励列表
直到回合结束 do
根据当前策略 π(a|s; θ) 选择动作 a
执行动作 a,观察下一个状态 s' 和奖励 r
存储状态 s、动作 a 和奖励 r
s = s'
total_reward += r
计算每个时间步的累计奖励 Gt
对于每个时间步 t do
计算优势函数 A(s_t, a_t) = Gt - V(s_t; θ) # 可以用价值函数估计
计算策略的梯度 ∇θ log(π(a_t|s_t; θ)) * A(s_t, a_t)
更新策略参数 θ = θ + α * ∇θ log(π(a_t|s_t; θ)) * A(s_t, a_t)
如果需要更新价值函数 V(s; θ):
使用 TD 学习或蒙特卡洛方法更新 V(s; θ)
返回策略参数 θ
基于策略的PG算法
初始化学习率α,折现率超参数
初始化网络参数θ
输入:状态s
输出:每个动作对应的概率值
1:构建神经网络 fc1 = tanh(s * weight + b);all_act = (fc1 * weight + b).self.all_act_prob = softmax(all_act).
2:计算损失 neg_log_prob = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=all_act, labels=self.tf_acts);loss = tf.reduce_mean(neg_log_prob * self.tf_vt)
这里的all_act是一个Tensor,代表着每个动作相对的得分,这里labels=self.tf_acts则表示实际选择到的动作。
3:衰减回合计算的reward:(用作动作值)
# 主要函数如下
def _discount_and_norm_rewards(self):
discounted_ep_rs = np.zeros_like(self.ep_rs) # 创建一个与 ep_rs 同样大小的数组,用于存储折扣回报
running_add = 0 # 初始化一个变量,用于累加折扣奖励
# 回溯,倒序,self.ep_rs为一个列表
for t in reversed(range(0, len(self.ep_rs))):
# G值
running_add = running_add * self.gamma + self.ep_rs[t] # 计算当前时间步的折扣回报
discounted_ep_rs[t] = running_add # 将计算得到的 G 值存入 discounted_ep_rs
# 归一化一回合的 rewards
discounted_ep_rs -= np.mean(discounted_ep_rs) # 减去均值
# 除以标准差,进行标准化
discounted_ep_rs /= np.std(discounted_ep_rs) if np.std(discounted_ep_rs) > 0 else 1 # 标准化
return discounted_ep_rs # 返回计算得到的折扣回报
3、改进
3.1Trick Baseline基准线
如图2所示,加入基线就是在原来的目标累计回报求导公式中的某一个轨迹基础上减b,为什么要减去b呢?下面来解释一下原因,以及加入基线b的好处,
真实环境中的奖励reward并不是分布在0周围,很多游戏的奖励全是正数,由第二部分代码讲解中就可以知道,policy-based的算法直接在神经网络输出对应动作的概率值,对应的(每个轨迹的total reward)若大于0,则在该回合的轨迹中被采样到的动作action所对应的概率就会被增加(也就是说鼓励该动作的发生),相反,就会被减小。一般在训练agent时,会跑很多个回合,若未加入基线b的话,有这样一种情况,当所有的(1=<n<=N)都大于0时,那么被采样到的轨迹中的所包含的动作对应的概率也会变大只不过变大的程度不一样,有大有小,那这样的话,轨迹中未被采样到的动作对应的概率就一定会变小,很明显,这不是我们所希望的看到的,理想情况下未被采样的动作我们希望的是让其对应的概率并不发生改变。这种方式会严重导致策略过于集中在某些动作上,忽略了未被采样到的动作。
加入基线b之后,b其实就相当于平均值,整体对奖励信号进行平均归一化操作。希望能分布在0周围,它代表了的平均水平,会导致有些轨迹对用的total reward是大于0的,代表此轨迹中动作的表现要高于平均水平;有些轨迹对应的totla reward是小于0的,代表此轨迹中的动作的表现差于平均水平,让其有正有负。这样的话,当total reward大于0时,会把轨迹中包含的动作的概率增大,当total reward小于0时,就会把轨迹中所包含的动作对应的概率值减小,两种情况的未被当前轨迹采样的动作所对应的概率值都要保持不变(理想状态下),但实际上,基线的引入可以帮助在多个回合中未被采样的动作的概率不会因为某些轨迹的总回报而发生剧烈的变化(多个小变化)。通过这种方式,基线帮助我们在更新策略时保持相对的平衡,避免了过度集中在某些动作上。
3.2 因果性
在之前的所有算法中,对于时间戳为t的动作a,它对并没有影响,而只是对后续的产生影响,因此只考虑从时间戳为t开始的累计回报,公式如下所示。轨迹只要是在同一个轨迹中的所有的state->action都会有相同的reward权重,显然有些情况是不那么公平的,因为明显是在某些回合中有些action非常好,但在有些回合中的action并不好,综上,也就是说整个回合的整体回报好并不能代表每个动作都是好的,相反,整个回合的整体回报不好,并不能代表每个动作action都不好,因此,我们希望给不同的action上乘以不同的权重weight,如图4所示,
左右两侧才有控制变量法,保证三个状态都分别相同,然后让对应的动作和对应的reward不同,可以看出,让一个轨迹的整体回报产生差异的主要在和,相同的状态,但是采取的动作不一样,产生的即使奖励reward不同,进而导致不同的两条轨迹之间的整体回报不同。
再然后,其实Q函数就是代表着从状态st开始执行动作at后的策略的回报估计值可以将替换为,则有
称为优势值函数,它代表了当前动作序列的回报相比于平均回报的优势程度。为什么可以这样看呢?主要就是因为由于Q(st,at)具体指的是在状态st条件下,选取动作at对应的状态动作值,这个动作at是唯一的,而b呢,可以使用V(st)来估计,V即是指状态值,代表的是在状态st条件下,所有的动作对应的累计回报的期望值,相当于一个平均值,因此使用Q-V可以评判出该动作相比于平均回报的优势程度,若结果大于0,则说明选择该动作是积极的positive,但若结果小于0,则说明该动作是消极的negative,结果是一个标量(scalar)。
如图5所示,将每一个轨迹的总回报换为从时间步t开始的累计加权奖励。PG用的就是MC的G值,也就是PG是用MC的G值来更新网络,也就是说,PG先会让智能体从某条轨迹一直走到最后,然后通过回溯计算G值。
讨论:添加基线b之后会不会改变?
由于分别对不同轨迹的回报求和取平均(期望),所以这一时刻我们只需要判断是否等于0即可,下面,将其展开得:
(代入).
可得:
.
这样就是加入基线b之后,并不会改变 ,但是却会是减小方差(减小离散程度)。
二、Actor-Critic算法(即可以离散动作空间,又可以连续动作空间)
Actor-Critic其实就是用两个网络,两个网络均输入状态S,但一个网络输出策略,即负责选择动作,这个网络称为Actor表演者;另一个网络负责评分,计算每个动作对应的分数,这个网络被称为Critic评判者。如图6所示,主要的过程就是Actor网络运用策略选择动作action,然后Critic网络对其打分,评估相应的值函数,Actor网络通过Critic评判的值函数进行相应的学习,若Critic评判的值函数较好,则Actor会对轨迹中的动作的输出概率相应的增大;相反,若Critic评判的值函数较差,则Actor会把相应轨迹中的动作的输出概率减小。综上,就是说Actor就是用于优化策略的,使得动作越来越好,而Critic适用于评估值函数的,使得对其的估计越来越准确。
算法
伪代码
分别初始化Actor网络和Critic网络的学习率
下面主要分为两个网络讲解Actor-Critic架构
一、Actor表演者网络中,Actor网络主要负责产生策略pi
1、在网络中输入状态s,经过可能几层神经网络的正向传播,最后一层加上蒸馏函数softmax,直接将各个动作对应的动作值转化为各个动作所占的百分比。
2、然后Actor网络采用从Critic网络传来的TD-error以及对动作的对应的概率求log计算期望V值(公式为logP * (r + gamma * vt+1 - vt)).
3、 由于目标是要最大化最后的v的期望值,故应采用梯度上升算法,具体操作为 self.train_op = tf.train.AdamOptimizer(lr).minimize(-self.exp_v).可以这样做的原因就是minimize是采用梯度下降算法最小化的过程,故若想要取最大值,将其参数加一个负号即可更改为梯度上升法.
二、Critic网络中,Critic网络主要适用于估计V值以及计算TD-error的。 ->
1、在网络中输入状态s,神经网络正向传播计算得到V值
2、然后根据下一时刻状态s_将其传入到神经网络中得到计算结果v_,然后目标为r + gamma * v_,估计值为v,故可以通过时序差分估计出TD-eror = r + gamma * v_ - v. ->
3、然后,将损失函数设定为均方差损失函数简称为MSE,这块包括反向传播(链式求导),采用优化器比如Adam通过梯度下降法最小化损失函数,然后将TD-error传到Actor网络中即可。最后这一步的过程都体现在self.train_op = tf.train.AdamOptimizer(lr).minimize(self.loss)中,也包括vt的更新公式由于有V的更新公式vt = vt + 学习率 * (r + gamma * vt+1 - vt).
改进:Advantage Actor-Critic,简称为A2C算法
Avantage Actor-Critic算法,它是目前使用Actor Critic思想的主流算法之一,其实Actor Critic系列算法不一定要使用优势函数A(s,a),还可以有其他的变种。
Avantage Actor-Critic算法在训练时,Actor会根据当前的状态st和策略采样获得动作at,并与环境交互得到下一时刻的状态st+1和奖励rt,通过TD方法即可估计每一步的状态st对应的V值,从而更新Critic网络使得值网络的估计更加接近真实环境的期望回报,通过At = rt + gammaV(st+1) - V(st)来估计当前动作的优势值,并采用计算Actor网络的梯度信息,如此循环网络采用梯度上升法,最大化总汇报的期望值,Critic网络会判断的越来越准确,而Actor网络也会调整自己的策略,使得下一次做得更好。
一般地,使用Advantage Actor-Critic算法就是Actor-Critic结构的扩展了,够用。
三、A3C算法
Asynchronous Advantage Actor-Critic,简称为A3C。这是基于Advantage Actor Critic网络之后的一个异步版本,将Actor-Critic网络部署在多个线程中同时进行训练,并通过全局网络来同步参数,这种异步训练的模式大大提升了训练效率,训练速度更快,并且算法性能也更好。
在A3C算法中,算法会创建一个全局网络Global Network和M个Worker线程,Global Network包含Actor和Critic网络,每个线程均会创建一个交互环境和Actor和Critic网络。Global Network并不直接参与到与环境的互动当中,而是每个Worker与环境有直接的交互,并且把所学习到的梯度信息上传到Global Network。初始化阶段Global Network随机初始化参数和,Worker中的Actor-Critic网络从Global Network中同步拉取最新参数来初始化网络。在训练时,Worker中的Actor-Critic网络首先先从Global Network拉取最新参数,然后在最新策略下与私有环境交互采样动作,并根据Advantage Actor-Critic算法计算参数和的梯度信息。在完成梯度计算之后,各个Worker将梯度信息提交到Global Network中,并利用Global Network的优化器完成Global Network的网络参数更新。在算法测试阶段只使用Global Network与环境交互即可。
算法
执行流程
伪代码
四、DDPG算法(Online-Policy,在连续动作空间上表现较好)
Deep Deterministic Policy Gradient,简称DDPG,深度确定性算法。DDPG也是解决连续控制型问题的一个算法,不过和PPO不一样,PPO输出的是一个策略,也就是一个概率分布,而DDPG输出的则直接是一个动作action,从DQN来延伸理解DDPG,相比于DQN算法而言,主要沿用了以下三种技术:
1、经验回放(Experience replay)
agent将每一轮与环境交互得到的经验数据(s,a,r,s',done)存入回放缓存(replay buffer)中,更新网络参数时按照批量的方式采样,能加快训练速度,提高训练的稳定性,但是比较耗费内存(memory)资源和计算(computation)资源.
对于经典的经验回放,就是分为存储和回放两个部分。
从存储的角度看,经验回访可以分为集中式存储和分布式存储:
集中式存储:智能体在一个环境中运行,把经验统一存储在经验池中。
分布式存储:多个智能体同时在多个环境中运行,并将经验统一存储在经验池中。由于多个智能体同时生成经验,所以能够使用更多资源的同时更快的收集经验。
从采样的角度来看,回放也就是从存储中批量取数据的方式可以分为均匀回放和优先回放。
均匀回放:等概率的从经验池中采样经验(数据)。
优先回放:为每条经验设定一个优先级,在采样经验时更倾向于选择优先级别更高的经验,证明其越需要被学习。
2、目标网络(fixed target Q-Network)
除了AC架构中的Actor和Critic网络,再使用一套Target Actor和Target Critic网络,这样在更新目标网络时,为避免网络参数更新过快带来的不稳定,采用软更新的方式.
3、噪声探索(Noisy explore)
确定性策略输出的动作为确定性动作,缺乏对于环境的探索,在训练阶段,给Actor网络输出的动作加入噪声,从而让智能体具有一定的探索能力.
伪代码
参考论文:https://arxiv.org/abs/1602.01783