强化学习算法A2C (AdvantageActor-Critic )和A3C (Asynchro 。。。⼀、策略梯度算法回顾
策略梯度(Policy Gradient)算法⽬标函数的梯度更新公式为:
公式(1)各个参数详解:表⽰采样的样本个数,因为我们要数值逼近奖励的期望; 表⽰折扣因⼦,指actor对未来奖励的重视程度,越接近1越重视未来各个时间步的奖励,越接近0越不重视; 表⽰第条采样样本第 时刻的奖励; 表⽰baline,加了baline之后,奖励就会有正有负,负奖励对应的动作的概率就会在优化之后下降,⽽正的奖励对应的动作的概率就会增加,也就是baline起到了不能将所有采样得到的动作对应的概率都增⼤,这是因为采样得到的动作未必是好的动作。 表⽰给定状态时采取动作 的概率。
现在我们取我们知道⽆论是环境还是actor本⾝都具有随机性(⽐如我们⽣活的现实世界⾥⾯,环境的变化是不可测的,也就是随机性很⼤),因此如果不采样⾜够多的数据,我们很难较为准确的逼近奖励的期望,但是数据太多,就会给计算资源带来负担。因次是⼀个⾮常不稳定的随机变量,也就⽅差很⼤,这样训练的模型的效果也会很差。只有⾜够很多的episode样本我们才可以更加准确的来数值逼近奖励的期望。如果还是不明⽩,可以参考我的这篇博客。
上⾯我们引⼊了⼗分不稳定这个问题,那么我们该如何解决这个问题呢?
问题:我们是否可以使⽤⼀个神经⽹络来估计这个这个值?
答:可以,我们使⽤强化学习的值函数⽅法。⼆、QLearning 算法回顾
下⾯先来介绍两个值函数以及他们之间的关系。
▽=R ˉθ(γr −N 1n =1∑N t =1∑T n t =t ′∑T n t −t ′t ′n b )▽logp (a ∣s )θt n t n (1)
N γr t ′n
n t ′b p (a ∣s )θt n t n s t n a t n G =t n γr t =t ′∑T n t −t ′t ′n (2)
G t n
G t n G t n
1. 状态价值函数该函数的意义是:actor和环境互动,当访问到状态 时,直到互动结束,所积累的奖励的期望。
举⼀个sutton强化学习书上的例⼦。
例⼦1:
假设我们采样得到8个eposides,分别如下:
1、2、3、4、5、6、7、8、这⾥给出了8个采样得到的eposide,并且忽略所采取的动作,这⾥是采样得到8个eposide来逼近,选择采样来逼近,是因为actor所处的环境和actor本⾝都具有随机性,由上⾯的公式(1)可以看到,如果所有的eposides有⽆穷多个,那么计算机根本⽆法实现计算根据上⾯的8个eposides,可以计算得到:
因为是要遇到状态 才开始计算,第⼀条样本和最后⼀条的样本在遇到状态时,得到的奖励是0,因此分⼦上⾯只有6个1,⽽分母是8.,这⾥的例⼦只是使⽤8条采样的样本来数值逼近的,如果条件允许,还可以采样更多的样本来更加精确的数值逼近.
2. 状态动作价值函数这个函数的意义就是actor在和环境互动过程中遇到状态 ,确定采取动作之后直到互动结束所累积的奖励的期望,这个函数值和上⾯的计算类似,下⾯修改⼀下上⾯那个例⼦,来举例说明如何计算
例⼦2:
假设我们采样得到8个eposides,分别如下:
1、2、3、4、5、6、7、8、我们现在来计算,因为第⼀条样本和第⼆条样本在遇到状态之后采取动作之后得到的奖励是0,因此有:
因为我只是简单的做了⼀个修改,计算的结果和上⾯的那个是⼀样的,当然这⼋条样本⾥⾯在观测到状态 之后都采取了动作 ,实际更为复杂多变,actor不⼀定在观测到状态都采取动作 的,还有别的动作可以采⽤。
3. 两个价值函数之间的关系
假设actor在观测到状态 之后采取的动作是 ,从环境⾥⾯得到的奖励是 ,因为做出动作 之后,导致环境发⽣变化,或者环境⾃⾝发⽣变化,状态转移到 ,那么就有
公式解释:上⾯说了是actor在观测到状态 确定采取动作 之后所获得的奖励的期望,⽽在状态 之后的状态我们却是不得⽽知的,因此上⾯的等式是成⽴的。
三、A2C 算法推导
3.1、算法流程
V (s )
πs s ,r =a 0,s ,r =b 0,End
s ,r =b 1,End
s ,r =b 1,End
s ,r =b 1,End
s ,r =b 1,End
s ,r =b 1,End
s ,r =b 1,End
s ,r =b 0,End
V (s )πV (s )πV (s )
πV (s )πb V (s )=πb =81+1+1+1+1+14
3s b s b V (s )πb Q (s ,a )
πs a s ,a ,r =a 10,s ,a ,r =b 20,End
s ,a ,r =b 21,End
s ,a ,r =b 21,End
s ,a ,r =b 21,End
s ,a ,r =b 21,End
s ,a ,r =b 21,End
s ,a ,r =b 21,End
s ,a ,r =b 20,End
Q (s ,a )πb 2s b a 2Q (s ,a )=πb 2=81+1+1+1+1+14
3s b a 2s b a 2s a r a s ′Q (s ,a )=πE [r +V (s )]π′(3)
Q (s ,a )πs a s
由公式(2)我们有
我们根据上⾯的两个值函数可以得到的期望是:公式(3)的解释:为什么会成⽴?
由公式(2)可知,是奖励的累加和,因为奖励是actor观测到某个状态之后由环境反馈过来的,因次这和状态动作价值函数是⼀样的。主要是因为actor得到的奖励都是在确定所采取的动作之后才得到的,⽽状态动作价值函数也是在actor观测到状态采取动作之后所获得奖励的期望。因此公式(3)成⽴。
我们可以使⽤ 来估计公式(1)中的baline ,也就是将公式(1),(4),(5)结合起来于是公式(1)就变为下⾯的公式(6).
但是公式(6)会引⼊⼀个问题,我们使⽤神经⽹络来估计 和 ,但是我们可以看到这两个函数的⾃变量是不⼀样的,也就是如果使⽤公式(6)来作为梯度更新的公式的话,这会引⼊两个神经⽹络,那么模型的复杂度也就会增加,复杂的模型会导致⼀系列问题,⽐如过拟合,两个值函数估测不准的可能性也会增加等等。
问题:我们是否可以只引⼊⼀个神经⽹络来解决这个问题?
答案是显然的,因为公式(6)⾥⾯有两个值函数,上⾯的(3)描述了这两个值函数之间的关系,我们要使⽤公式(3)来简化问题。由公式(3)我们有公式(3)只是提供了理论上的可能性,但是计算期望是⼀件很⿇烦的事情,⽽且在⽆穷多的情况下,计算机在实操时根本⽆法计算,那么我们就需要简化问题,于是有
公式解释:状态 是actor观测到状态 时采取动作 之后,状态转移到了状态 ,这种状态的转移可能是由于actor所采取的动作导致的,也可能是环境本⾝⾃⼰发⽣了变化⽽发⽣了转移。
将公式(7)带⼊到公式(6),于是就有:
G =t n γr t =t ′∑T n t −t ′t ′n (2)
G t n
E [G ]=t n Q (s ,a )πt n t n (4)
G t n
Q (s ,a )πs a V (s )πθt n b b =V (s )πθt n (5)
▽=R ˉθ(Q (s ,a )−N 1n =1∑N t =1∑T n πt n t n V (s ))▽πθt n logp (a ∣s )θt n t n (6)
Q (s ,a )πt n t n V (s )πθt n
Q (s ,a )=πE [r +V (s )]π′(3)
Q (s ,a )=πr +V (s )π′(7)
s ′s a s ′▽=R ˉθr +N 1n =1∑N t =1∑T n t n V (s )−πθt +1n V (s )▽πθt n logp (a ∣s )θt n t n (8)
公式(8)解释:虽然上⾯是说使⽤来作为baline,但是我更加觉得这个是在使⽤来逼近环境给出的奖励.我对这个公式的直观理解有点描述不出来,感觉和TD⽅法的思想有点类,从公式可以看出,计算这个梯度只需要使⽤这样的四元组,因为我们在采样数据的时候只需要存储这样的四元组就可以了,和TD⽅法的思想是⼀样的,我觉得是可以实现单步更新,⽆需等待⼀个回合结束再更新模型的。我们知道 是⼀个random variable(r.v.),因此公式⾥⾯还是引⼊了具有随机性的东西,只有在考虑的期望的时候才是正确的,但是 的随机性相对于的随机性是⼩了很多,因为是各个时间步奖励的和,因为相对来说,随机性不⼤。3.2、两个tips
1. 参数共享
我们知道状态价值函数和策略⽹络的输⼊都是状态,但是输出是不⼀样的,因此我们可以将⼀些参数共享来减少模型的复杂性。
2. 探索
我们为了避免actor陷⼊⼀个局部最优解,我们要增加actor的探索能⼒,也就是去尝试做出更多的动作,
可以是策略⽹络输出的动作的分布更加均匀⼀点,这样可以每个动作都有被优化到的可能性。例如可以使⽤e-greedy算法增加模型的探索能⼒,有⼀定的随机性选择新的动作。
四、
A3C
也就是多个actor和环境互动,并⾏更新⽹络
最上⾯的那个⽹络我们认为是global network,然后将他的参数复制,弄出多个⽹络,然后数据,计算梯度,更新global network。算法流程:
1、复制⽹络参数⽣成多个⽹络,放在不同的GPU上
2、每个⽹络都和环境互动,⽣成数据
3、计算梯度
4、更新global network
五、A2C 的Pytorch 实现
import random
import numpy as np
import gym
import torch .nn as nn
import torch as t
from torch .nn import functional as F
import matplotlib .pyplot as plt
import os
# env.clo()
eplison = 0.1
criterion = nn .CrossEntropyLoss ()
os .environ ["KMP_DUPLICATE_LIB_OK"]="TRUE"
gamma = 0.9
actor_lr = 0.001
critic_lr = 0.01
env = gym .make ("CartPole-v0")
env .ed (1) # reproducible, general Policy gradient has high variance
env = env .unwrapped
batch_size = 1
epochs = 500
class Share_layer (nn .Module ):
def __init__(lf ):
super (Share_layer , lf ).__init__()
lf .linear1 = nn .Linear (4, 20)
nn .init .normal_(lf .linear1.weight , 0, 0.1)
V (s )πθt n V (s )−πθt +1n V (s )πθt n
r t n (s ,a ,r ,s )t n t n t n t +1n
r t n r t n G t n G t n
al_(lf.linear1.weight,0,0.1)
stant_(lf.linear1.bias,0.1)
def forward(lf, out):
out = lf.linear1(out)
out = F.relu(out)
return out
class Actor(nn.Module):
def__init__(lf, sl):
super(Actor, lf).__init__()
lf.share_layer = sl
lf.linear2 = nn.Linear(20,2)
al_(lf.linear2.weight,0,0.1)
stant_(lf.linear2.bias,0.1)
def forward(lf, x):
out = t.from_numpy(x).float()
out = lf.share_layer(out)
out = lf.linear2(out)
prob = F.softmax(out, dim =1)#这个输出主要是⽤来使⽤概率来挑选动作return prob, out
class Critic(nn.Module):
def__init__(lf, sl):
super(Critic, lf).__init__()
lf.share_layer = sl
lf.linear2 = nn.Linear(20,1)
al_(lf.linear2.weight,0,0.1)
stant_(lf.linear2.bias,0.1)
def forward(lf, x):
out = t.from_numpy(x).float()
out = lf.share_layer(out)
out = lf.linear2(out)
return out
#下⾯该函数⽤来选择动作
def choo_action(prob):
# print(prob)
action = np.random.choice(a =2, p = prob[0].detach().numpy())
return action
# action = np.random.choice(a = 6, p = prob[0].detach().numpy())
# v = random.uniform(0, 1)
# p, index = t.topk(prob, 1, dim = 1)