目录
在动态规划中,我们估计状态和状态-动作函数需要有完备的环境知识,比如状态转移概率,但对于大多数的环境来说我们并不知道环境的动态特征。而蒙特卡罗方法仅仅需要经验,即从真实或模拟的环境交互中采样得到状态、动作、收益的序列。从真实经验中进行学习是非常好的,因为它不需要关于环境的动态变化规律的先验知识。蒙特卡罗方法假定所求解的问题是episode的,即有终止状态。
1、首次访问型MC预测(评估价值函数)
现在我们要评估策略
π
\pi
π下所有状态的价值函数
v
π
(
s
)
,
s
∈
S
v_\pi(s),s\in \mathcal S
vπ(s),s∈S。给定该策略下途径状态
s
s
s的多幕数据,在给定的一幕数据中,每次状态
s
s
s的出现都称为对
s
s
s的一次访问。当然,在同一幕中
s
s
s可能会出现多次,我们称第一次访问
s
s
s的为首次访问。首次访问型MC算法用
s
s
s的所有访问的回报的平均值作为
v
π
(
s
)
v_\pi(s)
vπ(s)的估计,而每次访问型MC算法则使用所有访问的回报的平均值。本文只关注首次访问型MC算法,下面通过举例来说明。
假定我们根据策略
π
\pi
π生成了以下3幕数据,,上标表示幕数:
Episode 1
:
S
0
1
,
A
0
1
,
R
1
1
,
S
1
1
,
A
1
1
,
R
2
1
,
S
2
1
,
A
2
1
,
R
3
1
Episode 2
:
S
0
2
,
A
0
2
,
R
1
2
,
S
1
2
,
A
1
2
,
R
2
2
,
S
2
2
,
A
2
2
,
R
3
2
,
S
3
2
,
A
3
2
,
R
4
2
Episode 3
:
S
0
3
,
A
0
3
,
R
1
3
,
S
1
3
,
A
1
3
,
R
2
3
\begin{aligned} &\text{Episode 1}: S_{0}^1,A_{0}^1,R_{1}^1,S_{1}^1,A_{1}^1,R_{2}^1,S_{2}^1,A_{2}^1,R_{3}^1 \\ &\text{Episode 2}:S_{0}^2,A_{0}^2,R_{1}^2,S_{1}^2,A_{1}^2,R_{2}^2,S_{2}^2,A_{2}^2,R_{3}^2,S_{3}^2,A_{3}^2,R_{4}^2\\ &\text{Episode 3}:S_{0}^3,A_{0}^3,R_{1}^3,S_{1}^3,A_{1}^3,R_{2}^3 \\ \end{aligned}
Episode 1:S01,A01,R11,S11,A11,R21,S21,A21,R31Episode 2:S02,A02,R12,S12,A12,R22,S22,A22,R32,S32,A32,R42Episode 3:S03,A03,R13,S13,A13,R23
假定状态s在第2幕和第3幕中出现,并且
s
=
S
1
2
=
S
3
2
=
S
1
3
s=S_{1}^2=S_{3}^2=S_{1}^3
s=S12=S32=S13。先计算第2幕中s首次出现的回报为
G
1
2
=
R
2
2
+
γ
R
3
2
+
γ
2
R
4
2
G_{1}^2 = R_{2}^2 + \gamma R_{3}^2+\gamma^2 R_{4}^2
G12=R22+γR32+γ2R42,注意这里我们不考虑状态s在
S
3
2
S_{3}^2
S32处的回报。类似地,状态s在第3幕中首次出现的回报为
G
1
3
=
R
2
3
G_{1}^3 = R_{2}^3
G13=R23。因此我们通过这3幕数据得到策略
π
\pi
π在状态s处的价值函数
v
π
(
s
)
≈
G
1
2
+
G
1
3
2
v_{\pi}(s) \approx \frac{G_{1}^2 + G_{1}^3}{2}
vπ(s)≈2G12+G13.
\\[20pt]
2、采用首次访问型MC评估寻宝问题的状态价值函数
我们通过以下寻宝问题来进一步说明采用蒙特卡罗方法怎样评估状态价值函数。假定寻宝家要在以下的网格中寻找宝藏,他除了知道该网格中只有一处有宝藏外,其他关于环境的特征一概不知,比如陷阱和宝藏的位置。可以想象你就是那个寻宝家,怎样以最快的方式找到宝藏呢,唯一的方式是你要进行多次的尝试,把所以的路径都走一遍,并记下哪里有陷阱,哪里没有。到达终止状态(陷阱或宝藏位置)后,此轮回合结束。蒙特卡罗就是这种不知道环境知识的条件下,简单粗暴的走多次回合,并记住走的过程中的经验。
其中红色圆圈代表智能体,黑色方框代表陷阱,箱子为要寻找的宝藏,智能体坠入陷阱时收益为-1,找到宝藏时收益为1,其他的状态转移收益为0。状态序号从左到右从上到下依次编号,如图中智能体的状态为0,宝藏的状态为14,规定每一幕的初始状态为非终止状态,数字0,1,2,3分别代表智能体向左,向上,向右,向下移动。每个动作都能导致智能体移动一个网格,当智能体移除网格边缘时,保持原状态不变。
假定我们通过某个策略
π
\pi
π生成了4幕数据,如以下所示,现在计算状态17的价值函数,从这4幕可知状态17出现在第1,2,4幕中,设置折扣
γ
=
1
\gamma=1
γ=1。
Episode 1
:
[
17
,
3
,
−
1
]
⇒
G
0
1
(
17
)
=
−
1
Episode 2
:
[
17
,
2
,
0
]
[
18
,
0
,
0
]
[
17
,
2
,
0
]
[
18
,
0
,
0
]
[
17
,
2
,
0
]
[
18
,
0
,
0
]
[
17
,
2
,
0
]
[
18
,
1
,
0
]
[
13
,
2
,
1
]
⇒
G
0
2
(
17
)
=
0
+
γ
0
+
γ
2
0
+
γ
3
0
+
γ
4
0
+
γ
5
0
+
γ
6
0
+
γ
7
0
+
γ
8
1
=
1
Episode 3
:
[
16
,
0
,
0
]
[
15
,
0
,
0
]
[
15
,
0
,
0
]
[
15
,
2
,
0
]
[
16
,
0
,
0
]
[
15
,
1
,
−
1
]
Episode 4
:
[
19
,
0
,
0
]
[
18
,
0
,
0
]
[
17
,
2
,
0
]
[
18
,
1
,
0
]
[
13
,
2
,
1
]
⇒
G
2
3
(
17
)
=
0
+
γ
0
+
γ
2
1
=
1
⟹
v
π
(
17
)
≈
G
0
1
(
17
)
+
G
0
2
(
17
)
+
G
2
3
(
17
)
3
≈
0.33
\begin{aligned} &\text{Episode 1}:[ \textcolor{red}{17} , 3 , -1 ] \\ & \Rightarrow G_0^1(17)=-1\\ &\text{Episode 2}:[ \textcolor{red}{17}, 2 , 0 ][ 18 , 0 , 0 ][ 17 , 2 , 0 ][ 18 , 0 , 0 ][ 17 , 2 , 0 ][ 18 , 0 , 0 ][ 17 , 2 , 0 ][ 18 , 1 , 0 ][ 13 , 2 , 1 ] \\ & \Rightarrow G_0^2(17)= 0 + \gamma 0+\gamma^2 0 +\gamma^3 0 +\gamma^4 0 +\gamma^5 0 +\gamma^6 0 +\gamma^7 0 +\gamma^8 1=1 \\ &\text{Episode 3}:[ 16 , 0 , 0 ][ 15 , 0 , 0 ][ 15 , 0 , 0 ][ 15 , 2 , 0 ][ 16 , 0 , 0 ][ 15 , 1 , -1 ] \\ &\text{Episode 4}: [ 19 , 0 , 0 ][ 18 , 0 , 0 ][ \textcolor{red}{17}, 2 , 0 ][ 18 , 1 , 0 ][ 13 , 2 , 1 ] \\ & \Rightarrow G_2^3(17)= 0 + \gamma 0+\gamma^2 1 =1 \\ &\\ & \Longrightarrow v_\pi(17) \approx \frac{G_0^1(17)+G_0^2(17)+G_2^3(17)}{3}\approx0.33 \end{aligned}
Episode 1:[17,3,−1]⇒G01(17)=−1Episode 2:[17,2,0][18,0,0][17,2,0][18,0,0][17,2,0][18,0,0][17,2,0][18,1,0][13,2,1]⇒G02(17)=0+γ0+γ20+γ30+γ40+γ50+γ60+γ70+γ81=1Episode 3:[16,0,0][15,0,0][15,0,0][15,2,0][16,0,0][15,1,−1]Episode 4:[19,0,0][18,0,0][17,2,0][18,1,0][13,2,1]⇒G23(17)=0+γ0+γ21=1⟹vπ(17)≈3G01(17)+G02(17)+G23(17)≈0.33
以下为首次访问型MC预测算法的伪代码:
\\[20pt]
3、蒙特卡罗ES(试探性出发)
我们使用状态-动作价值作为评价策略的标准,然后逐幕交替进行评估与改进。每一幕结束后,使用观测到的回报进行策略评估,然后在该幕序列访问到的每一个状态上进行策略的改进。使用该思想的方法叫基于试探性出发的蒙特卡罗,下面是伪代码:
以上的蒙特卡罗ES伪代码的效率并不高,因为对于每一个状态-动作二元组,都需要维护一个列表来存放所有的回报,然后重复的计算他们的平均值。鉴于此,我们可以使用增量更新的方式来计算
Q
(
S
t
,
A
t
)
Q(S_t,A_t)
Q(St,At),即
Q
n
(
S
t
,
A
t
)
=
1
n
∑
i
=
1
n
G
i
(
S
t
,
A
t
)
=
1
n
(
G
n
(
S
n
,
A
n
)
+
∑
i
=
1
n
−
1
G
i
(
S
t
,
A
t
)
)
=
1
n
(
G
n
(
S
n
,
A
n
)
+
(
n
−
1
)
1
n
−
1
∑
i
=
1
n
−
1
G
i
(
S
t
,
A
t
)
)
=
1
n
(
G
n
(
S
n
,
A
n
)
+
(
n
−
1
)
Q
n
−
1
(
S
t
,
A
t
)
)
=
Q
n
−
1
(
S
t
,
A
t
)
+
1
n
(
G
n
(
S
t
,
A
t
)
−
Q
n
−
1
(
S
t
,
A
t
)
)
\begin{aligned} Q_n(S_t,A_t) &= \frac{1}{n} \sum_{i=1}^n G_i(S_t,A_t)\\ &= \frac{1}{n} \left( G_n(S_n,A_n)+\sum_{i=1}^{n-1} G_i(S_t,A_t) \right)\\ &= \frac{1}{n} \left( G_n(S_n,A_n)+ (n-1) \frac{1}{n-1} \sum_{i=1}^{n-1} G_i(S_t,A_t) \right)\\ &= \frac{1}{n} \left( G_n(S_n,A_n)+ (n-1) Q_{n-1}(S_t,A_t) \right)\\ &= Q_{n-1}(S_t,A_t) +\frac{1}{n} (G_n(S_t, A_t) - Q_{n-1}(S_t,A_t)) \end{aligned}
Qn(St,At)=n1i=1∑nGi(St,At)=n1(Gn(Sn,An)+i=1∑n−1Gi(St,At))=n1(Gn(Sn,An)+(n−1)n−11i=1∑n−1Gi(St,At))=n1(Gn(Sn,An)+(n−1)Qn−1(St,At))=Qn−1(St,At)+n1(Gn(St,At)−Qn−1(St,At))
其中
G
n
(
S
t
,
A
t
)
G_n(S_t,A_t)
Gn(St,At)为第n次更新的目标。
若将这种增量更新方式应用在第2节的例子中,初始状态动作对
(
17
,
2
)
(17,2)
(17,2)的
Q
Q
Q函数
Q
0
(
17
,
2
)
=
0
Q_0(17,2)=0
Q0(17,2)=0,则更新过程如下:
Q
1
(
17
,
2
)
=
Q
0
(
17
,
2
)
+
1
1
(
G
1
(
17
,
2
)
−
Q
0
(
17
,
2
)
)
=
0
+
1
(
1
−
0
)
=
1
Q
2
(
17
,
2
)
=
Q
1
(
17
,
2
)
+
1
2
(
G
2
(
17
,
2
)
−
Q
1
(
17
,
2
)
)
=
1
+
0.5
(
1
−
1
)
=
1
\begin{aligned} &Q_1(17,2)= Q_0(17,2) +\frac{1}{1} (G_1(17, 2) - Q_0(17,2)) = 0+1(1-0)=1 \\ &Q_2(17,2)= Q_1(17,2) +\frac{1}{2} (G_2(17, 2) - Q_1(17,2)) = 1+0.5(1-1)=1\\ \end{aligned}
Q1(17,2)=Q0(17,2)+11(G1(17,2)−Q0(17,2))=0+1(1−0)=1Q2(17,2)=Q1(17,2)+21(G2(17,2)−Q1(17,2))=1+0.5(1−1)=1
\\[20pt]
4、在线策略首次访问型MC控制算法
对于在线策略方法来说,策略一般是“软性”的,即对于任意
s
∈
S
s\in \mathcal S
s∈S以及
a
∈
A
(
s
)
a\in \mathcal A(s)
a∈A(s),都有
π
(
a
∣
s
)
>
0
\pi(a|s)>0
π(a∣s)>0。但它们会逐渐地逼近一个确定性的策略。
ε
\varepsilon
ε-贪心策略是指在绝对大多数的时候采取最大动作价值函数所对应的动作,但同时以一个较小的
ε
\varepsilon
ε的概率来随机选择一个动作。在在线策略的MC控制算法中,我们采用
ε
\varepsilon
ε-软性策略来选择动作,即以
1
−
ε
+
ε
∣
A
(
s
)
∣
1-\varepsilon+\frac{\varepsilon}{|\mathcal A(s)|}
1−ε+∣A(s)∣ε的概率选择贪心动作,而以
ε
∣
A
(
s
)
∣
\frac{\varepsilon}{|\mathcal A(s)|}
∣A(s)∣ε的概率来选择非贪心动作。以下是在线策略的首次访问型MC控制算法伪代码:
\\[20pt]
5、采用在线策略首次访问型MC控制算法解决寻宝问题
仍然使用寻宝问题的例子来研究在线策略访问型MC控制算法的实施。设置 ε = 0.1 \varepsilon = 0.1 ε=0.1,折扣为1。
1)环境编写
这里只呈现环境的重置函数reset()和状态转移函数step()。【完整代码请单击此处】
- reset()函数的作用是重置环境为初始状态,这里我们初始环境状态为非终止状态,因为终止状态为初始状态的情况下无状态的转移。
def reset(self):
temp = copy.deepcopy(list(self.state_space.keys()))
temp = [list(state) for state in temp]
for state in self.terminate_space:
temp.remove(state)
self.current_state = temp[np.random.randint(0, len(temp))] # 随机初始化非终止状态
return self.current_state
- step()函数定义了状态的转移,智能体转移到宝藏状态时收益为1,此回合终止。智能体转移到陷阱时收益为-1,此回合终止。智能体转移到非终止状态时收益为0,此回合不终止。
def step(self, state, action):
next_state = (np.array(state) + self.ACTIONS[action]).tolist()
x, y = next_state
if next_state in self.treasure_space:
return next_state, 1, True
elif next_state in self.trap_space:
return next_state, -1, True
else:
if x < 0 or x >= self.GRID_SIZE or y < 0 or y >= self.GRID_SIZE:
next_state = state
return next_state, 0, False
2)算法实施
- 算法初始化
函数initialization()初始化算法,主要为: 1 ) 初 始 化 策 略 \textcolor{blue}{1)初始化策略} 1)初始化策略,对所有状态 s ∈ S = { 0 , 1 , 2 , . . . , 15 } s\in \mathcal S= \{0,1,2,...,15\} s∈S={0,1,2,...,15}以及动作 a ∈ A ( s ) = { 0 , 1 , 2 , 3 } a\in \mathcal A(s)=\{0,1,2,3\} a∈A(s)={0,1,2,3}。选择向左移动的概率为 1 − ε + ε ∣ A ( s ) ∣ = 1 − 0.1 + 0.1 4 = 0.925 1-\varepsilon+\frac{\varepsilon}{|\mathcal A(s)|}=1-0.1+\frac{0.1}{4}=0.925 1−ε+∣A(s)∣ε=1−0.1+40.1=0.925,向左为 ε \varepsilon ε-贪婪动作。 而选择其他非贪婪动作的概率为 ε ∣ A ( s ) ∣ = 0.1 4 = 0.025 \frac{\varepsilon}{|\mathcal A(s)|}=\frac{0.1}{4}=0.025 ∣A(s)∣ε=40.1=0.025。 2 ) 初 始 化 Q 表 \textcolor{blue}{2)初始化Q表} 2)初始化Q表,设置状态-动作对的价值函数为0。 3 ) 初 始 每 个 状 态 动 作 对 的 更 新 次 数 为 0 \textcolor{blue}{3)初始每个状态动作对的更新次数为0} 3)初始每个状态动作对的更新次数为0。
def initialization(self):
self.pi = [[1 - self.epsilon + self.epsilon/self.env.nA] for _ in range(self.env.nS)] # 选中贪心策略的概率 1-ε+ε/|A(s)|
for s in range(self.env.nS): # 初始其他动作的概率 ε/|A(s)|
for a in range(self.env.nA-1):
self.pi[s].append(self.epsilon/self.env.nA)
for i in range(self.env.GRID_SIZE):
for j in range(self.env.GRID_SIZE):
self.state_to_gridState.append([i, j])
for s in range(self.env.nS):
self.Q_table.append([0.] * self.env.nA)
self.Returns.append([] * self.env.nA)
self.state_action_count_list.append([0.] * self.env.nA)
- 生成一幕数据
generate_one_episode()函数用来生成一幕数据(即一个回合):1)状态列表state_list保存智能体在当前幕经过的所有状态。2)动作列表action_list保存当前状态所采取的动作。2)收益列表reward_list保存当前状态采取对应的动作后获得的收益。
注意第10行表示动作从一个概率分布中随机选择动作。
def generate_one_episode(self):
self.state_list = []
self.action_list = []
self.reward_list = []
state_grid = env.reset()
while True:
state = self.state_to_gridState.index(state_grid)
action_P = np.array(self.pi[state])
action = np.random.choice(np.arange(self.env.nA), p=action_P.ravel())
next_state, reward, done = self.env.step(state_grid, action)
self.load_one_transmission(state, action, reward)
state_grid = next_state
if done:
break
def load_one_transmission(self, state, action, reward):
self.state_list.append(state)
self.action_list.append(action)
self.reward_list.append(reward)
- 算法主体部分
函数run()实现了在线策略首次型MC控制算法。
第2行:算法初始化
第4行:生成一幕数据
第22-23行:以增量更新的方式更新Q表
def run(self):
self.initialization()
for episode in range(1, self.episode_number):
self.generate_one_episode()
state_action_list = []
for t in range(len(self.state_list)):
(s, a) = (self.state_list[t], self.action_list[t])
state_action_list.append((s, a))
G = 0.
for t in range(len(self.state_list)-1, -1, -1):
G = self.discount * G + self.reward_list[t]
state_action_list.pop()
S_t = self.state_list[t]
A_t = self.action_list[t]
if (S_t, A_t) not in state_action_list:
# self.Returns[S_t][A_t].append(G)
# self.Q_table[S_t][A_t] = np.average(self.Returns[S_t][A_t])
# 增量更新
self.state_action_count_list[S_t][A_t] += 1
self.Q_table[S_t][A_t] = self.Q_table[S_t][A_t] + (1. / self.state_action_count_list[S_t][A_t]) * (G - self.Q_table[S_t][A_t])
A_star= np.argmax(self.Q_table[S_t])
for a in range(self.env.nA):
if a == A_star:
self.pi[S_t][a] = 1 - self.epsilon + self.epsilon / self.env.nA
else:
self.pi[S_t][a] = self.epsilon / self.env.nA
print('Episode: {} | Total reward: {}'.format(episode, G))
return self.pi
3)结果展示
我们将所得策略展示出来,注意每次运行得到的策略可能有所不同。
↓ ↓ ↓ N ↓
→ → ↓ N ↓
N N → → N
→ → → → ↑
↑ ↑ N N N
4)完整代码
【完整代码请单击此处】
\\[30pt]
参考资料:
(1)Richard S. Sutton and Andrew G. Barto著, 俞凯译《强化学习》第二版
(2)张斯俊. 欢迎大家入坑Reinforcment Learning【知乎】
(3)郭宪, 方勇纯. 《深入浅出强化学习:原理入门》