8_Soft Actor Critic (SAC)

代码 14_SAC.ipynb

1. SAC算法

#机器学习/强化学习/异策略 #机器学习/强化学习/连续动作

SAC 模型的目标就是希望策略的回报和熵都尽可能大,所以不仅是要最大化收益,还要最大化动作熵,动作熵是负的动作概率的对数 log(π(a|s)),因此是希望选择某个动作的概率不要太大,熵前面有一个参数 α 调整熵的重要性, 也称为 温度 因子 ​。

SAC 采用软更新的方法,对两个 critic 进行软更新,在更新中取给出 Q 值比较小的那个,类似 TD3 的技巧一;对于演员则采用熵约束的方法。
#机器学习/强化学习/软更新 #机器学习/强化学习/熵约束

动作熵的概念:对网络输入状态, 网络给出动作和该动作的对数概率, 而把动作的对数概率取负就是熵, 熵越大, 代表该动作的不确定性越大, 也就是发生概率较小, 反过来, 熵越小, 说明确定性越大。

熵约束即既要求回报最大,也要求熵比较大,这就意味着要平衡回报和探索,目标如下

π=argmaxπEπ[tr(st,at)+αH(π(|st))]

也可以写成总的训练目标

J(π)=t=0TE(st,at)ρπ[r(st,at)+αH(π(|st))]

其中熵就是对数化的动作概率加负号, 在代码里面表现为变量 entropy

H(π(|st))=log(π(a|s))

并且 V 函数也加入熵, 如果不考虑负号应该是加上 αH(π(|st)), 改写为 Vsoftπ(s)

Vsoftπ(s)=E(s,a)ρπ[Qsoft(s,a)αlog(π(a|s))]

因此Q函数的贝尔曼方程跟以前类似

Qsoftπ(s,a)=r(s,a)+γE(s,a)ρπ[Qsoft(s,a)αlog(π(a|s))]=r(s,a)+γEsρ[Vsoftπ(s)]

1.1. 评论员的目标函数

对应代码 SAC 类中的 calc_target 方法,也就是在 Q网络的基础上改为软 Q 网络,演员网络的目标函数为

