【强化学习笔记1】从强化学习的基本概念到近端策略优化(PPO)
好久没有更新了。最近想学习一下强化学习,本系列是李宏毅老师强化学习的课程笔记。
1. Policy-based Model
1.1 Actor
在policy-based model中,主要的目的就是训练一个actor。
对于一个episode(例如,玩一局游戏),agent的observation、action和reward组成这样一个序列:
τ
=
{
s
1
,
a
1
,
r
1
,
.
.
.
,
s
T
,
a
T
,
r
T
}
\tau = \{s_1,a_1,r_1,...,s_T,a_T,r_T\}
τ={s1,a1,r1,...,sT,aT,rT}
上面的s可以理解为环境的State,那么做N次episode,所有的reward的和是
R
(
τ
)
=
∑
n
=
1
N
r
n
R(\tau) = \sum_{n=1}^Nr_n
R(τ)=n=1∑Nrn
对于模型的一个参数
θ
,
τ
\theta, \tau
θ,τ取到的概率实际上与\theta有关系:
P
(
τ
∣
θ
)
P(\tau|\theta)
P(τ∣θ)
然后我们关心的是一个episode的reward的期望:
R
ˉ
θ
=
∑
τ
R
(
τ
)
P
(
τ
∣
θ
)
\bar{R}_{\theta}=\sum_\tau R(\tau)P(\tau|\theta)
Rˉθ=τ∑R(τ)P(τ∣θ)
那么怎么去训练这个模型?推导过程如下:
∇
θ
R
ˉ
θ
=
∑
τ
R
(
τ
)
∇
θ
P
(
τ
∣
θ
)
(
所以梯度与
R
(
τ
)
无关,它不需要可微,甚至可以是一个黑盒
)
(
∇
x
log
f
(
x
)
=
1
f
(
x
)
∇
x
f
(
x
)
)
=
∑
τ
R
(
τ
)
P
(
τ
∣
θ
)
∇
x
log
P
(
τ
∣
θ
)
根据大数定律
,
当样本足够多时,样本均值依概率收敛于总体均值,即
μ
=
∑
τ
R
(
τ
)
P
(
τ
∣
θ
)
≈
X
ˉ
=
1
/
N
∑
i
=
1
N
R
(
τ
i
)
因此
原式
≈
1
/
N
∑
i
=
1
N
R
(
τ
i
)
∇
θ
log
P
(
τ
∣
θ
)
\nabla_\theta\bar{R}_{\theta}=\sum_\tau R(\tau)\nabla_\theta P(\tau|\theta) \\ (所以梯度与R(\tau)无关,它不需要可微,甚至可以是一个黑盒) \\ (\nabla_x \log f(x)=\frac{1}{f(x)} \nabla_x f(x)) =\sum_\tau R(\tau)P(\tau|\theta)\nabla_x \log P(\tau|\theta) \\ 根据大数定律, 当样本足够多时,样本均值依概率收敛于总体均值,即\mu=\sum_\tau R(\tau)P(\tau|\theta)\approx \bar{X} = 1/N\sum_{i=1}^N R(\tau_i) \\ 因此 \\ 原式\approx 1/N \sum_{i=1}^N R(\tau_i) \nabla_\theta \log P(\tau|\theta)
∇θRˉθ=τ∑R(τ)∇θP(τ∣θ)(所以梯度与R(τ)无关,它不需要可微,甚至可以是一个黑盒)(∇xlogf(x)=f(x)1∇xf(x))=τ∑R(τ)P(τ∣θ)∇xlogP(τ∣θ)根据大数定律,当样本足够多时,样本均值依概率收敛于总体均值,即μ=τ∑R(τ)P(τ∣θ)≈Xˉ=1/Ni=1∑NR(τi)因此原式≈1/Ni=1∑NR(τi)∇θlogP(τ∣θ)
那么
∇
θ
log
P
(
τ
∣
θ
)
\nabla_\theta \log P(\tau|\theta)
∇θlogP(τ∣θ)
怎么算?
将一个episode拆解开,实际上就是每次的1. 根据环境的state做出action,2. 环境根据action和上一次的state给出下一次的state和当前的reward:
P
(
τ
∣
θ
)
=
p
(
s
1
)
p
(
a
1
∣
s
1
,
θ
)
p
(
s
2
,
r
1
∣
s
1
,
a
1
)
.
.
.
p
(
a
k
∣
s
k
,
θ
)
p
(
s
k
+
1
,
r
k
∣
s
k
,
a
k
)
.
.
.
=
p
(
s
1
)
⋅
Π
t
=
1
T
p
(
a
t
∣
s
t
,
θ
)
p
(
s
t
+
1
,
r
t
∣
s
t
,
a
t
)
P(\tau|\theta)=p(s_1)p(a_1|s_1,\theta)p(s_2,r_1|s_1,a_1)...p(a_k|s_k,\theta)p(s_{k+1},r_k|s_k,a_k)... \\ =p(s_1)\cdot \Pi_{t=1}^Tp(a_t|s_t,\theta)p(s_{t+1},r_t|s_t,a_t)
P(τ∣θ)=p(s1)p(a1∣s1,θ)p(s2,r1∣s1,a1)...p(ak∣sk,θ)p(sk+1,rk∣sk,ak)...=p(s1)⋅Πt=1Tp(at∣st,θ)p(st+1,rt∣st,at)
有连乘,取对数:
log
P
(
τ
∣
θ
)
=
log
p
(
s
1
)
+
∑
t
[
log
p
(
a
t
∣
s
t
,
θ
)
+
log
p
(
s
t
+
1
,
r
t
∣
s
t
,
a
t
)
]
\log P(\tau|\theta)=\log p(s_1) + \sum_t[ \log p(a_t|s_t,\theta) + \log p(s_{t+1},r_t|s_t,a_t)]
logP(τ∣θ)=logp(s1)+t∑[logp(at∣st,θ)+logp(st+1,rt∣st,at)]
所以
∇
θ
log
P
(
τ
∣
θ
)
=
∑
t
∇
θ
log
p
(
a
t
∣
s
t
,
θ
)
\nabla_\theta \log P(\tau|\theta) = \sum_t \nabla_\theta \log p(a_t|s_t,\theta)
∇θlogP(τ∣θ)=t∑∇θlogp(at∣st,θ)
最终的梯度更新方式为:
∇
θ
R
ˉ
θ
=
1
/
N
∑
i
=
1
N
R
(
τ
i
)
∑
t
∇
θ
log
p
(
a
t
∣
s
t
,
θ
)
\nabla_\theta\bar{R}_{\theta}=1/N \sum_{i=1}^N R(\tau_i)\sum_t \nabla_\theta \log p(a_t|s_t,\theta)
∇θRˉθ=1/Ni=1∑NR(τi)t∑∇θlogp(at∣st,θ)
Reward越大越好,所以实际上上面这个式子也是越大越好。上述这种梯度计算的方式是显然的:
-
对于一个episode,如果它最终的reward R ( τ i ) R(\tau_i) R(τi) 为正,那么我们肯定希望在这个episode中的每一个决策出现的概率都足够大;反之,如果reward为负,那么我们希望概率足够低。
-
为什么要用 log \log log的梯度,而不直接是 ∇ θ p ( a t ∣ s t , θ ) \nabla_\theta p(a_t|s_t,\theta) ∇θp(at∣st,θ)? 这是因为,假如出现了下面这种情况,即状态 s s s在4个episode中都出现过,actor的反应和得到的reward如下图:
所以,模型会偏好出现次数多的action,因为虽然出现次数多的action,reward不一定很大,但是相加起来依旧可以增大最后的reward。所以,要对“出现次数”进行某种“归一化”,也就是除以概率就好: ∇ θ p ( a t ∣ s t , θ ) p ( a t ∣ s t , θ ) = ∇ θ log p ( a t ∣ s t , θ ) \frac{\nabla_\theta p(a_t|s_t,\theta)}{p(a_t|s_t,\theta)} = \nabla_\theta \log p(a_t|s_t,\theta) p(at∣st,θ)∇θp(at∣st,θ)=∇θlogp(at∣st,θ).
在通常情况下,为了避免Reward在啥时候都是正数的情况,需要减去一个bias,让Reward有正有负:
∇
θ
R
ˉ
θ
=
1
/
N
∑
i
=
1
N
(
R
(
τ
i
)
−
b
)
∑
t
∇
θ
log
p
(
a
t
∣
s
t
,
θ
)
=
1
/
N
∑
i
=
1
N
∑
t
(
R
(
τ
i
)
−
b
)
∇
θ
log
p
(
a
t
∣
s
t
,
θ
)
\nabla_\theta\bar{R}_{\theta}=1/N \sum_{i=1}^N (R(\tau_i) - b)\sum_t \nabla_\theta \log p(a_t|s_t,\theta) \\ = 1/N \sum_{i=1}^N \sum_t (R(\tau_i) - b)\nabla_\theta \log p(a_t|s_t,\theta)
∇θRˉθ=1/Ni=1∑N(R(τi)−b)t∑∇θlogp(at∣st,θ)=1/Ni=1∑Nt∑(R(τi)−b)∇θlogp(at∣st,θ)
然而,上面这个公式还有一点点问题。在一条轨迹中所有的动作都具有同样的价值。然而从直觉上来看,一条轨迹中一般不会所有的动作都是好的,而是有些动作好,而另外一些动作差,然而这些动作目前却会以相同的方式更新概率,这也会造成训练的不稳定。因此有必要为每个动作赋予其所应得的奖励。考虑到交互过程中 Actor 采取某一动作只会对之后的状态产生影响,而不会对之前的有影响。因此,不必令每个动作的权重都为全部奖励之和,而只需要累计在当前动作之后的奖励之和 R ( τ i ) = ∑ t ′ = t T i r t ′ i R(\tau_i)=\sum_{t'=t}^{T_i}r_{t'}^{i} R(τi)=∑t′=tTirt′i, 其中 T n T_n Tn是第 i i i个trajectory的长度, r t ′ i r_{t'}^{i} rt′i表示第 i i i个trajectory中时刻 t ′ t' t′的环境真实奖励。
另一个直觉是,当前动作会对时间较近的状态影响大,时间较远的影响小。因此,在计算累计奖励的时候,对于未来较遥远的奖励应该予以折扣,因此
R
(
τ
i
)
=
∑
t
′
=
t
T
i
γ
t
′
−
t
r
t
′
i
R(\tau_i)=\sum_{t'=t}^{T_i} \gamma^{t'-t} r_{t'}^{i}
R(τi)=t′=t∑Tiγt′−trt′i
最终的梯度更新公式为:
∇
θ
R
ˉ
θ
=
1
/
N
∑
i
=
1
N
∑
t
(
∑
t
′
=
t
T
i
γ
t
′
−
t
r
t
′
i
−
b
)
∇
θ
log
p
(
a
t
∣
s
t
,
θ
)
\nabla_\theta\bar{R}_{\theta} = 1/N \sum_{i=1}^N \sum_t (\sum_{t'=t}^{T_i} \gamma^{t'-t} r_{t'}^{i} - b)\nabla_\theta \log p(a_t|s_t,\theta)
∇θRˉθ=1/Ni=1∑Nt∑(t′=t∑Tiγt′−trt′i−b)∇θlogp(at∣st,θ)
1.2 Critic
Critic并不决定action,其负责评价action的好坏,表示为 V π ( s ) V^\pi(s) Vπ(s), 意思是用一个actor π \pi π,在当前状态为 s s s的情况下,从现在到一个episode结束累积的Reward的期望是多少.
如何估计Critic?
- 蒙特卡洛方法: 让Critic看actor玩游戏, 当前state为 s s s时,在游戏结束的Reward总和为 r r r,所以这就是一个回归问题. 让Critic输入为 s s s时,输出为 r r r.
- 时序差分方法: 对于序列中的 s t , a t , r t , s t + 1 s_t,a_t,r_t,s_{t+1} st,at,rt,st+1, 有递归关系 V π ( s t ) = V π ( s t + 1 ) + r t V^\pi(s_t)=V^\pi(s_{t+1})+r_t Vπ(st)=Vπ(st+1)+rt,也就是说 V π ( s t ) − V π ( s t + 1 ) = r t V^\pi(s_t)-V^\pi(s_{t+1})=r_t Vπ(st)−Vπ(st+1)=rt, 因此,只需要在Critic网络中,输入 s t s_t st得到 V π ( s t ) V^\pi(s_t) Vπ(st),输入 s t + 1 s_{t+1} st+1得到 V π ( s t + 1 ) V^\pi(s_{t+1}) Vπ(st+1),然后约束是让 V π ( s t ) − V π ( s t + 1 ) V^\pi(s_t)-V^\pi(s_{t+1}) Vπ(st)−Vπ(st+1)接近 r r r. 这样的好处就是不需要等整个游戏结束之后再计算Critic.
还有一种Critic的方式, 称之为Q-function, 定义是 Q π ( s , a ) Q^\pi(s,a) Qπ(s,a).意思是用一个actor π \pi π,在当前状态为 s s s的情况下,采取action为 a a a, 从现在到一个episode结束累积的Reward的期望是多少.
从Q-function可以引出Q-learning, 流程是这样的: 1. actor π \pi π和环境进行交互. 2. 通过MC或者时序差分方法训一个 Q Q Q. 3. Q Q Q可以去选一个比 π \pi π更好的actor π ′ \pi' π′, 然后重复上面这个过程.
上面的第三步是怎么做到的呢? 实际上, 更好的actor
π
′
\pi'
π′的本质是对于所有的
s
s
s,
V
π
′
(
s
)
≥
V
π
(
s
)
V^{\pi'}(s)\ge V^\pi(s)
Vπ′(s)≥Vπ(s). 做到这一点, 实际上就是采取能使得
Q
Q
Q最大的
a
a
a:
π
′
(
s
)
=
arg
max
a
Q
π
(
s
,
a
)
\pi' (s) = \arg \max_a Q^\pi(s,a)
π′(s)=argamaxQπ(s,a)
1.3 Actor + Critic
1.3.1 Advantage Actor-Critic( A 2 C A^2C A2C)
在A2C中, actor网络的更新公式为:
∇
θ
R
ˉ
θ
=
1
/
N
∑
i
=
1
N
∑
t
A
(
s
t
,
a
t
)
∇
θ
log
p
(
a
t
∣
s
t
,
θ
)
\nabla_\theta\bar{R}_{\theta}=1/N \sum_{i=1}^N \sum_t A(s_t,a_t) \nabla_\theta \log p(a_t|s_t,\theta)
∇θRˉθ=1/Ni=1∑Nt∑A(st,at)∇θlogp(at∣st,θ)
所以, 和前面传统方法不同的就是用优势函数
A
A
A替代了原本的环境Reward真值
R
(
τ
)
R(\tau)
R(τ). 优势函数的引出如下:
我们考虑采取某个动作
a
a
a相对于平均动作的优势:
A
(
s
t
,
a
t
)
=
Q
(
s
t
,
a
t
)
−
V
(
s
t
)
A(s_t,a_t) = Q(s_t,a_t)-V(s_t)
A(st,at)=Q(st,at)−V(st)
(我们先忽略上标
π
\pi
π,
Q
,
V
Q,V
Q,V的含义和上面一样)
根据时序差分的关系,可以得到
Q
^
(
s
t
,
a
t
)
=
r
+
γ
V
(
s
t
+
1
)
\hat{Q}(s_t,a_t) = r+\gamma V(s_{t+1})
Q^(st,at)=r+γV(st+1)
(上式的含义就是对于
t
t
t往后的平均reward大概等于当前的环境reward
r
r
r 加上 从
t
+
1
t+1
t+1往后的reward均值)
代入上面的式子得到:
A
(
s
t
,
a
t
)
=
Q
(
s
t
,
a
t
)
−
V
(
s
t
)
=
r
+
γ
V
(
s
t
+
1
)
−
V
(
s
t
)
A(s_t,a_t) = Q(s_t,a_t)-V(s_t)=r+\gamma V(s_{t+1})-V(s_t)
A(st,at)=Q(st,at)−V(st)=r+γV(st+1)−V(st)
所以 A A A实际上可以和 a t a_t at是没有关系的。
让上面的式子
γ
=
1
\gamma=1
γ=1, 还可以写成:
A
(
s
t
,
a
t
)
=
r
+
V
(
s
t
+
1
)
−
V
(
s
t
)
=
r
−
(
V
(
s
t
)
−
V
(
s
t
+
1
)
)
A(s_t,a_t) =r+ V(s_{t+1})-V(s_t) = r - ( V(s_{t})-V(s_{t+1}))
A(st,at)=r+V(st+1)−V(st)=r−(V(st)−V(st+1))
第一项是采取当前action的环境真实reward,第二项是对于actor
π
\pi
π来说这一步的平均reward. 所以说, 优势函数描述了当前action在平均意义上的优势程度. 如果优势程度比较大, 那么我们就鼓励这种action的发生. 上面的式子还可以看出, 相当于给环境的reward加了一个动态的bias.
然后,别忘了 V ( s t ) V(s_{t}) V(st)是直接由价值网络预测的,价值网络的训练就是一个回归问题,尽量贴近环境真实的reward. 参见1.2 Critic
A2C等actor+critic相比于前面的传统方法,主要是解决这几个问题:
- 传统的方法过度依赖环境的Reward,但是环境的Reward通常不够稳定;而Q-learning通过学习动作价值预测函数来选择最优动作,不直接优化策略,可能会导致策略更新滞后。
- Critic的价值估计为Actor提供了更直接的反馈,减少了策略探索的盲目性,加速了学习过程。
- Actor-Critic方法可以在每一步都更新策略和价值函数,充分利用每个样本的信息,提高样本效率。
1.3.2 Async Advantage Actor-Critic( A 3 C A^3C A3C)
A3C就是A2C的异步版本, 允许多个代理同时在不同环境中采样和更新,显著提高采样效率。
2. Inverse RL
对于没有reward function(比如机器人操作), 而只有一对trajectory的示例(或者说episode的示例), 那就需要IL来学习.
Inverse RL的核心是: 老师(也就是已经有的一堆trajectory)永远是对的.
所以说核心步骤如下: (核心概念就是先射箭在画靶)
- 初始化一个actor
- 在每个迭代中:
- actor和环境互动, 得到一些trajectory
- 定义一个reward function, 它使得teacher的trajectory永远比actor的要好
- actor的目的就是最大化reward
- 输出reward function和actor
所以IRL和GAN异曲同工:
3. PPO 近端策略优化
近端策略优化(Proximal Policy Optimization,PPO)是一种强化学习算法,用于训练智能体通过与环境的交互来学习最优策略。它是深度强化学习中的一种策略梯度方法,目的是在更新策略时确保“过度更新”不会导致性能下降。
PPO的主要优点是简单且高效,它通过限制每次更新策略的变化幅度,来避免策略更新时的巨大波动。具体来说,它通过引入一个“剪切”目标函数(clipped objective),来约束策略更新的范围,从而避免策略的突然变化。
PPO的更新方式如下:
∇
θ
R
ˉ
θ
=
1
/
N
∑
i
=
1
N
∑
t
min
{
r
t
(
θ
)
A
(
s
t
,
a
t
)
,
clip
(
1
−
ϵ
,
1
+
ϵ
)
A
(
s
t
,
a
t
)
}
\nabla_\theta\bar{R}_{\theta} = 1/N \sum_{i=1}^N \sum_t \min \{r_t(\theta)A(s_t,a_t),\text{clip}(1 - \epsilon,1 + \epsilon) A(s_t,a_t)\}
∇θRˉθ=1/Ni=1∑Nt∑min{rt(θ)A(st,at),clip(1−ϵ,1+ϵ)A(st,at)}
其中
r
t
(
θ
)
=
π
θ
(
a
t
∣
s
t
)
/
π
o
l
d
(
a
t
∣
s
t
)
r_t(\theta) = \pi_\theta(a_t|s_t) / \pi_{old} (a_t|s_t)
rt(θ)=πθ(at∣st)/πold(at∣st), 是当前策略与旧策略的比值,
A
(
s
t
,
a
t
)
A(s_t,a_t)
A(st,at)就是优势函数,可以按照1.3.1节中的计算方式去计算,但是更常用的是广义优势估计(GAE)的方法,公式如下:
A
(
s
t
,
a
t
)
=
δ
t
+
(
λ
γ
)
δ
t
+
1
+
(
λ
γ
)
2
δ
t
+
2
+
…
A(s_t,a_t) = \delta_t + (\lambda \gamma) \delta_{t+1} + (\lambda \gamma)^2 \delta_{t+2} + \dots
A(st,at)=δt+(λγ)δt+1+(λγ)2δt+2+…
其中
δ
t
\delta_t
δt是从
t
t
t时刻开始到结束的平均reward,计算方式恰好是1.3.1节中的
A
A
A, 也即:
δ
t
=
r
+
γ
V
(
s
t
+
1
)
−
V
(
s
t
)
\delta_t = r+\gamma V(s_{t+1})-V(s_t)
δt=r+γV(st+1)−V(st)
伪代码如下:
# 初始化策略网络 π_θ 和价值网络 V_φ,设置超参数
初始化策略网络 π_θ 和价值网络 V_φ
设置折扣因子 γ,GAE 参数 λ,剪切参数 ε,学习率 α,批次大小 N
设置最大更新步数 T,最大训练轮数 K
for 每个训练轮次 k in 1 到 K:
# 收集数据
初始化存储容器,存储状态 s, 动作 a, 奖励 r, 下一状态 s' 和折扣回报
for 每个时间步 t in 1 到 T:
通过策略网络 π_θ 选择动作 a_t 在状态 s_t 上
与环境交互,获得奖励 r_t 和下一个状态 s_{t+1}
存储 (s_t, a_t, r_t, s_{t+1}) 到存储容器
# 计算优势估计 (GAE)
对于每个时间步 t 从 T-1 到 1 反向计算:
计算 TD 残差 δ_t = r_t + γ * V_φ(s_{t+1}) - V_φ(s_t)
计算优势估计 \hat{A}_t 使用 GAE
进行优势估计平滑
# 更新策略和价值网络
对每个 mini-batch(大小 N)进行迭代:
# 计算重要性采样比 r_t(θ)
r_t(θ) = π_θ(a_t | s_t) / π_θ_old(a_t | s_t)
# 计算损失函数 L_CLIP
L_CLIP = E_t[ min(r_t(θ) * \hat{A}_t, clip(r_t(θ), 1-ε, 1+ε) * \hat{A}_t) ]
# 可选:加上熵正则化项 H(π_θ)
L = L_CLIP + β * H(π_θ)
# 更新策略网络参数 θ
计算 L 对 θ 的梯度
更新 θ = θ + α * 梯度
# 更新价值网络参数 φ
计算价值网络损失函数 L_critic
更新 φ = φ - α * 梯度(使用 TD 错误的均方误差)
# 更新旧策略网络 π_θ_old
复制当前策略网络参数 π_θ 到 π_θ_old
返回 最终的策略 π_θ
在实践中一般取 ϵ = 0.2 \epsilon=0.2 ϵ=0.2
参考学习链接:https://www.zhihu.com/tardis/bd/art/717010380