强化学习算法A2C(Advantage Actor-Critic)和A3C(Asynchronous Advantage Actor-Critic)算法详解以及A2C的Pytorch实现

  • Post author:
  • Post category:其他




一、策略梯度算法回顾

策略梯度(Policy Gradient)算法目标函数的梯度更新公式为:





R

ˉ

θ

=

1

N

n

=

1

N

t

=

1

T

n

(

t

=

t

T

n

γ

t

t

r

t

n

b

)

l

o

g

p

θ

(

a

t

n

s

t

n

)

(1)

\bigtriangledown \bar{R}_{\theta } = \frac{1}{N}\sum_{n=1}^{N}\sum_{t=1}^{T_{n}}(\sum_{

{t}’=t}^{T_{n}}\gamma ^{

{t}’-t}r_{

{t}’}^{n}-b)\bigtriangledown logp_{\theta }(a_{t}^{n}|s_{t}^{n})\tag{1}

















R







ˉ

















θ





















=



















N














1































n


=


1



















N





























t


=


1




















T











n



































(













t























=


t




















T











n






































γ













t


























t











r













t































n






























b


)













l


o


g



p











θ



















(



a











t










n























s











t










n



















)







(



1



)









公式(1)各个参数详解:



N

N






N





表示采样的样本个数,因为我们要数值逼近奖励的期望;



γ

\gamma






γ





表示折扣因子,指actor对未来奖励的重视程度,越接近1越重视未来各个时间步的奖励,越接近0越不重视;



r

t

n

r_{

{t}’}^{n}







r













t































n






















表示第



n

n






n





条采样样本第



t

{t}’








t


























时刻的奖励;



b

b






b





表示baseline,加了baseline之后,奖励就会有正有负,负奖励对应的动作的概率就会在优化之后下降,而正的奖励对应的动作的概率就会增加,也就是baseline起到了不能将所有采样得到的动作对应的概率都增大,这是因为采样得到的动作未必是好的动作。



p

θ

(

a

t

n

s

t

n

)

p_{\theta }(a_{t}^{n}|s_{t}^{n})







p











θ



















(



a











t










n























s











t










n



















)





表示给定状态



s

t

n

s_{t}^{n}







s











t










n






















时采取动作



a

t

n

a_{t}^{n}







a











t










n






















的概率。

现在我们取





G

t

n

=

t

=

t

T

n

γ

t

t

r

t

n

(2)

G_{t}^{n} = \sum_{

{t}’=t}^{T_{n}}\gamma ^{

{t}’-t}r_{

{t}’}^{n}\tag{2}







G











t










n





















=



















t























=


t




















T











n






































γ













t


























t











r













t































n
























(



2



)








我们知道无论是环境还是actor本身都具有随机性(比如我们生活的现实世界里面,环境的变化是不可测的,也就是随机性很大),因此如果不采样足够多的数据,我们很难较为准确的逼近奖励的期望,但是数据太多,就会给计算资源带来负担。因次



G

t

n

G_{t}^{n}







G











t










n






















是一个非常不稳定的随机变量,也就方差很大,这样训练的模型的效果也会很差。只有足够很多的episode样本我们才可以更加准确的来数值逼近奖励的期望。如果还是不明白,可以参考我的

策略梯度详解

这篇博客。

上面我们引入了



G

t

n

G_{t}^{n}







G











t










n






















十分不稳定这个问题,那么我们该如何解决这个问题呢?


问题:我们是否可以使用一个神经网络来估计这个



G

t

n

G_{t}^{n}







G











t










n






















这个值?


答:可以,我们使用强化学习的值函数方法。



二、QLearning算法回顾