JQ(θ)=E(st,at,st+1)D[12(Qθ(st,at)(r(st,at)+γVθ¯(st+1)))2]=E(st,at,st+1)D[12(Qθ(st,at)(r(st,at)+γ(Qθ¯(st+1,at+1)αlog(π(at+1|st+1)))2]

把上一节提到的 Vsoftπ(s) 的公式带入到第一个式子就得到第二个式子,其中 Qθ¯ 是两个评论员网络给出的价值评价的较小的那个,这里对 θ 求梯度是很简单的。

1.2. 演员的目标函数

即策略网络 Policy,目标函数为

Jπ(ϕ)=DKL(πk(|st)||exp(1αQsoftπ(st,))Zsoftπ(st))=EstD,aπϕ[logπϕ(at|st)1αQθ¯(st,at)+logZ(st)]

其中KL散度公式:

DKL(P||Q)=xp(x)logP(x)Q(x)dx=E[logP(x)Q(x)]

由于求梯度时也不需要对Z求梯度,而且本来也不知道Z,所以代码里面去掉了, 原论文思想也就是这样,位于第四页右侧上面,代码里面还全部同时乘以了α,这里就不乘了,直接写为

Jπ(ϕ)=EstD,aπϕ[logπϕ(at|st)1αQθ¯(st,at)]

这个目标函数是 KL 散度,表示两个分布之间的差异程度,减小这个目标函数就是试图使策略函数 πk 的分布看起来更像是由函数 Z 标准化的 Q 函数的指数分布;

对策略目标函数的参数 ϕ 求导时,与 Z 无关,但是与 Q 是有关的,因为 Q 中的 at 是从策略中重参数化取得的。

1.3. 重参数技巧

SAC 算法的 actor 输出动作,其中需要重参数化采样获得动作,这样才可以传导梯度,critic 接收动作,所以传导梯度是需要动作的,如果按照网络输出构建一个分布再采样,是无法依据动作往前传递梯度的,试想,一个被抽样的样本如何对其所属分布的参数求导呢?这是不可能的,所以必须要重参数化。

其中 at 是重参数化来的,如下公式,目的是让梯度正常更新,我们定义一个 ϵ ,它是从高斯分布采样的噪音,重参数技巧的实现如下,

at=μ+ϵtelog_var/2

其中 μlog_var 都是策略网络输出的,log_var 是对数方差,ϵt 是第 t 次采样给方差加上的噪音,这个噪音相当于常数了;此时动作 at 也是可以求导的。

但是如果依据 μlog_var 建立一个新的分布再采样一个动作,这个动作与参数 μlog_var 是没有关系的,也就不能传导梯度过去,所以要重参数化。

1.4. 动作被压缩后概率密度的变化

在求熵的时候,动作u原本是从正态分布采样的,但是经过a=tanh(u)压缩处理,不再是正态分布,需要重新计算概率,需要注意的是,这里采样到的单个动作的概率就是概率密度,而不是概率分布,这里的πμ都是概率密度函数,推导如下

a=tanh(u)π(a|s)da=μ(u|s)duπ(a|s)=μ(u|s)(dadu)1:dadu=1tanh2uπ(a|s)=μ(u|s)(1tanh2u)1:logπ(a|s)=logμ(u|s)i=1Dlog(1tanh2(ui))=logμ(u|s)i=1Dlog(1ai2)

1.5. α的目标函数

约束优化问题中没有α,它是作为拉格朗日乘子出现的。

存在以下约束优化, 其中H0是可以调整的参数。

maxπE[tr(st,at)]    s.t.    E(st,at)ρπ[log(π(at|st))]H0

参考第十三章 SAC 算法,先不考虑r(st,at),从最后一项往前推,也就是t=T时开始往前推即可发现规律,如下所示(来源Joy RL

maxπ0(E[r(s0,a0)]+maxπ1(E[]+maxπTE[r(sT,aT)] 第一次最大(子问题一) ) 倒数第二次最大 ) 倒数第一次最大 

所以第一次优化是

maxπTE[r(sT,aT)]s.t.    E(sT,aT)ρπT[log(π(aT|sT))]H0

拉格朗日函数为

L(πT,αT)=E[r(sT,aT)+αT(log(π(aT|sT)))]αTH0       H(πT)=log(π(aT|sT))  L(πT,αT)=E[r(sT,aT)+αTH(πT)]αTH0

转化为对偶问题

maxπTE(r(sT,aT))=minαT0maxπTE[r(sT,aT)+αTH(πT)]αTH0αTπT=argmaxπTE(r(sT,aT)+αTH(πT)αTH0)αTαT=argminαTE(r(sT,aT)+αTH(πT)αTH0)

这里发现πTαT的目标式是一样的,如果不清楚目标式是怎么来的,参考下面解minα0maxπT问题的步骤:

  1. 先固定外面的变量,看内层,就是说带外层参数的项都不动,这里指αT,带内层参数πT这一项的也不动,但是可以去掉等于0的项或者常数——因为是argmax求参数,要确定这个参数,和式子里面常数项的大小无关,和等于0的项也无关,只和带参数的项有关——这样就得到了关于内层参数的目标式,就是说确定了该参数的取值;
  2. 第二步是把第一步已经确定的这个参数固定住,当成常数,看到外层,式子里面保留含有外层参数的项,而常数项和等于0的项都去掉,可以看到H(πT)H0都是常数,但是它们都带了系数αT,也就是带了参数,所以不能去掉。

所以经过上面两步,就得到了目标式,但是还没结束,因为这只是第一项的,但是往后推也一样,第二个优化问题就是

maxπT1E[r(sT1,aT1)+r(sT,aT)]s.t.  E(sT1,aT1)ρπT1[log(π(aT1|sT1))]H0

为了找出规律r(sT1,aT1)+r(sT,aT) 可以根据 Qsoft 函数的迭代公式修改:

QT1(sT1,aT1)=r(sT1,aT1)+γE[r(sT,aT)+αTH(πT)]

上式是标准的Qsoft值目标式,但是在这里的操作中,γ被去掉了,提出自动调节温度因子的SAC原论文就没有写。

个人想法:实际上不写γ影响不大,因为就算保留,最后也只是影响H0,而目标熵是人为固定的,没必要再乘以一个折扣了。所以去掉γ,可以推出

QT1(sT1,aT1)αTH(πT)=r(sT1,aT1)+E[r(sT,aT)]

Question:等式右边就是上面第二个优化问题的目标,相当于做了个代换,为什么要有这个代换呢?如果不代换,就把原式的reward项当常数项去掉,结果也是一样的。

个人想法:因为这样可以把第一个优化中已经求出来的 πT 带入H(πT) ,并且 QT1(sT1,aT1) 根据第一次优化得出的结果,可以求出来,所以这两个都是已知的常数项了。在第一个优化问题中,原论文公式(14)处也直接去掉了reward项,但是在Joy RL的推导中,reward保留了,本文参考沿用该写法,本文认为这样更严谨——因为reward并不是人为确定的,所以不能视为常数,而Q函数和熵都是可以通过已知数据人为算出来的。

因此可以转化为下面这个max式子,所以在下面式子第二个等号转化为对偶函数时,加上拉格朗日乘子,注意:带星号的都视为常数,有

max(QT1(sT1,aT1)αTH(πT))=minαT10maxπT1(QT1(sT1,aT1)αTH(πT))+αT1(H(πT1)H0)

先确定πT1,再去掉无关的常数,就可以给出αT1的目标式

αT1=argmaxEatπt[α(H(πT1)H0)]

发现和第一个优化问题的解的形式是一样的,于是给出其目标函数为

J(α)=Eatπt[αlogπt(at|st)αH0]=Eatπt[α(logπt(at|st)H0)]

其中logπt(at|πt)也就是熵entropy,对α求导,就等于小括号里面的动作熵减去目标熵,所以这就是要使得动作熵靠近目标熵,使得J(α)变小。

参考下面策略目标函数,动作熵太大,大于目标熵了,梯度就是正的,α 目标函数在梯度下降时就会减小 α,就是指策略给的动作的概率比较低,拿不准应该怎么办,需要减小 α 使得模型专注于获得更高的回报,也就是尽可能提升动作确定性;而动作熵太小,就意味着策略对某一个动作过于肯定,容易造成过拟合,就调整 α 变大,α 变大就倾向于要求动作熵变大,等于希望动作概率降低,让模型重视探索。

π=argmaxπEπ[tr(st,at)+αH(π(|st))]

1.6. 目标熵的设定

原论文认为连续动作的目标熵等于动作空间的负值,torchrl中默认为torch.prod(n_actions),另一篇论文给出离散SAC,目标熵设置为0.98(log(1|A|)),依据未说明,可能和交叉熵类似,但是总的来说不建议将SAC应用于离散动作环境。