继续上一讲的内容【强化学习】05 —— 基于无模型的强化学习(Prediction)
在生活中,我们会遇见许多可以被建模成MDP的问题:
| Elevator | Parallel Parking | Ship Steering |
|---|---|---|
| Bioreactor | Helicopter | Aeroplane Logistics |
| Robocup Soccer | Quake | Portfolio management |
| Robot walking | Game of Go | … |
对于大部分真实世界中的问题,模型可以分为两类:
本章还会引入一组概念:在线策略学习和离线策略学习。通常来说,在线策略学习要求使用在当前策略下采样得到的样本进行学习,一旦策略被更新,当前的样本就被放弃了,就好像在水龙头下用自来水洗手;而离线策略学习使用经验回放池将之前采样得到的样本收集起来再次利用,就好像使用脸盆接水后洗手。因此,离线策略学习往往能够更好地利用历史数据,并具有更小的样本复杂度(算法达到收敛结果需要在环境中采样的样本数量),这使其被更广泛地应用。
在线策略学习(On-policy)
离线策略学习(Off-policy)
我们在动态规划算法(【强化学习】04 ——动态规划算法)那一讲中介绍了策略迭代的过程,从一个起始的价值函数出发,follow一个策略 π \pi π,经过不断的策略评估与策略提升,最后使得策略收敛到最优的策略 π ∗ \pi^* π∗。

基于状态价值函数
V
(
s
)
V(s)
V(s)的策略提升需要MDP模型:
π ′ ( s ) = argmax a ∈ A R s a + P s s ′ a V ( s ′ ) \pi^{\prime}(s)=\operatorname*{argmax}_{a\in\mathcal{A}}\mathcal{R}_s^a+\mathcal{P}_{ss^{\prime}}^aV(s^{\prime}) π′(s)=a∈AargmaxRsa+Pss′aV(s′)
但是对于无模型的强化学习,我们是无法得知奖励函数 R s a \mathcal{R}_s^a Rsa以及状态转移函数 P s s ′ a \mathcal{P}_{ss^{\prime}}^a Pss′a,因此需要基于动作价值函数进行贪婪策略提升: π ′ ( s ) = argmax s ∈ A Q ( s , a ) \pi^{\prime}(s)=\operatorname*{argmax}_{s\in\mathcal{A}}Q(s,a) π′(s)=s∈AargmaxQ(s,a)
同样地,基于动作价值函数的策略迭代过程如下图所。对于策略评估部分,可以采用Monte-Carlo策略评估,使得 Q = q π Q=q_\pi Q=qπ,之后利用贪婪策略进行提升。

不过单纯的用贪婪算法进行策略提升会存在局部最优解的问题,因为贪婪算法不能很好地权衡探索 Exploration和利用 Exploitation,因此得到的策略很有可能是次优的。下面用一个例子说明:
如下图所示,开启左边的门的期望奖励是4,而右边的是2。但是若一次开启左边的门得到的奖励是0,而右边始终可以获得奖励,采用贪婪策略很容易会使得我们去选择开启右边的门,虽然这样始终能获得奖励,但是是非最优的。