下面先来介绍两个值函数以及他们之间的关系。

  1. 状态价值函数



    V

    π

    (

    s

    )

    V^{\pi}(s)







    V











    π










    (


    s


    )






    该函数的意义是:actor和环境互动,当访问到状态



    s

    s






    s





    时,直到互动结束,所积累的奖励的期望。


    举一个sutton强化学习书上的例子。



    例子1:


    假设我们采样得到8个eposides,分别如下:

    1、



    s

    a

    ,

    r

    =

    0

    ,

    s

    b

    ,

    r

    =

    0

    ,

    E

    n

    d

    s_{a},r=0,s_{b},r=0,End







    s











    a



















    ,




    r




    =








    0


    ,





    s











    b



















    ,




    r




    =








    0


    ,




    E


    n


    d






    2、



    s

    b

    ,

    r

    =

    1

    ,

    E

    n

    d

    s_{b},r=1,End







    s











    b



















    ,




    r




    =








    1


    ,




    E


    n


    d






    3、



    s

    b

    ,

    r

    =

    1

    ,

    E

    n

    d

    s_{b},r=1,End







    s











    b



















    ,




    r




    =








    1


    ,




    E


    n


    d






    4、



    s

    b

    ,

    r

    =

    1

    ,

    E

    n

    d

    s_{b},r=1,End







    s











    b



















    ,




    r




    =








    1


    ,




    E


    n


    d






    5、



    s

    b

    ,

    r

    =

    1

    ,

    E

    n

    d

    s_{b},r=1,End







    s











    b



















    ,




    r




    =








    1


    ,




    E


    n


    d






    6、



    s

    b

    ,

    r

    =

    1

    ,

    E

    n

    d

    s_{b},r=1,End







    s











    b



















    ,




    r




    =








    1


    ,




    E


    n


    d






    7、



    s

    b

    ,

    r

    =

    1

    ,

    E

    n

    d

    s_{b},r=1,End







    s











    b



















    ,




    r




    =








    1


    ,




    E


    n


    d






    8、



    s

    b

    ,

    r

    =

    0

    ,

    E

    n

    d

    s_{b},r=0,End







    s











    b



















    ,




    r




    =








    0


    ,




    E


    n


    d







    这里给出了8个采样得到的eposide,并且忽略所采取的动作,这里是采样得到8个eposide来逼近



    V

    π

    (

    s

    )

    V^{\pi}(s)







    V











    π










    (


    s


    )





    ,选择采样来逼近



    V

    π

    (

    s

    )

    V^{\pi}(s)







    V











    π










    (


    s


    )





    ,是因为actor所处的环境和actor本身都具有随机性,由上面的公式(1)可以看到,如果所有的eposides有无穷多个,那么计算机根本无法实现计算



    V

    π

    (

    s

    )

    V^{\pi}(s)







    V











    π










    (


    s


    )







    根据上面的8个eposides,可以计算得到



    V

    π

    (

    s

    b

    )

    V^{\pi}(s_{b})







    V











    π










    (



    s











    b



















    )










    V

    π

    (

    s

    b

    )

    =

    1

    +

    1

    +

    1

    +

    1

    +

    1

    +

    1

    8

    =

    3

    4

    V^{\pi}(s_{b})=\frac{1+1+1+1+1+1}{8}=\frac{3}{4}







    V











    π










    (



    s











    b



















    )




    =




















    8
















    1


    +


    1


    +


    1


    +


    1


    +


    1


    +


    1























    =




















    4
















    3


























    因为是要遇到状态



    s

    b

    s_{b}







    s











    b






















    才开始计算,第一条样本和最后一条的样本在遇到状态



    s

    b

    s_{b}







    s











    b






















    时,得到的奖励是0,因此分子上面只有6个1,而分母是8.

    ,这里的例子只是使用8条采样的样本来数值逼近的,如果条件允许,还可以采样更多的样本来更加精确的数值逼近



    V

    π

    (

    s

    b

    )

    V^{\pi}(s_{b})







    V











    π










    (



    s











    b



















    )





    .

  2. 状态动作价值函数



    Q

    π

    (

    s

    ,

    a

    )

    Q^{\pi}(s,a)







    Q











    π










    (


    s


    ,




    a


    )






    这个函数的意义就是actor在和环境互动过程中遇到状态



    s

    s






    s





    ,确定采取动作



    a

    a






    a





    之后直到互动结束所累积的奖励的期望,这个函数值和上面的计算类似,下面修改一下上面那个例子,来举例说明如何计算


    例子2:


    假设我们采样得到8个eposides,分别如下:

    1、



    s

    a

    ,

    a

    1

    ,

    r

    =

    0

    ,

    s

    b

    ,

    a

    2

    ,

    r

    =

    0

    ,

    E

    n

    d

    s_{a}, a_{1}, r=0,s_{b}, a_{2}, r=0,End







    s











    a



















    ,





    a











    1



















    ,




    r




    =








    0


    ,





    s











    b



















    ,





    a











    2



















    ,




    r




    =








    0


    ,




    E


    n


    d






    2、



    s

    b

    ,

    a

    2

    ,

    r

    =

    1

    ,

    E

    n

    d

    s_{b}, a_{2}, r=1,End







    s











    b



















    ,





    a











    2



















    ,




    r




    =








    1


    ,




    E


    n


    d






    3、



    s

    b

    ,

    a

    2

    ,

    r

    =

    1

    ,

    E

    n

    d

    s_{b}, a_{2}, r=1,End







    s











    b



















    ,





    a











    2



















    ,




    r




    =








    1


    ,




    E


    n


    d






    4、



    s

    b

    ,

    a

    2

    ,

    r

    =

    1

    ,

    E

    n

    d

    s_{b}, a_{2}, r=1,End







    s











    b



















    ,





    a











    2



















    ,




    r




    =








    1


    ,




    E


    n


    d






    5、



    s

    b

    ,

    a

    2

    ,

    r

    =

    1

    ,

    E

    n

    d

    s_{b}, a_{2}, r=1,End







    s











    b



















    ,





    a











    2



















    ,




    r




    =








    1


    ,




    E


    n


    d






    6、



    s

    b

    ,

    a

    2

    ,

    r

    =

    1

    ,

    E

    n

    d

    s_{b}, a_{2}, r=1,End







    s











    b



















    ,





    a











    2



















    ,




    r




    =








    1


    ,




    E


    n


    d






    7、



    s

    b

    ,

    a

    2

    ,

    r

    =

    1

    ,

    E

    n

    d

    s_{b}, a_{2}, r=1,End







    s











    b



















    ,





    a











    2



















    ,




    r




    =








    1


    ,




    E


    n


    d






    8、



    s

    b

    ,

    a

    2

    ,

    r

    =

    0

    ,

    E

    n

    d

    s_{b}, a_{2}, r=0,End







    s











    b



















    ,





    a











    2



















    ,




    r




    =








    0


    ,




    E


    n


    d






    我们现在来计算



    Q

    π

    (

    s

    b

    ,

    a

    2

    )

    Q^{\pi}(s_{b},a_{2})







    Q











    π










    (



    s











    b



















    ,





    a











    2



















    )





    ,因为第一条样本和第二条样本在遇到状态



    s

    b

    s_{b}







    s











    b






















    之后采取动作



    a

    2

    a_{2}







    a











    2






















    之后得到的奖励是0,因此有:




    Q

    π

    (

    s

    b

    ,

    a

    2

    )

    =

    1

    +

    1

    +

    1

    +

    1

    +

    1

    +

    1

    8

    =

    3

    4

    Q^{\pi}(s_{b},a_{2})=\frac{1+1+1+1+1+1}{8}=\frac{3}{4}







    Q











    π










    (



    s











    b



















    ,





    a











    2



















    )




    =




















    8
















    1


    +


    1


    +


    1


    +


    1


    +


    1


    +


    1























    =




















    4
















    3

























    因为我只是简单的做了一个修改,计算的结果和上面的那个是一样的,当然这八条样本里面在观测到状态



    s

    b

    s_{b}







    s











    b






















    之后都采取了动作



    a

    2

    a_{2}







    a











    2






















    ,实际更为复杂多变,actor不一定在观测到状态



    s

    b

    s_{b}







    s











    b






















    都采取动作



    a

    2

    a_{2}







    a











    2






















    的,还有别的动作可以采用。

  3. 两个价值函数之间的关系

    假设actor在观测到状态



    s

    s






    s





    之后采取的动作是



    a

    a






    a





    ,从环境里面得到的奖励是



    r

    r






    r





    ,因为做出动作



    a

    a






    a





    之后,导致环境发生变化,或者环境自身发生变化,状态转移到



    s

    {s}’








    s


























    ,那么就有




    Q

    π

    (

    s

    ,

    a

    )

    =

    E

    [

    r

    +

    V

    π

    (

    s

    )

    ]

    (3)

    Q^{\pi}(s,a)=E[r + V^{\pi}({s}’)]\tag{3}







    Q











    π










    (


    s


    ,




    a


    )




    =








    E


    [


    r




    +









    V











    π










    (




    s























    )]







    (



    3



    )









    公式解释:上面说了



    Q

    π

    (

    s

    ,

    a

    )

    Q^{\pi}(s,a)







    Q











    π










    (


    s


    ,




    a


    )





    是actor在观测到状态



    s

    s






    s





    确定采取动作



    a

    a






    a





    之后所获得的奖励的期望,而在状态



    s

    s






    s





    之后的状态我们却是不得而知的,因此上面的等式是成立的。



