时序差分方法
时序差分方法是强化学习理论中最核心的内容,是强化学习领域最重要的成果,没有之一。与动态规划的方法和蒙特卡罗的方法比,时序差分的方法主要的不同点在值函数估计上面。
动态规划方法计算值函数是通过下式:
V
(
S
t
)
←
E
π
[
R
t
+
1
+
γ
V
(
S
t
+
1
)
]
=
∑
a
π
(
a
∣
S
t
)
∑
s
′
,
r
p
(
s
′
,
r
∣
S
t
,
a
)
[
r
+
γ
V
(
s
′
)
]
V\left(S_{t}\right) \leftarrow E_{\pi}\left[R_{t+1}+\gamma V\left(S_{t+1}\right)\right]=\sum_{a} \pi\left(a \mid S_{t}\right) \sum_{s^{\prime}, r} p\left(s^{\prime}, r \mid S_{t}, a\right)\left[r+\gamma V\left(s^{\prime}\right)\right]
V(St)←Eπ[Rt+1+γV(St+1)]=a∑π(a∣St)s′,r∑p(s′,r∣St,a)[r+γV(s′)]
上式给出了值函数估计的计算公式,从公式中可以看到,动态规划方法计算值函数时用到了当前状态
s
s
s的所有后继状态
s
′
s'
s′处的值函数。值函数的计算用到了bootstapping的方法。所谓bootstrpping本意是指自举,此处是指当前值函数的计算用到了后继状态的值函数。即用后继状态的值函数估计当前值函数。特别注意,此处后继的状态是由模型公式
p
(
s
′
,
r
∣
S
t
,
a
)
p(s',r|S_t,a)
p(s′,r∣St,a)计算得到的。由模型公式和动作集,可以计算状态
s
s
s所有的后继状态
s
′
s'
s′。当没有模型时,后继状态无法全部得到,只能通过试验和采样的方法每次试验得到一个后继状态
s
′
s'
s′。
无模型时,我们可以采用蒙特卡罗的方法利用经验平均来估计当前状态的值函数。蒙特卡罗方法利用经验平均估计状态的值函数,所谓的经验是指一次试验,而一次试验要等到终止状态出现才结束。下式中的
G
t
G_t
Gt是状态
S
t
S_t
St后直到终止状态所有回报的返回值。
V
(
S
t
)
←
V
(
S
t
)
+
α
(
G
t
−
V
(
S
t
)
)
V\left(S_{t}\right) \leftarrow V\left(S_{t}\right)+\alpha\left(G_{t}-V\left(S_{t}\right)\right)
V(St)←V(St)+α(Gt−V(St))
相比于动态规划的方法,蒙特卡罗的方法需要等到每次试验结束,所以学习速度慢,学习效率不高。很自然的,可以想到借鉴动态规划中bootstrapping的方法,在不等到试验结束时就估计当前的值函数。事实上,这就是时间差分方法的精髓。时间差分方法结合了蒙特卡罗的采样方法(即做试验)和动态规划方法的bootstrapping(利用后继状态的值函数估计当前值函数),其示意图如下
TD方法更新值函数的公式为
V
(
S
t
)
←
V
(
S
t
)
+
α
(
R
t
+
1
+
γ
V
(
S
t
+
1
)
−
V
(
S
t
)
)
V\left(S_{t}\right) \leftarrow V\left(S_{t}\right)+\alpha\left(R_{t+1}+\gamma V\left(S_{t+1}\right)-V\left(S_{t}\right)\right)
V(St)←V(St)+α(Rt+1+γV(St+1)−V(St))
其中
R
t
+
1
+
γ
V
(
S
t
+
1
)
R_{t+1}+\gamma V(S_{t+1})
Rt+1+γV(St+1)称为TD目标,与(1)式中的
G
t
G_t
Gt对应,两者不同之处是TD目标利用了bootstraping方法估计当前值函数。其中,
δ
t
=
R
t
+
1
+
γ
V
(
S
t
+
1
)
−
V
(
S
t
)
\delta_t=R_{t+1}+\gamma V(S_{t+1})-V(S_t)
δt=Rt+1+γV(St+1)−V(St)
被称为时序差分误差(TD Error)。
DP、MC、TD方法的异同
蒙特卡罗的方法使用的是值函数最原始的定义,该方法利用所有回报的累积和估计值函数。DP方法和TD方法则利用一步预测方法计算当前状态值函数。其共同点是利用了bootstrapping方法,不同的是,DP方法利用模型计算后继状态,而TD方法利用试验得到后继状态。
从统计学的角度来看,蒙特卡罗方法和时间差分方法都是利用样本去估计值函数的方法,既然是统计方法,就可以从期望和方差两个指标对两种方法进行对比。
- 蒙特卡罗方法:蒙特卡罗方法中的返回值
G
t
=
R
t
+
1
+
γ
R
t
+
2
+
⋯
+
γ
T
−
1
R
T
G_t=R_{t+1}+\gamma R_{t+2}+\cdots+\gamma^{T-1}R_T
Gt=Rt+1+γRt+2+⋯+γT−1RT
,其期望便是值函数的定义,因此蒙特卡罗方法是无偏估计。但是蒙特卡罗方法每次得到的 G t G_t Gt值要等到最终状态出现,在这个过程中要经历很多随机的状态和动作,因此每次得到的 G t G_t Gt随机性很大,所以尽管期望等于真值,但方差无穷大。 - 时间差分方法:时间差分方法的TD目标为 R t + 1 + γ V ( S t + 1 ) R_{t+1}+\gamma V(S_{t+1}) Rt+1+γV(St+1),若 V ( S t + 1 ) V(S_{t+1}) V(St+1)采用真实值,则TD估计也是无偏估计,然而在试验中 V ( S t + 1 ) V(S_{t+1}) V(St+1)用的也是估计值,因此时间差分估计方法属于有偏估计。跟蒙特卡罗方法相比,时间差分方法只用到了一步随机状态和动作,因此TD目标的随机性比蒙特卡罗方法中的 G t G_t Gt要小,因此其方差也比蒙特卡罗方法的方差小。
时序差分
时间差分方法在每个episode
中,当agent
处于
S
t
S_t
St的状态,采用Moving Average的方法对状态下
S
t
S_t
St 的价值函数
V
(
S
t
)
V(S_t)
V(St) 进行软更新:
V
(
S
t
)
←
(
1
−
α
)
V
(
S
t
)
+
α
G
t
V(S_t) \leftarrow (1-\alpha)V(S_t) + \alpha G_t
V(St)←(1−α)V(St)+αGt
其中的
G
t
G_t
Gt就是回报函数,而
α
\alpha
α是一个比较小的数,称为学习率。若
α
\alpha
α很小,
1
−
α
1-\alpha
1−α接近1,所以这个更新公式的右侧在结果上很接近
V
(
S
t
)
V(S_t)
V(St),但是往
G
t
G_t
Gt的方向移动了一点点,也就是说状态
S
t
S_t
St 的价值
V
(
S
t
)
V(S_t)
V(St) 往这一个episode中
S
t
S_t
St处的回报值
G
t
G_t
Gt的方向更新了一点点,挪动的长度就等于
α
∣
V
(
S
t
)
−
G
t
∣
\alpha |V(S_t)-G_t|
α∣V(St)−Gt∣。
以离散型的概率分布为例,离散型概率分布的期望实际上就是各个随机变量取值的加权和,也就是说权重越大,这个取值对期望值的贡献越大,影响越大,而衡量随机变量取值权重的就是这个取值的概率。
然而上式中的
G
t
G_t
Gt 我们是不知道的(因为
G
t
G_t
Gt需要这个episode结束才能计算)。所以需要继续近似,在右式中展开乘法并带入
G
t
G_t
Gt 的定义式:
(
1
−
α
)
V
(
S
t
)
+
α
G
t
=
V
(
S
t
)
+
α
(
G
t
−
V
(
S
t
)
)
=
V
(
S
t
)
+
α
(
∑
k
=
0
∞
γ
k
R
t
+
k
+
1
−
V
(
S
t
)
)
=
V
(
S
t
)
+
α
(
R
t
−
1
+
γ
(
R
t
−
2
+
γ
R
t
+
3
+
…
)
−
V
(
S
t
)
)
=
V
(
S
t
)
+
α
(
R
t
+
1
+
γ
G
t
+
1
−
V
(
S
t
)
)
≈
V
(
S
t
)
+
α
(
R
t
+
1
+
γ
V
(
S
t
+
1
)
−
V
(
S
t
)
)
\begin{aligned} (1-\alpha) V\left(S_{t}\right)+\alpha G_{t} =& V\left(S_{t}\right)+\alpha\left(G_{t}-V\left(S_{t}\right)\right) \\ =& V\left(S_{t}\right)+\alpha\left(\sum_{k=0}^{\infty} \gamma^{k} R_{t+k+1}-V\left(S_{t}\right)\right) \\ =& V\left(S_{t}\right)+\alpha\left(R_{t-1}+\gamma\left(R_{t-2}+\gamma R_{t+3}+\ldots\right)-V\left(S_{t}\right)\right) \\ =& V\left(S_{t}\right)+\alpha\left(R_{t+1}+\gamma G_{t+1}-V\left(S_{t}\right)\right) \\ \approx & V\left(S_{t}\right)+\alpha\left(R_{t+1}+\gamma V\left(S_{t+1}\right)-V\left(S_{t}\right)\right) \end{aligned}
(1−α)V(St)+αGt====≈V(St)+α(Gt−V(St))V(St)+α(k=0∑∞γkRt+k+1−V(St))V(St)+α(Rt−1+γ(Rt−2+γRt+3+…)−V(St))V(St)+α(Rt+1+γGt+1−V(St))V(St)+α(Rt+1+γV(St+1)−V(St))
首先
G
t
G_t
Gt我们是不知道的,所以需要做替换。因为我们是用单次的
G
t
G_t
Gt来更新价值的,我们是用若干次的软更细近似向真实期望值的逼近,所以当模型收敛时,来一次模型测试时,agent
处于
S
t
S_t
St 状态的
G
t
G_t
Gt,
V
(
S
t
)
V(S_t)
V(St) 与该处
G
t
G_t
Gt的期望值应该是很接近的。所以我们就直接用
S
t
+
1
S_{t+1}
St+1状态现存的价值来代替这次episode
中
S
t
+
1
S_{t+1}
St+1 状态下的
G
t
+
1
G_{t+1}
Gt+1,这样也符合模型收敛的方向,随着训练的进行,更新越来越准确。
最终可以确定更新式:
V
(
S
t
)
←
V
(
S
t
)
+
α
(
R
t
+
1
+
γ
V
(
S
t
+
1
)
−
V
(
S
t
)
)
V\left(S_{t}\right) \leftarrow V\left(S_{t}\right)+\alpha\left(R_{t+1}+\gamma V\left(S_{t+1}\right)-V\left(S_{t}\right)\right)
V(St)←V(St)+α(Rt+1+γV(St+1)−V(St))
价值函数
V
(
s
)
V(s)
V(s)是为了综合衡量一个状态的潜在价值,但仅仅有状态还不够,还需要加入动作,来评估一个状态下采取某个动作的潜在价值。我们把动作状态价值函数叫做Q函数,事实上Q表格里面的值也就是Q函数。与价值函数相比,Q函数也就只是多了一个约束条件–动作。其定义如下:
Q
(
s
,
a
)
=
E
[
G
t
∣
S
t
=
s
,
A
t
=
a
]
=
E
[
∑
k
=
0
∞
γ
k
R
t
+
k
+
1
∣
S
t
=
s
,
A
t
=
a
]
\begin{aligned} Q(s, a) &=\mathbb{E}\left[G_{t} \mid S_{t}=s, A_{t}=a\right] \\ &=\mathbb{E}\left[\sum_{k=0}^{\infty} \gamma^{k} R_{t+k+1} \mid S_{t}=s, A_{t}=a\right] \end{aligned}
Q(s,a)=E[Gt∣St=s,At=a]=E[k=0∑∞γkRt+k+1∣St=s,At=a]
所以Q函数描述了在状态
S
t
S_{t}
St 下采取动作
A
t
A_{t}
At取得的回报值
G
t
G_{t}
Gt 的期望值。
采用和上式推导完全相同的思路,可以得出Q函数的更新方式:
Q
(
S
t
,
A
t
)
←
Q
(
S
t
,
A
t
)
+
α
[
R
t
+
1
+
γ
Q
(
S
t
+
1
,
A
t
+
1
)
−
Q
(
S
t
,
A
t
)
]
Q(S_t,A_t) \leftarrow Q(S_t,A_t)+\alpha [R_{t+1}+\gamma Q(S_{t+1},A_{t+1})-Q(S_t,A_t)]
Q(St,At)←Q(St,At)+α[Rt+1+γQ(St+1,At+1)−Q(St,At)]
可以证明,只要不断使用上式更新迭代
S
t
S_{t}
St 下的价值函数,最终
S
t
S_{t}
St下的价值函数
V
(
S
t
)
V(S_{t})
V(St)会收敛到一个值。即使用TD的RL模型的收敛性是确定的。
Sarsa
算法
既然我们可以用时序差分方法来估计价值函数,那一个很自然的问题是,我们能否用类似策略迭代的方法来进行强化学习。策略评估已经可以通过时序差分算法实现,那么在不知道奖励函数和状态转移函数的情况下该怎么进行策略提升呢?答案是可以直接用时序差分算法来估计动作价值函数
Q
Q
Q:
Q
(
s
t
,
a
t
)
←
Q
(
s
t
,
a
t
)
+
α
[
r
t
+
γ
Q
(
s
t
+
1
,
a
t
+
1
)
−
Q
(
s
t
,
a
t
)
]
Q\left(s_{t}, a_{t}\right) \leftarrow Q\left(s_{t}, a_{t}\right)+\alpha\left[r_{t}+\gamma Q\left(s_{t+1}, a_{t+1}\right)-Q\left(s_{t}, a_{t}\right)\right]
Q(st,at)←Q(st,at)+α[rt+γQ(st+1,at+1)−Q(st,at)]
然后我们用贪婪算法来选取在某个状态下动作价值最大的那个动作,即
arg
max
a
Q
(
s
,
a
)
\operatorname{arg} \max _{a} Q(s, a)
argmaxaQ(s,a)。这样就形成了一个完整的强化学习算法:用贪婪算法根据动作价值选取动作来和环境交互,再根据得到的数据用时序差分算法更新动作价值估计。
然而这个简单的算法存在两个需要进一步考虑的问题。
- 第一,如果要用时序差分算法来准确地估计策略的状态价值函数,我们需要用极大量的样本来进行更新。但实际上我们可以忽略这一点,直接用一些样本来评估策略,然后就可以更新策略了。我们可以这么做的原因是策略提升可以在策略评估未完全进行的情况进行,这其实是广义策略迭代(generalized policy iteration)的思想。
- 第二,如果在策略提升中一直根据贪婪算法得到一个确定性策略,可能会导致某些状态动作对 ( s , a ) (s,a) (s,a)无法访问到,以至于无法对其动作价值进行估计,进而无法保证策略提升后的策略比之前的好。简单常用的解决方案是使用 ϵ \epsilon ϵ-greedy策略。
现在,我们就可以得到一个实际的基于时序差分方法的强化学习算法。这个算法被称为 Sarsa,因为它的动作价值更新用到了当前状态 s s s、当前动作 a a a、获得的奖励 r r r、下一个状态 s ′ s' s′和下一个动作 a ′ a' a′,将这些符号拼接后就得到了算法名称。
Sarsa
是一种On-Policy的TD算法。说Sarsa是On-Policy的算法是因为Sarsa的一次软更新需要
S
t
,
A
t
,
S
t
+
1
,
A
t
+
1
S_{t}, A_{t}, S_{t+1}, A_{t+1}
St,At,St+1,At+1 这四个量 (随着
S
t
S_{t}
St与
S
t
+
1
S_{t+1}
St+1的确定,
R
t
+
1
R_{t+1}
Rt+1也随之确定) ,而这四个量中的
A
t
A_{t}
At与
A
t
+
1
A_{t+1}
At+1的确定方式都是通过同一张表格(更新前后的表格属于不同的表格,此时的 “同” 指的是根据Q表格选取动作
A
t
A_{t}
At 和动作
A
t
+
1
A_{t+1}
At+1 之间表格没有更新过) 。而此处Q表格就是 agent 行使的准则,即Policy。
我们将这种更新一次所需要的参量都需要依托同一个Policy称为On-Policy(也就是行动策略和评估策略是同一个策略)。Sarsa的初始算法如下
- 初始化 Q ( s , a ) Q(s,a) Q(s,a)
- for 序列
e
=
1
→
E
e=1\rightarrow E
e=1→E do:
- 得到初始状态 s s s
- 用 ϵ \epsilon ϵ-greedy 策略根据选择当前状态 s s s下的动作 a a a
- for 时间步
t
=
1
→
T
t=1\rightarrow T
t=1→T do :
- 得到环境反馈的 r r r、 s ′ s' s′
- 用 ϵ \epsilon ϵ-greedy 策略根据 Q Q Q选择当前状态 s ′ s' s′下的动作 a ′ a' a′
- Q ( s , a ) ← Q ( s , a ) + α [ r + γ Q ( s ′ , a ′ ) − Q ( s , a ) ] Q(s, a) \leftarrow Q(s, a)+\alpha\left[r+\gamma Q\left(s^{\prime}, a^{\prime}\right)-Q(s, a)\right] Q(s,a)←Q(s,a)+α[r+γQ(s′,a′)−Q(s,a)]
- s ← s ′ , a ← a ′ s \leftarrow s^{\prime}, a \leftarrow a^{\prime} s←s′,a←a′
- end for
- end for
多步 Sarsa
算法
可以从上面的算法看出,在更新当前值函数时,用到了下一个状态的值函数。那么以此推理,可以利用后继
n
n
n个状态的值函数来更新当前状态的值函数。首先,可以用
G
t
(
1
)
=
R
t
+
1
+
γ
V
(
S
t
+
1
)
G_t^{(1)}=R_{t+1}+\gamma V(S_{t+1})
Gt(1)=Rt+1+γV(St+1)表示TD目标,利用第二步值函数来估计当前值函数可表示为:
G
t
(
2
)
=
R
t
+
1
+
γ
R
t
+
2
+
γ
2
V
(
S
t
+
1
)
G_t^{(2)}=R_{t+1}+\gamma R_{t+2}+\gamma^2V(S_{t+1})
Gt(2)=Rt+1+γRt+2+γ2V(St+1),以此类推,利用第
n
n
n步的值函数更新当前值函数,可表示为:
G
t
(
n
)
=
R
t
+
1
+
γ
R
t
+
2
+
⋯
+
γ
n
−
1
R
t
+
n
+
γ
n
V
(
S
t
+
n
)
G_{t}^{(n)}=R_{t+1}+\gamma R_{t+2}+\cdots+\gamma^{n-1} R_{t+n}+\gamma^{n} V\left(S_{t+n}\right)
Gt(n)=Rt+1+γRt+2+⋯+γn−1Rt+n+γnV(St+n)
如下图所示为利用
n
n
n步值函数估计当前值函数的示意图。再审视一下刚刚的结论:可以利用
n
n
n步值函数来估计当前值函数,也就是说当前值函数有
n
n
n种估计方法。那么哪种估计值更接近真实值呢?我们不知道,但是我们可以对这
n
n
n个估计值利用加权的方法进行融合,这就是
T
D
(
λ
)
TD(\lambda)
TD(λ)。
我们在
G
t
(
n
)
G_t^{(n)}
Gt(n)前乘以加权因子
(
1
−
λ
)
λ
n
−
1
(1-\lambda)\lambda^{n-1}
(1−λ)λn−1,乘这个加权是因为:
G
t
λ
=
(
1
−
λ
)
G
t
(
1
)
+
(
1
−
λ
)
λ
G
t
(
2
)
+
⋯
+
(
1
−
λ
)
λ
n
−
1
G
t
(
n
)
≈
[
(
1
−
λ
)
+
(
1
−
λ
)
λ
+
⋯
+
(
1
−
λ
)
λ
n
−
1
]
V
(
S
t
)
=
V
(
S
t
)
\begin{aligned} G_{t}^{\lambda}&=(1-\lambda) G_{t}^{(1)}+(1-\lambda) \lambda G_{t}^{(2)}+\cdots+(1-\lambda) \lambda^{n-1} G_{t}^{(n)} \\ & \approx\left[(1-\lambda)+(1-\lambda) \lambda+\cdots+(1-\lambda) \lambda^{n-1}\right] V\left(S_{t}\right) \\ &=V\left(S_{t}\right) \end{aligned}
Gtλ=(1−λ)Gt(1)+(1−λ)λGt(2)+⋯+(1−λ)λn−1Gt(n)≈[(1−λ)+(1−λ)λ+⋯+(1−λ)λn−1]V(St)=V(St)
利用
G
t
λ
G_{t}^{\lambda}
Gtλ来更新当前状态的值函数的方法称为
T
D
(
λ
)
TD(\lambda)
TD(λ)的方法。对于
T
D
(
λ
)
TD(\lambda)
TD(λ)的理解一般可以从两个视角进行解读。
第一个视角是前向视角,该视角也是
T
D
(
λ
)
TD(\lambda)
TD(λ)的定义。
上图所示为
T
D
(
λ
)
TD(\lambda)
TD(λ)方法的前向视角解释。假设一个人坐在状态流上拿着望远镜看向前方,前方是那些将来的状态。当估计当前状态的值函数时,
T
D
(
λ
)
TD(\lambda)
TD(λ)的定义中可以看到,它需要用将来时刻的值函数。也就是说,
T
D
(
λ
)
TD(\lambda)
TD(λ)前向观点通过观看将来状态的值函数来估计当前的值函数。
V
(
S
t
)
←
V
(
S
t
)
+
α
(
G
t
(
λ
)
−
V
(
S
t
)
)
V\left(S_{t}\right) \leftarrow V\left(S_{t}\right)+\alpha\left(G_{t}^{(\lambda)}-V\left(S_{t}\right)\right)
V(St)←V(St)+α(Gt(λ)−V(St))
其中
G
t
λ
=
(
1
−
λ
)
∑
n
=
1
∞
λ
n
−
1
G
t
(
n
)
G_{t}^{\lambda}=(1-\lambda) \sum_{n=1}^{\infty} \lambda^{n-1} G_{t}^{(n)}
Gtλ=(1−λ)∑n=1∞λn−1Gt(n),而
G
t
(
n
)
=
R
t
+
1
+
γ
R
t
+
2
+
⋯
+
γ
n
−
1
R
t
+
n
+
γ
n
V
(
S
t
+
n
)
G_{t}^{(n)}=R_{t+1}+\gamma R_{t+2}+\cdots+\gamma^{n-1} R_{t+n}+\gamma^{n} V\left(S_{t+n}\right)
Gt(n)=Rt+1+γRt+2+⋯+γn−1Rt+n+γnV(St+n)
利用
T
D
(
λ
)
TD(\lambda)
TD(λ)的前向观点估计值函数时,
G
t
λ
G_{t}^{\lambda}
Gtλ的计算用到了将来时刻的值函数,因此需要等到整个试验结束之后。这跟蒙特卡罗方法相似。现在想寻求一种不需要等到试验结束就可以更新当前状态的值函数的更新方法,这种增量式的更新方法需要利用
T
D
(
λ
)
TD(\lambda)
TD(λ)的后向观点。
上图为
T
D
(
λ
)
TD(\lambda)
TD(λ)后向观点示意图,人骑坐在状态流上,手里拿着话筒,面朝已经经历过的状态流,获得当前回报并利用下一个状态的值函数得到TD偏差后,此人会向已经经历过的状态喊话,告诉这些已经经历过的状态处的值函数需要利用当前时刻的TD偏差进行更新。此时过往的每个状态值函数更新的大小应该跟距离当前状态的步数有关。假设当前状态为
s
t
s_t
st,TD偏差为
δ
t
\delta_t
δt,那么
s
t
−
1
s_{t-1}
st−1处的值函数更新应该乘以一个衰减因子
γ
λ
\gamma \lambda
γλ,状态
s
t
−
2
s_{t-2}
st−2处的值函数更新应该乘以
(
γ
λ
)
2
(\gamma \lambda)^2
(γλ)2,以此类推。故
T
D
(
λ
)
TD(\lambda)
TD(λ)更新过程为:
- 首先计算当前状态的TD偏差: δ t = R t + 1 + γ V ( S t + 1 ) − V ( S t ) \delta_{t}=R_{t+1}+\gamma V\left(S_{t+1}\right)-V\left(S_{t}\right) δt=Rt+1+γV(St+1)−V(St)
- 更新适合度轨迹: E t ( s ) = { γ λ E t − 1 , if s ≠ s t γ λ E t − 1 + 1 , if s = s t E_{t}(s)=\left\{\begin{array}{l}\gamma \lambda E_{t-1}, \text { if } s \neq s_{t} \\ \gamma \lambda E_{t-1}+1, \text { if } s=s_{t}\end{array}\right. Et(s)={γλEt−1, if s=stγλEt−1+1, if s=st
- 对于状态空间中的每个状态 s s s,更新值函数: V ( s ) ← V ( s ) + α δ t E t ( s ) V(s) \leftarrow V(s)+\alpha \delta_{t} E_{t}(s) V(s)←V(s)+αδtEt(s)
T D ( λ ) TD(\lambda) TD(λ)前向观点和后向观点的异同:
- 前向观点需要等到一次试验之后再更新当前状态的值函数;而后向观点不需要等到值函数结束后再更新值函数,而是每一步都在更新值函数,是增量式方法。
- 前向观点在一次试验结束后更新值函数时,更新完当前状态的值函数后,此状态的值函数就不再改变。而后向观点,在每一步计算完当前的TD误差后,其他状态的值函数需要利用当前状态的TD误差进行更新。
- 在一次试验结束后,前向观点和后向观点每个状态的值函数的更新总量是相等的,都是 G t λ G_t^{\lambda} Gtλ。也就是说, T D ( λ ) TD(\lambda) TD(λ)前向观点和后向观点其实是等价的。
S a r s a ( λ ) Sarsa(\lambda) Sarsa(λ)的伪代码:
Input:初始化 Q ( s , a ) , ∀ s ∈ S , a ∈ A ( s ) Q(s, a), \forall s \in S, a \in A(s) Q(s,a),∀s∈S,a∈A(s),给定参数 α , β \alpha,\beta α,β
- 给定起始状态 s s s,并根据 ϵ \epsilon ϵ贪婪策略在状态 s s s选择动作 a a a,对所有的 s ∈ S , a ∈ A ( s ) s\in S,a\in A(s) s∈S,a∈A(s), E ( s , a ) = 0 E(s,a)=0 E(s,a)=0
- 根据 ϵ \epsilon ϵ贪婪策略在状态 s s s选择动作 a a a,得到回报 r r r和下一状态 s ′ s' s′,在状态 s ′ s' s′根据 ϵ \epsilon ϵ贪婪策略得到动作 a a a
- δ ← r + γ Q ( s ′ , a ′ ) − Q ( s , a ) \delta \leftarrow r+\gamma Q(s',a')-Q(s,a) δ←r+γQ(s′,a′)−Q(s,a), E ( s , a ) ← E ( s , a ) + 1 E(s,a)\leftarrow E(s,a)+1 E(s,a)←E(s,a)+1
- 对所有的 s ∈ S , a ∈ A ( s ) s\in S, a\in A(s) s∈S,a∈A(s): Q ( s , a ) ← Q ( s , a ) + α δ E ( s , a ) Q(s,a) \leftarrow Q(s,a)+\alpha \delta E(s,a) Q(s,a)←Q(s,a)+αδE(s,a), E ( s , a ) ← γ λ E ( s , a ) E(s,a)\leftarrow\gamma\lambda E(s,a) E(s,a)←γλE(s,a)
- s = s ′ s =s' s=s′, a = a ′ a = a' a=a′,返回第3步
- 返回第2步,直到所有的 Q ( s , a ) Q(s,a) Q(s,a)收敛为止
- 输出最终策略: π ( s ) = arg max a Q ( s , a ) \pi(s)=\arg\max\limits_a Q(s,a) π(s)=argamaxQ(s,a)
Q-Learning
Q-Learning
算法与Sarsa算法在前几步上完全相同,从Sarsa
的第四步往后就开始不一样。Sarsa
第四步开始是选取动作
A
t
+
1
A_{t+1}
At+1,因为必须确定
A
t
+
1
A_{t+1}
At+1,才能使用上式软更新Q表格,否则式子中会出现未知量。
但这么做有一个小问题,观察Sarsa
算法,在第五步更新时用到了
t
+
1
t+1
t+1时刻的动作
A
t
+
1
A_{t+1}
At+1。也就是说,使用Sarsa
更新Q表格
t
t
t 时刻的
Q
(
S
t
,
A
t
)
Q(S_t,A_t)
Q(St,At) 之前就需要做出下一时刻
t
+
1
t+1
t+1的动作
A
t
+
1
A_{t+1}
At+1。所以Sarsa
算法在更新表格时会将下一刻的动作趋势也考虑进去。总结就是,Sarsa
是先做
t
+
1
t+1
t+1 时刻的动作,再更新
t
t
t 时刻的表格。这么做更新的表格具有一定的滞后性,训练出的agent
往往会走鲁棒性最强的路线(最谨慎的动作方法)。
但事实上,我们还可以先更新
t
t
t 时刻的表格,再做
t
+
1
t+1
t+1时刻的动作。像这样步步为营,更新一步,走一步的思路更加符合常人的思路。为了达到这样的目的,我们就不需要agent
在更新
t
t
t时刻的Q表格前做出
t
+
1
t+1
t+1 时刻的动作,在表达式上也就是需要将
A
t
+
1
A_{t+1}
At+1 这个量给消除。
考察
Q
(
S
t
+
1
,
A
t
+
1
)
Q\left(S_{t+1}, A_{t+1}\right)
Q(St+1,At+1)
Q
(
S
t
+
1
,
A
t
+
1
)
=
Q
(
S
t
+
1
,
argmax
a
Q
(
S
t
+
1
,
a
)
)
=
max
a
∈
A
Q
(
S
t
+
1
,
a
)
Q\left(S_{t+1}, A_{t+1}\right)=Q\left(S_{t+1}, \underset{a}{\operatorname{argmax}} Q\left(S_{t+1}, a\right)\right)=\max _{a \in A} Q\left(S_{t+1}, a\right)
Q(St+1,At+1)=Q(St+1,aargmaxQ(St+1,a))=a∈AmaxQ(St+1,a)
将上式带入可得Q-Learning
算法的更新式:
Q
(
S
t
,
A
t
)
←
Q
(
S
t
,
A
t
)
+
α
(
R
t
+
1
+
γ
max
a
∈
A
Q
(
S
t
+
1
,
a
)
−
Q
(
S
t
,
A
t
)
)
Q\left(S_{t}, A_{t}\right) \leftarrow Q\left(S_{t}, A_{t}\right)+\alpha\left(R_{t+1}+\gamma \max _{a \in A} Q\left(S_{t+1}, a\right)-Q\left(S_{t}, A_{t}\right)\right)
Q(St,At)←Q(St,At)+α(Rt+1+γa∈AmaxQ(St+1,a)−Q(St,At))
与Sarsa
相比,再去掉更新前选择
t
+
1
t+1
t+1时刻的动作的第四步就是Q-Learning
算法。
下面给出Q-Learning
算法的伪代码:
Input:初始化 Q 表格 (可以直接创建一个全 0 矩阵)
- 在 t t t时刻 agent 处于状态 S t S_{t} St ,根据 Q Q Q表格选择最佳的 A t = argmax a Q ( S t , a ) A_{t}={\operatorname{argmax}}_a Q\left(S_{t}, a\right) At=argmaxaQ(St,a)
- agent采取 A t A_{t} At 与环境交互得到奖励 R t + 1 R_{t+1} Rt+1 与下一时刻的状态 S t + 1 S_{t+1} St+1
- if
S
t
+
1
=
d
o
n
e
S_{t+1} = done
St+1=done then
- Q ( S t , A t ) ← Q ( S t , A t ) + α ( R t + 1 − Q ( S t , A t ) ) Q\left(S_{t}, A_{t}\right) \leftarrow Q\left(S_{t}, A_{t}\right)+\alpha\left(R_{t+1}-Q\left(S_{t}, A_{t}\right)\right) Q(St,At)←Q(St,At)+α(Rt+1−Q(St,At))
- end
- else
- Q ( S t , A t ) ← Q ( S t , A t ) + α ( R t − 1 + γ max a ∈ A Q ( S t + 1 , a ) − Q ( S t , A t ) ) Q\left(S_{t}, A_{t}\right) \leftarrow Q\left(S_{t}, A_{t}\right)+\alpha\left(R_{t-1}+\gamma \max _{a \in A} Q\left(S_{t+1}, a\right)-Q\left(S_{t}, A_{t}\right)\right) Q(St,At)←Q(St,At)+α(Rt−1+γmaxa∈AQ(St+1,a)−Q(St,At))
- t ← t + 1 t \leftarrow t+1 t←t+1
- 并回到第 2 步
- end
事实上,在
S
t
S_t
St和Q表格相同的前提下,Sarsa
和Q-Learning
的更新式完全等价,不同的是两者执行的策略:
- Sarsa在 t t t 时刻表格更新前选取 t + 1 t+1 t+1时刻的动作
- Q-Learning则在 t t t时刻表格更新后选取 t + 1 t+1 t+1时刻的动作。
简单说,Sarsa
是先执行再更新,Q-Learning
是先更新再执行。但很明显,这两种更新方法本质上都是贪心,所以存在漏洞。