很容易想到【强化学习】02—— 探索与利用中采用
ϵ
−
g
r
e
e
d
y
\epsilon-greedy
ϵ−greedy的策略:
π
(
a
∣
s
)
=
{
ϵ
/
m
+
1
−
ϵ
i
f
a
∗
=
a
r
g
m
a
x
Q
(
s
,
a
)
ϵ
/
m
o
t
h
e
r
w
i
s
e
\left.\pi(a|s)=\left\{ϵ/m+1−ϵif a∗=argmax Q(s,a)ϵ/motherwise
这里涉及到一个定理,去证明对于任意的
ϵ
−
g
r
e
e
d
y
\epsilon-greedy
ϵ−greedy策略
π
\pi
π,关于
Q
π
Q_\pi
Qπ的
ϵ
−
g
r
e
e
d
y
\epsilon-greedy
ϵ−greedy策略
π
′
\pi'
π′是策略
π
\pi
π的提升,即
V
π
′
(
s
)
≥
V
π
(
s
)
V_{\pi'}(s)\ge V_\pi(s)
Vπ′(s)≥Vπ(s)
Q
π
(
s
,
π
′
(
s
)
)
=
∑
a
∈
A
π
′
(
a
∣
s
)
Q
π
(
s
,
a
)
=
ϵ
/
m
∑
a
∈
A
Q
π
(
s
,
a
)
+
(
1
−
ϵ
)
max
a
∈
A
Q
π
(
s
,
a
)
≥
ϵ
/
m
∑
a
∈
A
Q
π
(
s
,
a
)
+
(
1
−
ϵ
)
∑
a
∈
A
π
(
a
∣
s
)
−
ϵ
/
m
1
−
ϵ
Q
π
(
s
,
a
)
=
∑
a
∈
A
π
(
a
∣
s
)
Q
π
(
s
,
a
)
=
v
π
(
s
)
Qπ(s,π′(s))=∑a∈Aπ′(a|s)Qπ(s,a)=ϵ/m∑a∈AQπ(s,a)+(1−ϵ)maxa∈AQπ(s,a)≥ϵ/m∑a∈AQπ(s,a)+(1−ϵ)\textcolorred∑a∈Aπ(a|s)−ϵ/m1−ϵQπ(s,a)=∑a∈Aπ(a|s)Qπ(s,a)=vπ(s)
也可以在每经历一个Episode之后就策略评估或策略提升。

基于 ϵ − g r e e d y \epsilon-greedy ϵ−greedy算法,我们其实只能得到近似的 Q ≈ Q π Q ≈ Q_π Q≈Qπ,因为该算法没有一个终止条件,会导致其一直在探索。
因此我们必须关注以下两个方面:
因此,我们希望得到一个这样的学习方法:
于是我们将引入GLIE算法
Greedy in the Limit with Infinite Exploration (GLIE),在有限的时间内进行无限可能的探索
Definition
1. 所有已经经历的状态行为对(state-action pair)会被无限次探索 lim k → ∞ N k ( s , a ) = ∞ \lim_{k\to\infty}N_k(s,a)=\infty limk→∞Nk(s,a)=∞
2. 策略最终要趋向于贪婪策略(因为要达到最优策略)。 lim k → ∞ π k ( a ∣ s ) = 1 ( a = argmax a ′ ∈ A Q k ( s , a ′ ) ) \lim_{k\to\infty}\pi_k(a|s)=\mathbf{1}(a=\underset{a^{\prime}\in\mathcal{A}}{\operatorname*{argmax}}Q_k(s,a^{\prime})) limk→∞πk(a∣s)=1(a=a′∈AargmaxQk(s,a′))
Example:设计类似于双曲函数的策略。 ϵ k = 1 / k \epsilon_k=1/k ϵk=1/k, k k k为探索的Episode数目,那么该Ɛ贪婪蒙特卡洛控制就具备GLIE特性。
基于GLIE的蒙特卡洛控制流程如下:
定理:GLIE蒙特卡洛控制能收敛至最优的状态行为价值函数。
本章接下来将要讲解无模型的强化学习中的两大经典算法:Sarsa 和 Q-learning,它们都是基于时序差分(temporal difference,TD)的强化学习算法。
SARSA(State-Action-Reward-State-Action)是一种基于值函数的强化学习算法,用于解决马尔可夫决策过程(MDP)中的控制问题。SARSA算法同时考虑当前的状态和动作,以及下一步的状态和动作来决定以后的行为,是一个(状态-动作-奖励-状态-动作)
⟨
S
,
A
,
R
,
S
′
,
A
′
⟩
\langle S,A,R,S',A'\rangle
⟨S,A,R,S′,A′⟩五元组。
在SARSA算法中,智能体按照一定的策略(如ε-greedy策略)选取动作,并根据环境的反馈(奖励信号)更新值函数。SARSA算法的更新规则为:
Q
(
s
,
a
)
←
Q
(
s
,
a
)
+
α
[
r
+
γ
Q
(
s
′
,
a
′
)
−
Q
(
s
,
a
)
]
Q(s, a) \leftarrow Q(s, a) + \alpha [r + \gamma Q(s', a') - Q(s, a)]
Q(s,a)←Q(s,a)+α[r+γQ(s′,a′)−Q(s,a)]
使用SARSA的在线策略控制

每个时间步长:
• 策略评估:
Q
(
s
,
a
)
←
Q
(
s
,
a
)
+
α
[
r
+
γ
Q
(
s
′
,
a
′
)
−
Q
(
s
,
a
)
]
Q(s, a) \leftarrow Q(s, a) + \alpha [r + \gamma Q(s', a') - Q(s, a)]
Q(s,a)←Q(s,a)+α[r+γQ(s′,a′)−Q(s,a)],
Q
≈
Q
π
Q ≈ Q_π
Q≈Qπ
• 策略改进:
ε
−
g
r
e
e
d
y
ε-greedy
ε−greedy策略改进
Sarsa伪代码:

注:在线策略时序差分控制(on-policy TD control)使用当前策略进行动作
采样。即,SARSA算法中的两个“A”都是由当前策略选择的,这也保证了数据分布的一致性。
有一股侧风从格栅中间向上吹过。标准动作为(上,下,左,右)。但在中间区域,有一股自下而上的风,会使得原本的动作发生改变,风的强度标注在栅格下方的数字。例如,如果你是目标G右侧的一个单元格,那么向左侧的动作会将你带到目标上方的单元格。
训练结果如下图所示:

可以看到,随着训练的进行,Sarsa训练一个Episode所用的时间越来越少,即,达到目标的速度越来越快。

类似TD(λ),
Q
λ
Q^λ
Qλ组合了所有的
Q
t
(
n
)
Q_t^{(n)}
Qt(n),并且赋上了相应的权值
(
1
−
λ
)
λ
n
−
1
(1-\lambda)\lambda^{n-1}
(1−λ)λn−1,累计奖励为:
Q
t
λ
=
(
1
−
λ
)
∑
n
=
1
∞
λ
n
−
1
Q
t
(
n
)
Q_t^\lambda=(1-\lambda)\sum_{n=1}^\infty\lambda^{n-1}Q_t^{(n)}
Qtλ=(1−λ)n=1∑∞λn−1Qt(n)使用下式进行更新:
Q
(
S
t
,
A
t
)
←
Q
(
S
t
,
A
t
)
+
α
(
Q
λ
−
Q
(
S
t
,
A
t
)
)
Q(S_t,A_t)\leftarrow Q(S_t,A_t)+\alpha\left(Q^λ-Q(S_t,A_t)\right)
Q(St,At)←Q(St,At)+α(Qλ−Q(St,At))
这就是Forward View Sarsa(λ),使用它更新Q价值需要遍历完整的Episode,我们同样可以反向理解Sarsa(λ).
类似于Backward View TD(λ),引入Eligibility Trace的概念,不同的是这次的E值针对的不是一个状态,而是一个状态行为对:
E
0
(
s
,
a
)
=
0
E
t
(
s
,
a
)
=
γ
λ
E
t
−
1
(
s
,
a
)
+
1
(
S
t
=
s
,
A
t
=
a
)
E0(s,a)=0Et(s,a)=γλEt−1(s,a)+1(St=s,At=a)
Q值更新
δ
t
=
R
t
+
1
+
γ
Q
(
S
t
+
1
,
A
t
+
1
)
−
Q
(
S
t
,
A
t
)
Q
(
s
,
a
)
←
Q
(
s
,
a
)
+
α
δ
t
E
t
(
s
,
a
)
δt=Rt+1+γQ(St+1,At+1)−Q(St,At)Q(s,a)←Q(s,a)+αδtEt(s,a)

Sarsa(λ) Gridworld Example
下图则用了格子世界的例子具体解释了Sarsa和Sarsa(λ)算法区别,详细解释请参考《强化学习》第五讲 不基于模型的控制

LearningRL/Hands-on-RL/Sarsa_Cliff_Walking.py
部分结果(部分算法波动性较大)



什么是离线策略学习
使用离线策略学习的重要性
当用行为策略
μ
(
a
∣
s
)
\mu(a|s)
μ(a∣s)所收集的数据去学习另一个策略(估计一个不同分布的期望)时,可以用到重要性采样(Importance Sampling)。于是有以下公式:
E
x
∼
p
[
f
(
x
)
]
=
∫
x
p
(
x
)
f
(
x
)
d
x
=
∫
x
q
(
x
)
p
(
x
)
q
(
x
)
f
(
x
)
d
x
=
E
x
∼
q
[
p
(
x
)
q
(
x
)
f
(
x
)
]
Ex∼p[f(x)]=∫xp(x)f(x)dx=∫xq(x)p(x)q(x)f(x)dx=Ex∼q[p(x)q(x)f(x)]
使用策略𝜇产生的时序差分目标评估策略𝜋
根据重要性采样对时序差分目标𝑟 + 𝛾𝑉(𝑠′)加权
仅需要一步来进行重要性采样修正
V
(
S
t
)
←
V
(
S
t
)
+
α
(
π
(
A
t
∣
S
t
)
μ
(
A
t
∣
S
t
)
(
R
t
+
1
+
γ
V
(
S
t
+
1
)
)
−
V
(
S
t
)
)
V(St)←V(St)+α(\textcolorredπ(At|St)μ(At|St)(Rt+1+γV(St+1))−V(St))
具有比蒙特卡洛重要性采样更低的方差
策略仅需在单步中被近似

Q-learning的伪代码

class Qlearning():
def __init__(self, env, gamma, alpha, epsilon, numOfEpisodes, numOfActions=4):
self.env = env
self.gamma = gamma
self.alpha = alpha
self.epsilon = epsilon
self.numOfEpisodes = numOfEpisodes
self.numOfActions = numOfActions
# 初始化Q(s, a)表
self.Q_table = np.zeros([self.env.nrows * self.env.ncols, numOfActions])
# Choose A from S using policy derived from Q (e.g., epsilon-greedy)
def ChooseAction(self, state):
if np.random.random() < self.epsilon:
action = np.random.randint(self.numOfActions)
else:
action = np.argmax(self.Q_table[state])
return action
def QlearningRun(self):
# 记录每一条序列的回报
returnList = []
# 显示10个进度条
for i in range(10):
# tqdm的进度条功能
with tqdm(total=int(self.numOfEpisodes / 10), desc='Iteration %d' % i) as pbar:
# 每个进度条的序列数
for episode in range(int(self.numOfEpisodes / 10)):
# initialize state
state = self.env.Reset()
done = False
episodeReward = 0
# Loop for each step of episode:
while not done:
# Choose A from S using policy derived from Q (e.g., epsilon-greedy)
action = self.ChooseAction(state)
# Take action A, observe R, S'
stateprime, reward, done = self.env.Step(action)
episodeReward += reward
# Update
TD_error = reward + self.gamma * self.Q_table[stateprime].max() \
- self.Q_table[state, action]
self.Q_table[state,action] += self.alpha * TD_error
state = stateprime
returnList.append(episodeReward)
if (episode + 1) % 10 == 0: # 每10条序列打印一下这10条序列的平均回报
pbar.set_postfix({
'episode':
'%d' % (self.numOfEpisodes / 10 * i + episode + 1),
'return':
'%.3f' % np.mean(returnList[-10:])
})
pbar.update(1)
return returnList
Q-learning算法最终收敛得到的策略为:
^ooo ovoo ovoo ^ooo ^ooo ovoo ooo> ^ooo ^ooo ooo> ooo> ovoo
ooo> ooo> ooo> ooo> ooo> ooo> ^ooo ooo> ooo> ooo> ooo> ovoo
ooo> ooo> ooo> ooo> ooo> ooo> ooo> ooo> ooo> ooo> ooo> ovoo
^ooo **** **** **** **** **** **** **** **** **** **** EEEE
seed = 0时的对比

十次训练平均:

可以看到在当前的参数设置下,Q-learning的奖励回报略低于Sarsa。
[1] 伯禹AI
[2] https://www.deepmind.com/learning-resources/introduction-to-reinforcement-learning-with-david-silver
[3] 动手学强化学习
[4] Reinforcement Learning