三、A2C算法推导



3.1、算法流程

由公式(2)我们有





G

t

n

=

t

=

t

T

n

γ

t

t

r

t

n

(2)

G_{t}^{n} = \sum_{

{t}’=t}^{T_{n}}\gamma ^{

{t}’-t}r_{

{t}’}^{n}\tag{2}







G











t










n





















=



















t























=


t




















T











n






































γ













t


























t











r













t































n
























(



2



)








我们根据上面的两个值函数可以

得到



G

t

n

G_{t}^{n}







G











t










n






















的期望是







E

[

G

t

n

]

=

Q

π

(

s

t

n

,

a

t

n

)

(4)

E[G_{t}^{n}] = Q^{\pi}(s_{t}^{n},a_{t}^{n})\tag{4}






E


[



G











t










n



















]




=









Q











π










(



s











t










n



















,





a











t










n



















)







(



4



)









公式(3)的解释:为什么会成立?



由公式(2)可知,



G

t

n

G_{t}^{n}







G











t










n






















是奖励的累加和,因为奖励是actor观测到某个状态之后由环境反馈过来的,因次这和状态动作价值函数是一样的。主要是因为actor得到的奖励都是在确定所采取的动作之后才得到的,而状态动作价值函数



Q

π

(

s

,

a

)

