目录
强化学习基本概念
强化学习即 Reinforcement Learning,而现在所说的强化学习更多的实际是深度强化学习。本篇先了解强化学习中的基本概念。
数学基础回顾
首先,我们回顾随机变量Random Variable,随机变量是一个未知的量,它的值取决于一个随机事件的结果。以硬币投掷为例:
我们将正面朝上记为0,反面为1,抛硬币是一个随机事件,抛硬币的结果记为随机变量
X
X
X,随机变量有两种取值情况(0或1),并且我们可以知道抛硬币结果的概率。
通常,我们用大写字母表示随机变量,用小写字母表示随机变量的观测值,观测值只是一个数值,没有随机性,比如我们抛硬币4次,可以记录以下4个观测值: x 1 = 1 , x 2 = 1 , x 3 = 0 , x 4 = 1 x_{1}=1,x_{2}=1,x_{3}=0,x_{4}=1 x1=1,x2=1,x3=0,x4=1下面我们了解概率密度函数(PDF,Probability Density Function),概率密度函数的物理意义为:PDF反映随机变量在某个确定取值点上的可能性。
比如高斯分布,高斯分布是连续概率分布,标准高斯分布的PDF为:
可以看出,在随机变量
X
X
X取值为0时的概率最大。
对于离散型的分布,假设随机变量取值为离散型(
X
∈
{
1
,
3
,
7
}
X\in\left\{1,3,7\right\}
X∈{1,3,7}),其PDF为:
可以将PDF描述为:
p
(
X
=
1
)
=
0.2
,
p
(
X
=
3
)
=
0.5
,
p
(
X
=
7
)
=
0.3
p(X=1)=0.2,p(X=3)=0.5,p(X=7)=0.3
p(X=1)=0.2,p(X=3)=0.5,p(X=7)=0.3。
假设随机变量 X X X的取值域为 χ \chi χ,如果随机变量为连续型,则有: ∫ χ p ( X = x ) d x = 1 \int_{\chi}p(X=x)dx=1 ∫χp(X=x)dx=1与 X X X相关的分布 f ( X ) f(X) f(X)的期望为: E [ f ( X ) ] = ∫ χ p ( X = x ) f ( x ) d x E[f(X)]=\int_{\chi}p(X=x)f(x)dx E[f(X)]=∫χp(X=x)f(x)dx
如果随机变量为离散型,则有:
∑
x
∈
χ
p
(
X
=
x
)
=
1
\sum_{x\in\chi}p(X=x)=1
x∈χ∑p(X=x)=1与
X
X
X相关的分布
f
(
X
)
f(X)
f(X)的期望为:
E
[
f
(
X
)
]
=
∑
x
∈
χ
p
(
X
=
x
)
f
(
x
)
E[f(X)]=\sum_{x\in\chi}p(X=x)f(x)
E[f(X)]=x∈χ∑p(X=x)f(x)
接下来了解随机抽样(Random Sampling),以黑箱摸球为例,假设一个箱子里有10个球:2个红球,5个绿球,3个蓝球。现在从中取一个球,我们想知道会摸出什么球。
所谓随机抽样就是从箱子中取出一个球,并观察到颜色,我们把这个过程叫做随机抽样。
我们可以借助Numpy.random下的choice函数模拟上述随机抽样,假设我们模拟100次(有放回):
from numpy.random import choice
samples=choice(['R','G','B'],size=100,p=[0.2,0.5,0.3])
print(samples)
"""
['R' 'G' 'R' 'G' 'G' 'G' 'B' 'G' 'G' 'G' 'B' 'G' 'R' 'B' 'G' 'B' 'G' 'B'
'G' 'B' 'G' 'G' 'G' 'G' 'B' 'B' 'B' 'G' 'G' 'G' 'R' 'G' 'G' 'R' 'B' 'G'
'G' 'B' 'B' 'G' 'B' 'B' 'R' 'G' 'B' 'B' 'B' 'B' 'R' 'R' 'B' 'B' 'G' 'B'
'G' 'G' 'G' 'G' 'G' 'B' 'G' 'R' 'R' 'G' 'G' 'R' 'G' 'G' 'G' 'G' 'B' 'G'
'B' 'R' 'R' 'G' 'B' 'G' 'G' 'G' 'G' 'G' 'G' 'G' 'G' 'R' 'G' 'R' 'G' 'G'
'B' 'G' 'G' 'B' 'G' 'G' 'G' 'B' 'G' 'G']
"""
强化学习中的专业术语
我们以《超级马里奥》为背景,认识强化学习中的专业术语。
首先,我们讲解state与action,我们可以认为state
s
s
s 就是当前游戏的一帧画面:
action则是智能体agent的行为,在强化学习中,动作action由谁发出,谁就是智能体,action
a
∈
{
l
e
f
t
,
r
i
g
h
t
,
u
p
}
a\in\left\{left,right,up\right\}
a∈{left,right,up}:
基于当前的state,agent做出某个action的过程被称为policy(策略)。函数policy
π
\pi
π 被定义为:
π
(
a
∣
s
)
=
p
(
A
=
a
∣
S
=
s
)
∈
[
0
,
1
]
\pi(a|s)=p(A=a|S=s)\in[0,1]
π(a∣s)=p(A=a∣S=s)∈[0,1]policy函数本质是一种概率密度函数,比如基于当前 state
s
s
s,我们有以下policy:
π
(
l
e
f
t
∣
s
)
=
0.2
,
π
(
r
i
g
h
t
∣
s
)
=
0.7
,
π
(
u
p
∣
s
)
=
0.1
\pi(left|s)=0.2,\pi(right|s)=0.7,\pi(up|s)=0.1
π(left∣s)=0.2,π(right∣s)=0.7,π(up∣s)=0.1这反映了agent会以0.7的概率选择动作right,以0.2的概率选择动作left,以0.1的概率选择动作up。具体采取的action由分布采样得到。
强化学习的本质就是学习policy函数,policy函数是指导机器根据state采取action的依据。
注意这些动作是具有随机性的(根据概率分布采样action),我们不索引max,而保留随机性,这有利于一些博弈问题,由于action的随机性,对手不能根据当前state准确预测出所采取的action,所以不能预判出下一个state的情况,同理不能顺序预测下一个state应该采取的action。
下面介绍奖励 reward R R R,奖励的设置由实际情况决定,比如我们可以设置:
- 马里奥收到一个金币,奖励为1: R = 1 R=1 R=1;
- 赢了当前游戏: R = 10000 R=10000 R=10000;
- 游戏失败: R = − 10000 R=-10000 R=−10000;
- 什么都没发生: R = 0 R=0 R=0;
state由于action触发到下一个state,该过程为状态转移 state transition。状态转移的随机性可以存在,也可以不存在,随机性是否存在取决于环境environment,比如:
比如我们让agent采取up的action,下一个state必然存在马里奥出现在上方的情况,但由于"环境"(即游戏程序)设置蘑菇怪 Goomba 会以0.8的概率向前走,0.2的概率向后走,这就导致下一个state并不是完全确定的,所以说此时的state具有随机性。
但不管是什么状态,我们总是用一帧图像描述。我们将状态记为随机变量 S S S,下一个状态记为随机变量 S ′ S^{'} S′,我们可将状态转移函数描述为概率密度函数: p ( s ′ ∣ s , a ) = p ( S ′ = s ′ ∣ S = s , A = a ) p(s'|s,a)=p(S'=s'|S=s,A=a) p(s′∣s,a)=p(S′=s′∣S=s,A=a)注意,状态转移函数只有环境能得到,玩家是不能得到的。
下面我们来了解:agent与environment的交互。
agent为马里奥,环境为游戏程序。状态
s
t
s_{t}
st由环境得到,我们可以将其定义为一帧图像。agent根据
s
t
s_{t}
st做出动作
a
t
a_{t}
at。
在agent做出
a
t
a_{t}
at后,环境会更新状态至
s
t
+
1
s_{t+1}
st+1,同时给agent奖励
r
t
r_{t}
rt。
强化学习中的随机性
明白强化学习中随机性的来源是必要的。
- 第一个随机性来源于action,给定状态
s
s
s,动作是随机的,用随机变量
A
A
A表示动作(
a
a
a表示观测值),根据policy函数进行随机抽样:
- 第二个随机性来自状态转移,我们可以描述为,给定状态
S
=
s
S=s
S=s,动作
A
=
a
A=a
A=a,环境会随机生成状态
S
′
∼
p
(
⋅
∣
s
,
a
)
S'\sim p(\cdot|s,a)
S′∼p(⋅∣s,a):
如何使用AI进行游戏
首先,我们利用强化学习获得policy函数 π \pi π,然后进行以下循环:
- 观测到当前状态(一帧图像) s 1 s_{1} s1;
- 由policy函数计算概率分布,随机抽样得到动作 a 1 a_{1} a1;
- 由环境生成下一个状态 s 2 s_{2} s2,同时环境返回给agent一个奖励 r 1 r_{1} r1;
- 由policy函数计算概率分布,随机抽样得到动作 a 2 a_{2} a2;
- 同理如上操作 ⋅ ⋅ ⋅ ⋅ ⋅ \cdot\cdot\cdot\cdot\cdot ⋅⋅⋅⋅⋅
在以上循环中,我们可以得到一个(state,action,reward)组成的轨迹: s 1 , a 1 , r 1 , s 2 , a 2 , r 2 , . . . , s T , a T , r T s_{1},a_{1},r_{1},s_{2},a_{2},r_{2},...,s_{T},a_{T},r_{T} s1,a1,r1,s2,a2,r2,...,sT,aT,rT
关于rewards和returns
rewards在前面已经提到过,是agent获得的奖励。而returns的定义是:cumulative future reward,即未来的累计奖励,returns被翻译为回报。我们将 t t t时刻的回报记为 U t U_{t} Ut: U t = R t + R t + 1 + R t + 2 + ⋅ ⋅ ⋅ U_{t}=R_{t}+R_{t+1}+R_{t+2}+\cdot\cdot\cdot Ut=Rt+Rt+1+Rt+2+⋅⋅⋅可以看出, U t U_{t} Ut为:从 t t t时刻奖励 R t R_{t} Rt一直求和至游戏结束时的奖励。
现在考虑一个问题: R t R_{t} Rt和 R t + 1 R_{t+1} Rt+1一样重要吗?
- 解释:一般,未来的奖励不如现在的奖励有价值,比如今天给我100美元和一年后给我100美元,我更倾向于选择今天就得到,因为未来的不确定性会让我怀疑一年后得不到100美元。
由于未来奖励的价值有削弱,所以我们更正回报,得到折扣回报的表达: U t = R t + γ R t + 1 + γ 2 R t + 2 + ⋅ ⋅ ⋅ U_{t}=R_{t}+\gamma R_{t+1}+\gamma^{2}R_{t+2}+\cdot\cdot\cdot Ut=Rt+γRt+1+γ2Rt+2+⋅⋅⋅其中, γ \gamma γ为折扣率,是一个超参数,折扣率的设置会对强化学习的表现产生影响。
下面分析一下回报计算中的随机性。
前面已经知道,随机性有两个来源:
- action A A A是随机的: p [ A = a ∣ S = s ] = π ( a ∣ s ) p[A=a|S=s]=\pi(a|s) p[A=a∣S=s]=π(a∣s);
- 新状态 S ′ S' S′是随机的: p [ S ′ = s ′ ∣ S = s , A = a ] = p ( s ′ ∣ s , a ) p[S'=s'|S=s,A=a]=p(s'|s,a) p[S′=s′∣S=s,A=a]=p(s′∣s,a);
注意到,对于 i ≥ t i\geq t i≥t,奖励 R i R_{i} Ri取决于 S i + 1 S_{i+1} Si+1和 A i A_{i} Ai,所以 R i R_{i} Ri也是随机的。因此,给定某个状态 S t = s t S_{t}=s_{t} St=st,该时刻的回报 U t U_{t} Ut也会是随机的, U t U_{t} Ut取决于下面的随机变量: A t , A t + 1 , . . . , S t + 1 , S t + 2 , . . . A_{t},A_{t+1},...,S_{t+1},S_{t+2},... At,At+1,...,St+1,St+2,...
价值函数Value Functions
action-value function
根据前面讲过的回报returns,我们可以很直接地希望获得一种策略,使得 t t t时刻的回报尽量大,但由于 U t U_{t} Ut是随机变量,因此,我们可以使其期望最大达到一个良好的游戏结果。回报的期望记作: Q π ( s t , a t ) = E [ U t ∣ S t = s t , A t = a t ] Q_{\pi}(s_{t},a_{t})=E[U_{t}|S_{t}=s_{t},A_{t}=a_{t}] Qπ(st,at)=E[Ut∣St=st,At=at]函数 Q π Q_{\pi} Qπ又被称为基于 π \pi π的 action-value function(动作-价值函数)。
注意, U t U_{t} Ut应该取决于随机变量: A t , A t + 1 , . . . , S t + 1 , S t + 2 , . . . A_{t},A_{t+1},...,S_{t+1},S_{t+2},... At,At+1,...,St+1,St+2,...,但在计算期望时,由于我们对后续不确定性的随机变量进行积分或求和,最终使得期望与初始观测值 s t s_{t} st和 a t a_{t} at,以及策略函数 π ( a ∣ s ) \pi(a|s) π(a∣s),状态转移函数 p ( s ′ ∣ s , a ) p(s'|s,a) p(s′∣s,a)有关。由于状态转移函数是环境决定的,故我们将动作-价值函数记作 Q π ( s t , a t ) Q_{\pi}(s_{t},a_{t}) Qπ(st,at)。
给定当前状态 s t s_{t} st和policy函数 π \pi π,通过计算 Q π ( s t , a t ) Q_{\pi}(s_{t},a_{t}) Qπ(st,at),我们可以得到不同 a t a_{t} at下的 U t U_{t} Ut的期望,从而可判断哪个动作可以获得更多回报。
补充一点:如果选择不同的policy函数,我们将得到不同的 Q π Q_{\pi} Qπ,我们可以选择最大的动作-价值函数,记作: Q ∗ ( s t , a t ) = m a x π Q π ( s t , a t ) Q^{*}(s_{t},a_{t})=max_{\pi}Q_{\pi}(s_{t},a_{t}) Q∗(st,at)=maxπQπ(st,at)函数 Q ∗ Q^{*} Q∗被称为optimal action-value function,即最优动作-价值函数。
state-value function
状态-价值函数即state-value function,它是action-value function关于动作的期望: V π ( s t ) = E A [ Q π ( s t , A ) ] V_{\pi}(s_{t})=E_{A}[Q_{\pi}(s_{t},A)] Vπ(st)=EA[Qπ(st,A)]状态-价值函数的意义在于: V π V_{\pi} Vπ可以反映当前状态的局势好坏,假设我们根据policy函数下围棋, V π V_{\pi} Vπ可以通过当前的棋盘状态告诉我们是快要胜利,还是快要失败。
如果动作是离散的,我们可以将state-value function表达为: V π ( s t ) = E A [ Q π ( s t , A ) ] = ∑ a π ( a ∣ s t ) Q π ( s t , a ) V_{\pi}(s_{t})=E_{A}[Q_{\pi}(s_{t},A)]=\sum_{a}\pi(a|s_{t})Q_{\pi}(s_{t},a) Vπ(st)=EA[Qπ(st,A)]=a∑π(a∣st)Qπ(st,a)如果动作是连续的,比如自动驾驶的方向盘角度(-90度到+90度之间的连续值),我们可以将state-value function表达为: V π ( s t ) = E A [ Q π ( s t , A ) ] = ∫ − 90 + 90 π ( a ∣ s t ) Q π ( s t , a ) d a V_{\pi}(s_{t})=E_{A}[Q_{\pi}(s_{t},A)]=\int_{-90}^{+90}\pi(a|s_{t})Q_{\pi}(s_{t},a)da Vπ(st)=EA[Qπ(st,A)]=∫−90+90π(a∣st)Qπ(st,a)da
关于价值函数的理解:
- 选择某个policy函数 π \pi π后,action-value function Q π ( s t , a t ) Q_{\pi}(s_{t},a_{t}) Qπ(st,at)可以告诉我们,在状态 s t s_{t} st下,agent选择动作 a t a_{t} at后获得的回报期望。
- state-value function V π ( s t ) V_{\pi}(s_{t}) Vπ(st)可以告诉我们,在状态 s t s_{t} st下,我们将要获胜的程度。很明显,如果状态越好,则 V π V_{\pi} Vπ的值会越大。
- 延申一下,其实我们可以用 V π V_{\pi} Vπ判断policy的好坏,如果策略函数 π \pi π越好,则期望 E S [ V π ( S ) ] E_{S}[V_{\pi}(S)] ES[Vπ(S)]越大。
再述用AI进行游戏
还是以超级玛丽为例:多捕捉金币,避开敌人,向前走,直到通关。我们要做的是写一个算法控制agent。我们可以有下面的方式:
第一种做法是学习policy函数 π ( a ∣ s ) \pi(a|s) π(a∣s),这属于强化学习中的策略学习(Policy-Based Learning),当我们获得策略后,进行以下操作:
- 观测当前状态 s t s_{t} st;
- 随机抽样: a t ∼ π ( ⋅ ∣ s t ) a_{t}\sim\pi(\cdot|s_{t}) at∼π(⋅∣st)。
另一种做法是学习最优动作-价值函数(optimal action-value function) Q ∗ ( s , a ) Q^{*}(s,a) Q∗(s,a),这属于强化学习中的价值学习(Value-Based Learning),当我们获得价值函数后,进行以下操作:
- 观测当前状态 s t s_{t} st;
- 选择 Q ∗ ( s , a ) Q^{*}(s,a) Q∗(s,a)最大化对应的动作: a t = a r g m a x a Q ∗ ( s t , a ) a_{t}=argmax_{a}Q^{*}(s_{t},a) at=argmaxaQ∗(st,a)。
关于第二种做法,进行下面的补充:对于 t t t时刻,我们可以使用不同的policy,这就导致我们可以计算出不同的回报期望 Q π ( s t , a ) Q_{\pi}(s_{t},a) Qπ(st,a),但我们选择 t t t时刻回报期望最大的policy,得到该时刻下,对于不同policy,选择动作 a a a的最大回报 Q ∗ ( s t , a ) Q^{*}(s_{t},a) Q∗(st,a),我们统计所有 a a a对应的 Q ∗ ( s t , a ) Q^{*}(s_{t},a) Q∗(st,a),取回报最大的那个action作为最优动作 a t a_{t} at。
关于OpenAI Gym
Gym 是一个用于开发和比较强化学习算法的工具包。它与各种数值计算库兼容,比如 tensorflow 和 Theano。Gym 库是测试问题(环境)的集合,我们可以使用它来制定强化学习算法。这些环境(environment)具有共享接口,允许我们编写通用算法。
Gym包含以下两个部分:
- Gym开源库:一个问题和环境的集合,用于提供测试强化学习算法的背景问题。
- Gym服务:一个API,用于对比训练后智能体的性能。
Gym的环境举例如下,有经典的控制问题:
也有小霸王游戏机里的游戏 Atari Games:
此处我以CartPole为例描述问题:黑色的小车可以在传送带上左右移动,我们给小车左右的力,使得小车上的木杆能够竖起来不倒下去。
Gym的安装简单:
pip install gym
在Python中调用Gym是容易的,我们以经典控制问题中的CartPole问题为例:
import gym
# 构造问题环境
env=gym.make('CartPole-v0')
# 环境重置,获取初始状态
state=env.reset()
for t in range(100):
# 渲染游戏,render会将当前state(一帧图像)以窗口可视化给我们看
env.render()
print(state)
# 随机均匀地抽样一个动作,本行语句其实是错误的,实际应该由pi函数或Q*函数算出action,而不是简单的直接均匀抽样
action=env.action_space.sample()
# agent发出action,环境更新state,并返回reward,同时有两个返回对象done(布尔)和info(字典),info是调试信息
state,reward,done,info=env.step(action)
# 如果done=1,代表游戏结束(赢了或者输了)
if done:
print('Finished')
break
# 环境销毁
env.close()