【Datawhale打卡】十一的时候自己看过一遍,李宏毅老师讲的很好,对数学小白也很友好,但是由于没有做笔记(敲代码),看完以后脑袋里空落落的。趁着这次打卡活动,重新看一遍,果然好多细节需要重头梳理一遍。
文章目录
- 1. 新概念/符号
- 2. 三个组成部分
- 3. Gradient Ascent
- 4. 实现/实做
- 4.1 TIP1 Add a Baseline
- 4.2 TIP2 Assign Suitable Credit
- 5. MC & TD
- 5.1 MC-REINFORCE
- 5.2 TD-Actor Critic
- 6. 问答
- 7. 参考
1. 新概念/符号
- policy(策略): 每一个actor中会有对应的策略,这个策略决定了actor的行为。(给定一个state,policy会决定action)。policy记为 π \pi π 。
- Return(回报): 一个回合(Episode)所得到的所有的reward的总和,也称为Total reward。一般地,用 R R R 来表示。
- Trajectory(轨迹 τ \tau τ ): 一个试验中将environment 输出的 s s s 跟 actor 输出的行为 a a a,把这个 s s s 跟 a a a 全部串起来形成的集合,称为Trajectory,即 Trajectory τ = { s 1 , a 1 , s 2 , a 2 , ⋯ , s t , a t } \text { Trajectory } \tau=\left\{s_{1}, a_{1}, s_{2}, a_{2}, \cdots, s_{t}, a_{t}\right\} Trajectory τ={s1,a1,s2,a2,⋯,st,at}。
- Reward function: 根据在某一个 state 采取的某一个 action 决定说现在这个行为可以得到多少的分数,它是一个 function。也就是给一个 s 1 s_1 s1, a 1 a_1 a1,它告诉你得到 r 1 r_1 r1。给它 s 2 s_2 s2 , a 2 a_2 a2,它告诉你得到 r 2 r_2 r2。 把所有的 r r r 都加起来,就得到了 R ( τ ) R(\tau) R(τ) ,代表某一个 trajectory τ \tau τ 的 reward。
- Expected reward: R ˉ θ = ∑ τ R ( τ ) p θ ( τ ) = E τ ∼ p θ ( τ ) [ R ( τ ) ] \bar{R}_{\theta}=\sum_{\tau} R(\tau) p_{\theta}(\tau)=E_{\tau \sim p_{\theta}(\tau)}[R(\tau)] Rˉθ=∑τR(τ)pθ(τ)=Eτ∼pθ(τ)[R(τ)]。
符号 | 解释 |
---|---|
τ \tau τ | 轨迹,游戏从开始到结束的s、a串( { s 1 , a 1 , s 2 , a 2 , ⋯ , s t , a t } \left\{s_{1}, a_{1}, s_{2}, a_{2}, \cdots, s_{t}, a_{t}\right\} {s1,a1,s2,a2,⋯,st,at}) |
episode | 一个游戏回合,从开始到结束 |
π \pi π | Policy 策略的代指符号 |
θ \theta θ | Policy π \pi π中的参数 |
2. 三个组成部分
强化学习通常有以下组成部分,actor, environment, reward。具体过程如上图所示,构成了一个完整的轨迹Trajectory:
Trajectory
τ
=
{
s
1
,
a
1
,
s
2
,
a
2
,
⋯
,
s
t
,
a
t
}
\text { Trajectory } \tau=\left\{s_{1}, a_{1}, s_{2}, a_{2}, \cdots, s_{t}, a_{t}\right\}
Trajectory τ={s1,a1,s2,a2,⋯,st,at}
每一个 trajectory,你可以计算它发生的概率。假设现在 actor 的参数已经被给定了话,就是
θ
\theta
θ。根据
θ
\theta
θ,你其实可以计算某一个 trajectory 发生的概率,你可以计算某一个回合,某一个 episode 里面, 发生这样子状况的概率。
p
θ
(
τ
)
=
p
(
s
1
)
p
θ
(
a
1
∣
s
1
)
p
(
s
2
∣
s
1
,
a
1
)
p
θ
(
a
2
∣
s
2
)
p
(
s
3
∣
s
2
,
a
2
)
⋯
=
p
(
s
1
)
∏
t
=
1
T
p
θ
(
a
t
∣
s
t
)
p
(
s
t
+
1
∣
s
t
,
a
t
)
\begin{aligned} p_{\theta}(\tau) &=p\left(s_{1}\right) p_{\theta}\left(a_{1} | s_{1}\right) p\left(s_{2} | s_{1}, a_{1}\right) p_{\theta}\left(a_{2} | s_{2}\right) p\left(s_{3} | s_{2}, a_{2}\right) \cdots \\ &=p\left(s_{1}\right) \prod_{t=1}^{T} p_{\theta}\left(a_{t} | s_{t}\right) p\left(s_{t+1} | s_{t}, a_{t}\right) \end{aligned}
pθ(τ)=p(s1)pθ(a1∣s1)p(s2∣s1,a1)pθ(a2∣s2)p(s3∣s2,a2)⋯=p(s1)t=1∏Tpθ(at∣st)p(st+1∣st,at)
注:以上的P函数分为两种!
1 p ( s t + 1 ∣ s t , a t ) p\left(s_{t+1} | s_{t}, a_{t}\right) p(st+1∣st,at)函数代表环境,当前环境,如果在状态st下使用at,转化到 s t + 1 s_{t+1} st+1的概率。
2 p θ ( a t ∣ s t ) p_{\theta}(a_t|s_t) pθ(at∣st)函数代表actor/agent的policy,如果在状态st下使用at的概率。
Reward Function: 根据在某一个 state 采取的某一个 action 决定说现在这个行为可以得到多少的分数。
给它
s
1
s_1
s1,
a
1
a_1
a1,它告诉你得到
r
1
r_1
r1。给它
s
2
s_2
s2 ,
a
2
a_2
a2,它告诉你得到
r
2
r_2
r2。 把所有的
r
r
r 都加起来,就得到了
R
(
τ
)
R(\tau)
R(τ) , 目标就是通过调整actor的参数
θ
\theta
θ, 让R的值越大越好。由于actor采取action的时候存在随机性,所以R也是一个随机变量,采用以下公式估计其期望值:
R
ˉ
θ
=
∑
τ
R
(
τ
)
p
θ
(
τ
)
=
E
τ
∼
p
θ
(
τ
)
[
R
(
τ
)
]
\bar{R}_{\theta}=\sum_{\tau} R(\tau) p_{\theta}(\tau)=E_{\tau \sim p_{\theta}(\tau)}[R(\tau)]
Rˉθ=τ∑R(τ)pθ(τ)=Eτ∼pθ(τ)[R(τ)]
这个计算方式也就是:穷举所有可能的 trajectory
τ
\tau
τ, 每一个 trajectory
τ
\tau
τ 都有一个概率。同时也可以表达为期望的形式,从
p
θ
(
τ
)
p_{\theta}(\tau)
pθ(τ) 这个 distribution sample 一个 trajectory
τ
\tau
τ,然后计算
R
(
τ
)
R(\tau)
R(τ) 的期望值,就是你的 expected reward。 目标就是 maximize expected reward。
3. Gradient Ascent
对以下式子希望得到maximize expected reward, 要使用Gradient Ascent算法,先计算R的梯度gradient。
R
ˉ
θ
=
∑
τ
R
(
τ
)
p
θ
(
τ
)
\bar{R}_{\theta}=\sum_{\tau} R(\tau) p_{\theta}(\tau)
Rˉθ=τ∑R(τ)pθ(τ)
由于只有
p
θ
(
τ
)
p_{\theta}(\tau)
pθ(τ)是和参数
θ
\theta
θ相关的,所以梯度只需要对这部分求即可。
存在以下公式:
由:
d
(
l
n
x
)
d
x
=
1
x
\frac{d(lnx)}{dx}=\frac{1}{x}
dxd(lnx)=x1
得:
∇
f
(
x
)
=
f
(
x
)
∇
l
o
g
f
(
x
)
\nabla f(x)=f(x)\nabla logf(x)
∇f(x)=f(x)∇logf(x)
所以带入
p
θ
p_\theta
pθ以后有:
∇
p
θ
(
τ
)
p
θ
(
τ
)
=
∇
l
o
g
p
θ
(
τ
)
\frac{\nabla p_\theta(\tau)}{p_\theta(\tau)}=\nabla log p_\theta(\tau)
pθ(τ)∇pθ(τ)=∇logpθ(τ)
推导过程如下:
∇
R
ˉ
θ
=
∑
τ
R
(
τ
)
∇
p
θ
(
τ
)
=
∑
τ
R
(
τ
)
p
θ
(
τ
)
∇
p
θ
(
τ
)
p
θ
(
τ
)
=
∑
τ
R
(
τ
)
p
θ
(
τ
)
∇
log
p
θ
(
τ
)
=
E
τ
∼
p
θ
(
τ
)
[
R
(
τ
)
∇
log
p
θ
(
τ
)
]
\begin{aligned} \nabla \bar{R}_{\theta}&=\sum_{\tau} R(\tau) \nabla p_{\theta}(\tau)\\&=\sum_{\tau} R(\tau) p_{\theta}(\tau) \frac{\nabla p_{\theta}(\tau)}{p_{\theta}(\tau)} \\&= \sum_{\tau} R(\tau) p_{\theta}(\tau) \nabla \log p_{\theta}(\tau) \\ &=E_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right] \end{aligned}
∇Rˉθ=τ∑R(τ)∇pθ(τ)=τ∑R(τ)pθ(τ)pθ(τ)∇pθ(τ)=τ∑R(τ)pθ(τ)∇logpθ(τ)=Eτ∼pθ(τ)[R(τ)∇logpθ(τ)]
最终是一个期望,这个期望无法直接计算,只能通过sample一些轨迹
τ
\tau
τ, 求解器平均值来计算梯度,有了梯度以后就可以更新参数,具体公式如下:
E
τ
∼
p
θ
(
τ
)
[
R
(
τ
)
∇
log
p
θ
(
τ
)
]
≈
1
N
∑
n
=
1
N
R
(
τ
n
)
∇
log
p
θ
(
τ
n
)
=
1
N
∑
n
=
1
N
∑
t
=
1
T
n
R
(
τ
n
)
∇
log
p
θ
(
a
t
n
∣
s
t
n
)
\begin{aligned} E_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right] &\approx \frac{1}{N} \sum_{n=1}^{N} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(\tau^{n}\right) \\ &=\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) \end{aligned}
Eτ∼pθ(τ)[R(τ)∇logpθ(τ)]≈N1n=1∑NR(τn)∇logpθ(τn)=N1n=1∑Nt=1∑TnR(τn)∇logpθ(atn∣stn)
注: p θ ( τ ) p_{\theta}(\tau) pθ(τ) 里面有两项, p ( s t + 1 ∣ s t , a t ) p(s_{t+1}|s_t,a_t) p(st+1∣st,at) 来自于 environment, p θ ( a t ∣ s t ) p_\theta(a_t|s_t) pθ(at∣st) 是来自于 agent。
p ( s t + 1 ∣ s t , a t ) p(s_{t+1}|s_t,a_t) p(st+1∣st,at) 由环境决定从而与 θ \theta θ 无关,因此 ∇ log p ( s t + 1 ∣ s t , a t ) = 0 \nabla \log p(s_{t+1}|s_t,a_t) =0 ∇logp(st+1∣st,at)=0。因此 ∇ p θ ( τ ) = ∇ log p θ ( a t n ∣ s t n ) \nabla p_{\theta}(\tau)= \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right) ∇pθ(τ)=∇logpθ(atn∣stn)。
然后对推导得到的最终结果进行定性解释:
-
在sample到的轨迹中,某一个状态 s t s_t st, 要执行动作 a t a_t at。
-
如果 R ( τ ) R(\tau) R(τ)是正的,那就要增加 ( s t , a t ) (s_t,a_t) (st,at)的概率,让actor能够在下一次遇到 s t s_t st以后能以更高的概率选中 a t a_t at。
-
为负同理。
4. 实现/实做
具体实现过程如下:
θ
←
θ
+
η
∇
R
θ
ˉ
∇
R
θ
ˉ
=
1
N
∑
n
=
1
N
∑
t
=
1
T
n
R
(
τ
n
)
∇
l
o
g
p
θ
(
a
t
n
∣
s
t
n
)
\theta \leftarrow \theta+\eta \nabla \bar{R_\theta} \\ \nabla \bar{R_\theta}=\frac{1}{N}\sum^N_{n=1}\sum^{T_n}_{t=1}R(\tau^n)\nabla log p_\theta(a_t^n|s_t^n)
θ←θ+η∇Rθˉ∇Rθˉ=N1n=1∑Nt=1∑TnR(τn)∇logpθ(atn∣stn)
还需要收集一系列s和a的pair,以及对应的reward。将sample得到的s和a组成的pair带入到上面的gradient的式子中,然后计算其log probablitiy,然后取gradient,然后就可以进行更新了。
这一点和分类问题中的交叉熵有一点类似,可以按照以下方法进行理解:
标签值
×
l
o
g
(
标签对应的概率
)
\text{标签值}\times log(\text{标签对应的概率})
标签值×log(标签对应的概率)
这样就和以上做到了形式上的一致(不是很严谨)。RL和一般分类问题不同的地方是loss前面乘上了weight R。
在这里会需要乘以一个奖励回报 R R R。这个奖励回报相当于是对这个真实 action 的评价, R R R 具体越大,未来总收益越大,说明当前输出的这个真实的 action 就越好,这个 loss 就越需要重视。如果 R R R 越小,那就说明做这个 action a t a_t at 并没有那么的好,loss 的权重就要小一点,优化力度就小一点。
4.1 TIP1 Add a Baseline
θ ← θ + η ∇ R θ ˉ ∇ R θ ˉ = 1 N ∑ n = 1 N ∑ t = 1 T n ( R ( τ n ) − b ) ∇ l o g p θ ( a t n ∣ s t n ) b ≈ E [ R ( τ ) ] \theta \leftarrow \theta+\eta \nabla \bar{R_\theta} \\ \nabla \bar{R_\theta}=\frac{1}{N}\sum^N_{n=1}\sum^{T_n}_{t=1}(R(\tau^n)-b)\nabla log p_\theta(a_t^n|s_t^n) \\ b \approx E[R(\tau)] θ←θ+η∇Rθˉ∇Rθˉ=N1n=1∑Nt=1∑Tn(R(τn)−b)∇logpθ(atn∣stn)b≈E[R(τ)]
如果某些样本没有sample到,那其他动作的概率都会提升,它本身概率会下降,这就存在问题了,可以通过添加一个baseline,让reward不总是正的值。
4.2 TIP2 Assign Suitable Credit
下面这个式子的话,
∇ R ˉ θ ≈ 1 N ∑ n = 1 N ∑ t = 1 T n ( R ( τ n ) − b ) ∇ log p θ ( a t n ∣ s t n ) \nabla \bar{R}_{\theta} \approx \frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}}\left(R\left(\tau^{n}\right)-b\right) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) ∇Rˉθ≈N1n=1∑Nt=1∑Tn(R(τn)−b)∇logpθ(atn∣stn)
原来会做的事情是,在某一个 state,假设你执行了某一个 action a,它得到的 reward ,它前面乘上的这一项 R ( τ n ) − b R(\tau^n)-b R(τn)−b, 这个值就可以理解为,当前s下使用动作a以后的好坏程度。
R ( τ n ) R(\tau^n) R(τn) 代表整个episode执行完以后得到的结果,由于强化学习具有延迟奖励的特点,可以考虑以下改进:更关注于近期得到的奖励,长远奖励要被削弱。这个想法实现如下:
∇ R ˉ θ ≈ 1 N ∑ n = 1 N ∑ t = 1 T n ( ∑ t ′ = t T n γ t ′ − t r t ′ n − b ) ∇ log p θ ( a t n ∣ s t n ) \nabla \bar{R}_{\theta} \approx \frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}}\left(\sum_{t'=t}^{T_n}\gamma^{t'-t}r_{t'}^n-b\right) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) ∇Rˉθ≈N1n=1∑Nt=1∑Tn(t′=t∑Tnγt′−trt′n−b)∇logpθ(atn∣stn)
其中 γ \gamma γ代表的是0-1之间的小数,用于削弱长远的奖励,这就是discount fastor:
- 一般会设个 0.9 或 0.99,
- γ = 0 \gamma = 0 γ=0 : 只关心即时奖励;
- γ = 1 \gamma = 1 γ=1 : 未来奖励等同于即时奖励。
然后就可以顺利引入Advantage Function,这个函数是依赖于状态s和动作a的,如下所示:
A θ ( s t , a t ) A^\theta(s_t,a_t) Aθ(st,at)
代表在 s t s_t st状态下执行动作 a t a_t at到底有多好,可以带来多大的奖励。这个”好“代表的是相对优势,因为会减掉baseline,这个函数通常可以是由一个network(critic)估计出来的。
5. MC & TD
策略梯度可以用蒙特卡洛算法(MC)或者时序差分算法(TD)求解。
5.1 MC-REINFORCE
蒙特卡洛算法是回合更新,常见算法是REINFORCE。
∇ R ˉ θ ≈ 1 N ∑ n = 1 N ∑ t = 1 T n G t n ∇ log p θ ( a t n ∣ s t n ) \nabla \bar{R}_{\theta} \approx \frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}}G_t^n \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) ∇Rˉθ≈N1n=1∑Nt=1∑TnGtn∇logpθ(atn∣stn)
可以理解为完成一个episode以后,拿这个episode的数据去学习,然后做一次更新。
G t G_t Gt 是未来总收益, G t G_t Gt 代表是从这个 step 后面,能拿到的收益之和是多少。
在代码上的处理上是先拿到每个 step 的 reward,然后计算每个 step 的未来总收益 G t G_t Gt 是多少,然后拿每个 G t G_t Gt 代入公式,去优化每一个 action 的输出。
编写代码时会有这样一个函数,输入每个 step 拿到的 reward,把这些 reward 转成每一个 step 的未来总收益。因为未来总收益是这样计算的:
G
t
=
∑
k
=
t
+
1
T
γ
k
−
t
−
1
r
k
=
r
t
+
1
+
γ
G
t
+
1
\begin{aligned} G_{t} &=\sum_{k=t+1}^{T} \gamma^{k-t-1} r_{k} \\ &=r_{t+1}+\gamma G_{t+1} \end{aligned}
Gt=k=t+1∑Tγk−t−1rk=rt+1+γGt+1
先产生一个 episode 的数据,比如 ( s 1 , a 1 , G 1 ) , ( s 2 , a 2 , G 2 ) , ⋯ , ( s T , a T , G T ) (s_1,a_1,G_1),(s_2,a_2,G_2),\cdots,(s_T,a_T,G_T) (s1,a1,G1),(s2,a2,G2),⋯,(sT,aT,GT)。然后针对每个 action 来计算梯度。
在代码上计算时,要拿到神经网络的输出。神经网络会输出每个 action 对应的概率值,然后还可以拿到实际的 action,把它转成 one-hot 向量乘一下,可以拿到 ln π ( A t ∣ S t , θ ) \ln \pi(A_t|S_t,\theta) lnπ(At∣St,θ) 。
5.2 TD-Actor Critic
时序差分是单步更新,更新频率更高,这里用Q-function来近似表示未来的收益。
∇ R ˉ θ ≈ 1 N ∑ n = 1 N ∑ t = 1 T n Q n ( s t n , a t n ) ∇ log p θ ( a t n ∣ s t n ) \nabla \bar{R}_{\theta} \approx \frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}}Q^n(s_t^n,a^n_t) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) ∇Rˉθ≈N1n=1∑Nt=1∑TnQn(stn,atn)∇logpθ(atn∣stn)
时序差分强化学习能够在知道结果之前就开始学习,相比蒙特卡洛强化学习,其更快速、灵活。
6. 问答
Q: 在一个process中,一个具体的trajectory s 1 s_1 s1, a 1 a_1 a1, s 2 s_2 s2 , a 2 a_2 a2 出现的概率取决于什么?
A:
- 一部分是 environment 的行为, environment 的 function 它内部的参数或内部的规则长什么样子。 p ( s t + 1 ∣ s t , a t ) p(s_{t+1}|s_t,a_t) p(st+1∣st,at)这一项代表的是 environment, environment 这一项通常你是无法控制它的,因为那个是人家写好的,或者已经客观存在的。
- 另一部分是 agent 的行为,你能控制的是 p θ ( a t ∣ s t ) p_\theta(a_t|s_t) pθ(at∣st)。给定一个 s t s_t st, actor 要采取什么样的 a t a_t at 会取决于你 actor 的参数 θ \theta θ, 所以这部分是 actor 可以自己控制的。随着 actor 的行为不同,每个同样的 trajectory, 它就会有不同的出现的概率。
Q: 可以使用哪些方法来进行gradient ascent的计算?
A:用 gradient ascent 来 update 参数,对于原来的参数 θ \theta θ ,可以将原始的 θ \theta θ 加上更新的 gradient 这一项,再乘以一个 learning rate,learning rate 其实也是要调的,和神经网络一样,可以使用 Adam、RMSProp 等优化器对其进行调整。
Q: Advantage Function作用:
A: 在某一个 state s t s_t st 执行某一个 action a t a_t at,相较于其他可能的 action,它有多好。它在意的不是一个绝对的好,而是相对的好,即相对优势(relative advantage)。因为会减掉一个 b,减掉一个 baseline, 所以这个东西是相对的好,不是绝对的好。 A θ ( s t , a t ) A^{\theta}\left(s_{t}, a_{t}\right) Aθ(st,at) 通常可以是由一个 network estimate 出来的,这个 network 叫做 critic。
Q:对于梯度策略的两种方法,蒙特卡洛(MC)强化学习和时序差分(TD)强化学习两个方法有什么联系和区别
A: 两者的更新频率不同,蒙特卡洛强化学习方法是每一个episode更新一次,即需要经历完整的状态序列后再更新(比如贪吃蛇游戏,贪吃蛇“死了”游戏结束后再更新)
对于时序差分强化学习方法是每一个step就更新一次 ,(比如贪吃蛇游戏,贪吃蛇每移动一次(或几次)就进行更新)。相对来说,时序差分强化学习方法比蒙特卡洛强化学习方法更新的频率更快。
时序差分强化学习能够在知道一个小step后就进行学习,相比于蒙特卡洛强化学习,其更加快速、灵活。