Q^{\pi}(s,a)







Q











π










(


s


,




a


)





也是在actor观测到状态



s

s






s





采取动作



a

a






a





之后所获得奖励的期望。因此公式(3)成立。

我们可以使用



V

π

θ

(

s

t

n

)

V^{\pi_{\theta}}(s_{t}^{n})







V












π











θ



























(



s











t










n



















)





来估计公式(1)中的baseline



b

b






b





,也就是




b

=

V

π

θ

(

s

t

n

)

(5)

b = V^{\pi_{\theta}}(s_{t}^{n})\tag{5}






b




=









V












π











θ



























(



s











t










n



















)







(



5



)








将公式(1),(4),(5)结合起来于是公式(1)就变为下面的公式(6).





R

ˉ

θ

=

1

N

n

=

1

N

t

=

1

T

n

(

Q

π

(

s

t

n

,

a

t

n

)

V

π

θ

(

s

t

n

)

)

l

o

g

p

θ

(

a

t

n

s

t

n

)

(6)

\bigtriangledown \bar{R}_{\theta } = \frac{1}{N}\sum_{n=1}^{N}\sum_{t=1}^{T_{n}}(Q^{\pi}(s_{t}^{n},a_{t}^{n})-V^{\pi_{\theta}}(s_{t}^{n}))\bigtriangledown logp_{\theta }(a_{t}^{n}|s_{t}^{n})\tag{6}

















R







ˉ

















θ





















=



















N














1































n


=


1



















N





























t


=


1




















T











n



































(



Q











π










(



s











t










n



















,





a











t










n



















)














V












π











θ



























(



s











t










n



















))













l


o


g



p











θ



















(



a











t










n























s











t










n



















)







(



6



)






但是公式(6)会引入一个问题,我们使用神经网络来估计



Q

π

(

s

t

n

,

a

t

n

)

Q^{\pi}(s_{t}^{n},a_{t}^{n})







Q











π










(



s











t










n



















,





a











t










n



















)









V

π

θ

(

s

t

n

)

V^{\pi_{\theta}}(s_{t}^{n})







V












π











θ



























(



s











t










n



















)





,但是我们可以看到这两个函数的自变量是不一样的,也就是如果使用公式(6)来作为梯度更新的公式的话,这会引入两个神经网络,那么模型的复杂度也就会增加,复杂的模型会导致一系列问题,比如过拟合,两个值函数估测不准的可能性也会增加等等。


问题:我们是否可以只引入一个神经网络来解决这个问题?


答案是显然的,因为公式(6)里面有两个值函数,上面的(3)描述了这两个值函数之间的关系,我们要使用公式(3)来简化问题。

由公式(3)我们有




Q

π

(

s

,

a

)

=

E

[

r

+

V

π

(

s

)

]

(3)

Q^{\pi}(s,a)=E[r + V^{\pi}({s}’)]\tag{3}







Q











π










(


s


,




a


)




=








E


[


r




+









V











π










(




s























)]







(



3



)








公式(3)只是提供了理论上的可能性,但是计算期望是一件很麻烦的事情,而且在无穷多的情况下,计算机在实操时根本无法计算,那么我们就需要简化问题,于是有




Q

π

(

s

,

a

)

=

r

+

V

π

(

s

)

(7)

Q^{\pi}(s,a)=r + V^{\pi}({s}’)\tag{7}







Q











π










(


s


,




a


)




=








r




+









V











π










(




s























)







(



7



)









公式解释:状态



s

{s}’








s


























是actor观测到状态



s

s






s





时采取动作



a

a






a





之后,状态转移到了状态



s

{s}’








s


























,这种状态的转移可能是由于actor所采取的动作导致的,也可能是环境本身自己发生了变化而发生了转移。

将公式(7)带入到公式(6),于是就有:





R

ˉ

θ

=

1

N

n

=

1

N

t

=

1

T

n

r

t

n

+

V

π

θ

(

s

t

+

1

n

)

V

π

θ

(

s

t

n

)

l

o

g

p

θ

(

a

t

n

s

t

n

)

(8)

\bigtriangledown \bar{R}_{\theta } = \frac{1}{N}\sum_{n=1}^{N}\sum_{t=1}^{T_{n}}r_{t}^{n}+V^{\pi_{\theta}}(s_{t+1}^{n})-V^{\pi_{\theta}}(s_{t}^{n})\bigtriangledown logp_{\theta }(a_{t}^{n}|s_{t}^{n})\tag{8}

















R







ˉ

















θ





















=



















N














1































n


=


1



















N





























t


=


1




















T











n






































r











t










n





















+









V












π











θ



























(



s











t


+


1










n



















)














V












π











θ



























(



s











t










n



















)













l


o


g



p











θ



















(



a











t










n























s











t










n



















)







(



8



)







公式(8)解释:虽然上面是说使用



V

π

θ

(

s

t

n

)

V^{\pi_{\theta}}(s_{t}^{n})







V












π











θ



























(



s











t










n



















)





来作为baseline,但是我更加觉得这个是在使用



V

π

θ

(

s

t

+

1

n

)

V

π

θ

(

s

t

n

)

V^{\pi_{\theta}}(s_{t+1}^{n})-V^{\pi_{\theta}}(s_{t}^{n})







V












π











θ



























(



s











t


+


1










n



















)














V












π











θ



























(



s











t










n



















)





来逼近环境给出的奖励



r

t

n

r_{t}^{n}







r











t










n






















.我对这个公式的直观理解有点描述不出来,感觉和TD方法的思想有点类,从公式可以看出,计算这个梯度只需要使用



(

s

t

n

,

a

t

n

,

r

t

n

,

s

t

+

1

n

)

(s_{t}^{n},a_{t}^{n},r_{t}^{n},s_{t+1}^{n})






(



s











t










n



















,





a











t










n



















,





r











t










n



















,





s











t


+


1










n



















)





这样的四元组,因为我们在采样数据的时候只需要存储这样的四元组就可以了,和TD方法的思想是一样的,我觉得是可以实现单步更新,无需等待一个回合结束再更新模型的。我们知道



r

t

n

r_{t}^{n}







r











t










n






















是一个random variable(r.v.),因此公式里面还是引入了具有随机性的东西,只有在考虑的期望的时候才是正确的,但是



r

t

n

r_{t}^{n}







r











t










n






















的随机性相对于



G

t

n

G_{t}^{n}







G











t










n






















的随机性是小了很多,因为



G

t

n

G_{t}^{n}







G











t










n






















是各个时间步奖励的和,因为相对来说,随机性不大。



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.close()

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.seed(1)     # reproducible, general Policy gradient has high variance
env = env.unwrapped
batch_size = 1
epochs = 500


class Share_layer(nn.Module):
    def __init__(self):
        
        super(Share_layer, self).__init__()
        self.linear1 = nn.Linear(4, 20)
        nn.init.normal_(self.linear1.weight, 0, 0.1)
        nn.init.constant_(self.linear1.bias, 0.1)
        
    def forward(self, out):
        
        out = self.linear1(out)
        out = F.relu(out)
        
        return out
        
        

class Actor(nn.Module):
    
    def __init__(self, sl):
        
        super(Actor, self).__init__()
        
        self.share_layer = sl
      
        self.linear2 = nn.Linear(20, 2)
        nn.init.normal_(self.linear2.weight, 0, 0.1)
        nn.init.constant_(self.linear2.bias, 0.1)
        
    def forward(self, x):
        
        out = t.from_numpy(x).float()

        out = self.share_layer(out) 
        out = self.linear2(out)
        prob = F.softmax(out, dim = 1) #这个输出主要是用来使用概率来挑选动作
        return prob, out
    
    
class Critic(nn.Module):
    
    def __init__(self, sl):
        
        super(Critic, self).__init__()
        
        self.share_layer = sl
        
        self.linear2 = nn.Linear(20, 1)
        nn.init.normal_(self.linear2.weight, 0, 0.1)
        nn.init.constant_(self.linear2.bias, 0.1)
        
    def forward(self, x):
        
        out = t.from_numpy(x).float()
        
        out = self.share_layer(out)
        
        out = self.linear2(out)
       
        return out
  
#下面该函数用来选择动作
def choose_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)
        
    # #下面开始eplison-greedy 算法
    # if v > eplison:       
    #     #这里是求最大的状态价值函数对应的动作
    #     action = index[0][0].item()        
    # else: 
    #     #下面是随机产生动作
    #     action = random.randint(0, 1)  

    # return action

#下面的函数主要用来计算Actor部分训练的损失函数
def Actor_learn(optim, critic, s, s_, a, r, logits):
    
    '''
    根据当前的状态,奖励以及下一个时间步的章台完成损失函数的计算
    Parameters
    ----------
    critic : Critic()实例
        用来估计当前时间的奖励的期望
    s : float array
        当前时间步的状态.
    a : int scalar
        当前时间步根据当前状态s所采取的动作
    r : float scalar
        当前时间步的奖励.
    s_ : float array
        下一个时间步的状态.
    logits : actor网络最后一层的输出
        用来计算交叉熵损失

    Returns
    -------
    Actor 的损失.

    '''
    V_s = critic(s)
    V_s_ = critic(s_)
    #开始计算动作对应的交叉熵
    a = t.tensor([a]).long()
    logp_a = criterion(logits, a)
    
    l = r + V_s_ - V_s
    l = l.item()
    loss = l * logp_a
    # print('Actor loss is :', loss)
    optim.zero_grad()
    
    loss.backward()
    optim.step()
    

def Critic_learn(optim, critic, s, r, s_):
    
    '''
    用来计算Critic网络的损失,来更新Critic网络
    Parameters
    ----------
    critic : Critic实例
        用来计算各个时间步的值函数.
    s : float array
        当前时间步的状态.
    r : float scalar
        当前时间步的奖励.
    s_ : float array
        下一个时间步的状态.

    Returns
    -------
    Critic网络的损失.
    '''
    
    V_s = critic(s)
    V_s_ = critic(s_)
    
    loss = (r + gamma * V_s_.item()- V_s)**2
    optim.zero_grad()
    loss.backward()
    
    optim.step()
    
    return r + gamma * V_s_.item()- V_s
    
 
    
def learn():
    
    #下面采用时间差分方法学习,该方法的学习速度较快,且很稳,时间差分方法和蒙特卡洛方法各有自己的优势
    sl = Share_layer()
    actor = Actor(sl)
    critic = Critic(sl)
    
    actor.train()
    critic.train()
    
    #还需要两个优化器
    actor_optim = t.optim.Adam(actor.parameters(), lr = actor_lr)
    critic_optim = t.optim.Adam(critic.parameters(), lr = critic_lr)
    train_rewards = []
    
    for i in range(epochs):
        
        state = env.reset()
        done = False
        sum_rewards_i = 0
        step = 0

            
        
        while not done:
            
            step += 1
            
            env.render()
            state = np.expand_dims(state, axis = 0)
            
            prob, logits = actor(state)
            
            #下面开始选择动作
            action = choose_action(prob)
            
            state_, reward, done, info = env.step(action)
            if done:
                reward = -20.0
            sum_rewards_i += reward
            
            
            #下面开始学习,先学习的是critic网络,接着才是actor网络
            l = Critic_learn(critic_optim, critic, state, reward, state_)
            Actor_learn(actor_optim, critic, state, state_, action, reward, logits)                       
            state = state_
            
        train_rewards.append(sum_rewards_i)
        print('epoch is :', i)
        print('step nums is :', step)
        
        
        
    plt.plot(train_rewards)
        
            
            
if __name__ == "__main__":
    learn()    
    env.close()


参考内容主要是李宏毅老师的强化学习课程和莫烦python的代码



版权声明:本文为qq_41626059原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。