一、 重要性采样
TRPO和PPO主要思想的数学基础是重要性采样
- 重要性采样: x i x_i xi 是从 p ( x ) p(x) p(x)分布中采样得到的, 但是 p ( x ) p(x) p(x)的值往往无法直接获得,需要通过其他分布 q ( x ) q(x) q(x)进行间接采样获得。
E x ∼ p [ f ( x ) ] = ∫ f ( x ) p ( x ) d x = ∫ f ( x ) p ( x ) q ( x ) q ( x ) d x = E x ∼ q [ f ( x ) p ( x ) q ( x ) ] \begin{aligned} \mathbb{E}_{x\sim p}[f(x)] &=\int f(x)p(x) dx \\ &=\int f(x) \frac{p(x)}{q(x)}q(x)dx \\ &=\mathbb{E}_{x\sim q}[f(x)\frac{p(x)}{q(x)}] \end{aligned} Ex∼p[f(x)]=∫f(x)p(x)dx=∫f(x)q(x)p(x)q(x)dx=Ex∼q[f(x)q(x)p(x)]
-
条件:
- p p p分布与 q q q分布需要相近,才能得到较好的效果。
-
用在强化学习里面:
- 由于策略梯度原始公式中的 新策略分布难以得到,因而使用旧策略进行间接采样,以使得未知项变成可估计的已知项进行计算。
二、 梯度与参数更新
1. 回报的期望: 最大化全部采样轨迹上的策略回报值
R
θ
ˉ
=
∑
τ
R
(
τ
)
p
θ
(
τ
)
\bar{R_\theta}=\sum_\tau R(\tau)p_\theta(\tau)
Rθˉ=τ∑R(τ)pθ(τ)
2. 回报的期望的梯度:(第三个等号用到的公式:
∇
f
(
x
)
=
f
(
x
)
∇
log
f
(
x
)
\nabla f(x) = f(x) \nabla \log f(x)
∇f(x)=f(x)∇logf(x))
∇ R θ ˉ = ∑ τ R ( τ ) ∇ p θ ( τ ) = ∑ τ R ( τ ) p θ ( τ ) ∇ p θ ( τ ) p θ ( τ ) = ∑ τ R ( τ ) p θ ( τ ) ∇ log p θ ( τ ) = 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} \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)}\\ &= \mathbb{E}_{\tau \sim p_\theta{\tau}}[R(\tau){\nabla \log p_\theta(\tau)}] \\ &≈ \frac{1}{N} \sum_{n=1}^{N}R(\tau^n)\nabla \log p_{\theta}(\tau^n) \\ &=\frac{1}{N}\sum_{n=1}^{N} \sum_{t=1}^{T_n} R(\tau^n)\nabla \log p_\theta(a_t^n|s_t^n) \end {aligned} ∇Rθˉ=τ∑R(τ)∇pθ(τ)=τ∑R(τ)pθ(τ)pθ(τ)∇pθ(τ)=τ∑R(τ)pθ(τ)∇logpθ(τ)=Eτ∼pθτ[R(τ)∇logpθ(τ)]≈N1n=1∑NR(τn)∇logpθ(τn)=N1n=1∑Nt=1∑TnR(τn)∇logpθ(atn∣stn)
式中
-
N N N表示采样了 N N N条trajectory, T n T_n Tn表示每条trajectory的step数量。
-
关于 p θ ( τ ) p_{\theta}(\tau) pθ(τ)
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(s_1)p_\theta(a_1|s_1)p(s_2|s_1,a_1)p_\theta(a_2|s_2)p(s_3|s_2,a_2) \space\space...\space\space \\ &=p(s_1) \prod_{t=1}^T p_{\theta}(a_t|s_t)p(s_{t+1}|s_t, a_t) \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 θ ( s t + 1 ∣ s t , a ) p_\theta(s_{t+1}|s_t, a) pθ(st+1∣st,a), 一部分是来自agent的 p θ ( a t ∣ s t ) p_\theta {(a_t|s_t)} pθ(at∣st), 其中来自环境的部分不带入计算,策略更新只考虑agent这部分。所以最后一步并没有 t + 1 t+1 t+1这部分。
3. 参数更新:
θ
=
θ
+
η
∇
R
θ
ˉ
\theta = \theta+\eta \nabla \bar{R_\theta}
θ=θ+η∇Rθˉ
三、 实际算法中对策略梯度的处理方法
1. 策略梯度方法:
加入baseline
∇
R
θ
ˉ
=
1
N
∑
n
=
1
N
(
R
(
τ
n
)
−
b
)
∇
log
p
θ
(
τ
n
)
b
≈
E
[
R
(
τ
)
]
\nabla \bar{R_\theta}=\frac{1}{N} \sum_{n=1}^{N}(R(\tau^n)-b)\nabla \log p_{\theta}(\tau^n) \\ b≈\mathbb{E}[R(\tau)]
∇Rθˉ=N1n=1∑N(R(τn)−b)∇logpθ(τn)b≈E[R(τ)]
b b b 的加入保证reward不是恒大于0的,若reward一直大于0,则会导致未被采样的action无法得到提升,但其实该action并不是不好而是未被采样。
2. 状态值函数估计轨迹回报:
R
(
τ
n
)
−
b
R(\tau^n)-b
R(τn)−b 部分使用状态值函数来替代
q
(
s
,
a
)
q(s,a)
q(s,a)
3. 优势函数估计轨迹回报(Actor-Critic):
R ( τ n ) − b R(\tau^n)-b R(τn)−b 部分用以下Advantage function来替代
A ( s t , a t ) = q ( s , a ) − V ( s ) A(s_t,a_t)= q(s,a)-V(s) A(st,at)=q(s,a)−V(s)
4. TD-Error估计轨迹回报:
R
(
τ
n
)
−
b
R(\tau^n)-b
R(τn)−b 部分用以下TD-Error 代替
r
(
s
t
.
a
t
)
+
v
(
s
t
+
1
)
−
v
(
s
)
r(s_t. a_t)+v(s_{t+1})-v(s)
r(st.at)+v(st+1)−v(s)
四、GAE(Generalized Advantage Estimation)
-
GAE的作用
- GAE的意思是泛化优势估计,因而他是用来优化Advantage Function优势函数的。
- GAE的存在是用来权衡variance和bias问题的:
- On-policy直接交互并用每一时刻的回报作为长期回报的估计 ∑ t ′ = t T γ t ′ − t r t ′ \sum_{t'=t}^{T} \gamma^{t'-t}r_{t'} ∑t′=tTγt′−trt′ 会产生较大的方差,Variance较大。
- 而通过基于优势函数的AC方法来进行回报值估计,则会产生方差较小,而Bias较大的问题。
-
GAE 推导
满足 γ \gamma γ-just条件。(未完待续)
-
GAE形式
GAE的形式为多个价值估计的加权平均数。
T D E r r o r = δ t = r t + γ v ( s t + 1 ) − v ( s t ) TD Error=\delta_t=r_t+\gamma v(s_{t+1})-v(s_t) TDError=δt=rt+γv(st+1)−v(st)
运用GAE公式进行优势函数的估计:
∑ l = 0 ∞ ( γ λ ) l δ t + 1 V \sum_{l=0}^\infin(\gamma\lambda)^l \delta_{t+1}^V l=0∑∞(γλ)lδt+1V
为了快速估计序列中所有时刻的估计值,采用倒序计算,从t+1时刻估计t时刻:
A
t
^
G
A
E
(
γ
,
λ
)
=
∑
l
=
0
∞
(
γ
λ
)
l
δ
t
+
1
V
=
δ
t
V
+
γ
λ
A
^
t
+
1
G
A
E
(
γ
,
λ
)
\hat{A_t}^{GAE(\gamma,\lambda)}=\sum_{l=0}^{\infin}(\gamma\lambda)^l \delta_{t+1}^V=\delta_t^V+\gamma\lambda\hat{A}_{t+1}^{GAE(\gamma,\lambda)}
At^GAE(γ,λ)=l=0∑∞(γλ)lδt+1V=δtV+γλA^t+1GAE(γ,λ)
五、PPO关于策略梯度的目标函数
以上所述的策略梯度算法属于on-policy的算法,而PPO属于近似on-policy的算法
-
on-policy: 使用当前策略 π θ \pi_\theta πθ收集数据,当参数 θ \theta θ更新后,必须重新采样。
∇ R θ ˉ = E τ ∼ p θ τ [ R ( τ ) ∇ log p θ ( τ ) ] \nabla \bar{R_\theta}=\mathbb{E}_{\tau \sim p_\theta{\tau}}[R(\tau){\nabla \log p_\theta(\tau)}] ∇Rθˉ=Eτ∼pθτ[R(τ)∇logpθ(τ)] -
off-policy: 可以从可重用的样本数据中获取样本来训练当前的策略 π θ \pi _\theta πθ,下式用了重要性采样。
∇ R θ ˉ = E τ ∼ p θ ′ τ [ p θ ( τ ) p θ ′ ( τ ) R ( τ ) ∇ log p θ ( τ ) ] \nabla \bar{R_\theta}=\mathbb{E}_{\tau \sim p_{\theta^\prime}{\tau}}[\frac{p_\theta(\tau)}{p_{\theta^\prime}(\tau)} R(\tau){\nabla \log p_\theta(\tau)}] ∇Rθˉ=Eτ∼pθ′τ[pθ′(τ)pθ(τ)R(τ)∇logpθ(τ)]
1. PPO目标函数
对于PPO而言,轨迹回报通过采用Advantage function的方式进行估计,因而其梯度更新方式为:
∇
R
θ
ˉ
=
E
(
s
t
,
a
t
)
∼
π
θ
[
A
θ
(
s
t
,
a
t
)
∇
log
p
θ
(
a
t
n
∣
s
t
n
)
]
=
E
(
s
t
,
a
t
)
∼
π
θ
′
[
p
θ
(
s
t
,
a
t
)
p
θ
′
(
s
t
,
a
t
)
A
θ
′
(
s
t
,
a
t
)
∇
log
p
θ
(
a
t
n
∣
s
t
n
)
]
=
E
(
s
t
,
a
t
)
∼
π
θ
′
[
p
θ
(
a
t
∣
s
t
)
p
θ
′
(
a
t
∣
s
t
)
p
θ
(
s
t
)
p
θ
′
(
s
t
)
A
θ
′
(
s
t
,
a
t
)
∇
log
p
θ
(
a
t
n
∣
s
t
n
)
]
≈
E
(
s
t
,
a
t
)
∼
π
θ
′
[
∇
p
θ
(
a
t
∣
s
t
)
p
θ
′
(
a
t
∣
s
t
)
A
θ
′
(
s
t
,
a
t
)
]
\begin{aligned} \nabla \bar{R_\theta} &=\mathbb{E}_{(s_t,a_t)\sim\pi_\theta}[A^\theta(s_t,a_t)\nabla \log p_\theta({a_t^n|s_t^n})] \\ &=\mathbb{E}_{(s_t,a_t)\sim\pi_\theta^\prime}[\frac{p_\theta(s_t,a_t)}{p_\theta^\prime(s_t,a_t)}A^{\theta^\prime}(s_t,a_t)\nabla \log p_\theta({a_t^n|s_t^n})] \\ &=\mathbb{E}_{(s_t,a_t)\sim\pi_\theta^\prime}[\frac{p_\theta(a_t|s_t)}{p_\theta^\prime(a_t|s_t)}\frac{p_\theta(s_t)}{p_\theta^\prime(s_t)}A^{\theta^\prime}(s_t,a_t)\nabla \log p_\theta({a_t^n|s_t^n})] \\ &≈\mathbb{E}_{(s_t,a_t) \sim \pi_\theta^\prime}[\frac{\nabla p_\theta(a_t|s_t)}{p_\theta^\prime(a_t|s_t)}A^{\theta^\prime}(s_t,a_t)] \end{aligned}
∇Rθˉ=E(st,at)∼πθ[Aθ(st,at)∇logpθ(atn∣stn)]=E(st,at)∼πθ′[pθ′(st,at)pθ(st,at)Aθ′(st,at)∇logpθ(atn∣stn)]=E(st,at)∼πθ′[pθ′(at∣st)pθ(at∣st)pθ′(st)pθ(st)Aθ′(st,at)∇logpθ(atn∣stn)]≈E(st,at)∼πθ′[pθ′(at∣st)∇pθ(at∣st)Aθ′(st,at)]
其中,从第二个等式用的是重要性采样,第三到第四个约等式由于
p
θ
(
s
t
)
p
θ
′
(
s
t
)
\frac{p_\theta(s_t)}{p_\theta^\prime(s_t)}
pθ′(st)pθ(st)这一项来源于重要性采样,前提假设两个分布差别不大,近似为1,且不易计算,故省略,后面的
∇
log
p
θ
(
a
t
n
∣
s
t
n
)
\nabla \log p_\theta({a_t^n|s_t^n})
∇logpθ(atn∣stn) ,根据公式
∇
f
(
x
)
=
f
(
x
)
∇
log
f
(
x
)
\nabla f(x) = f(x) \nabla \log f(x)
∇f(x)=f(x)∇logf(x)转换。
因而,定义目标函数为:
J
θ
′
(
θ
)
=
E
(
s
t
,
a
t
)
∼
π
θ
′
[
p
θ
(
a
t
∣
s
t
)
p
θ
′
(
a
t
∣
s
t
)
A
θ
′
(
s
t
,
a
t
)
]
J^{\theta^{\prime}} (\theta)=\mathbb{E}_{(s_t,a_t) \sim \pi_\theta^\prime}[\frac{p_\theta(a_t|s_t)}{p_\theta^\prime(a_t|s_t)}A^{\theta^\prime}(s_t,a_t)]
Jθ′(θ)=E(st,at)∼πθ′[pθ′(at∣st)pθ(at∣st)Aθ′(st,at)]
2. PPO对于重要性采样约束的处理
为了保证$p_\theta(s_t,a_t) $ 与 p θ ′ ( s t , a t ) p_\theta^\prime(s_t,a_t) pθ′(st,at) 分布的差别不会太大,采用以下约束:
- TRPO: 使用约束 K L ( θ , θ ′ ) < δ KL(\theta,\theta')<\delta KL(θ,θ′)<δ,在分布上进行约束。
- PPO1(Adaptive KL):使用 J P P O θ ′ ( θ ) = J θ ′ ( θ ) − β K L ( θ , θ ′ ) J_{PPO}^{\theta'}(\theta)=J^{\theta'}(\theta)-\beta KL(\theta,\theta') JPPOθ′(θ)=Jθ′(θ)−βKL(θ,θ′),在目标函数上加一个正则项进行约束,注意,这里KL散度衡量的是action之间的距离,而不是参数 θ \theta θ与 θ ′ \theta' θ′之间的距离。
- PPO2 (Clip,论文中推荐的):使用 J P P O 2 θ ′ ( θ ) = ∑ ( s t , a t ) min { ( [ p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) A θ ′ ( s t , a t ) ] , [ c l i p ( p θ ( a t ∣ s t ) p θ ′ ( a t ∣ s t ) , 1 − ϵ , 1 + ϵ ) A θ ′ ( s t , a t ) ] ) } J_{PPO_2}^{\theta'}(\theta)=\sum_{(s_t,a_t)}\min\{([\frac{p_\theta(a_t|s_t)}{p_\theta^\prime(a_t|s_t)}A^{\theta^\prime}(s_t,a_t)], [clip(\frac{p_\theta(a_t|s_t)}{p_\theta^\prime(a_t|s_t)},1-\epsilon,1+\epsilon)A^{\theta^\prime}(s_t,a_t)])\} JPPO2θ′(θ)=∑(st,at)min{([pθ′(at∣st)pθ(at∣st)Aθ′(st,at)],[clip(pθ′(at∣st)pθ(at∣st),1−ϵ,1+ϵ)Aθ′(st,at)])}, 来约束分布距离。
3. 使用GAE对优势函数进行优化
def get_gaes(self, rewards, v_preds, v_preds_next):
"""
GAE
:param rewards: r(t)
:param v_preds: v(st)
:param v_preds_next: v(st+1)
:return:
"""
deltas = [r_t + self.gamma * v_next - v for r_t, v_next, v in zip(rewards, v_preds_next, v_preds)]
#计算GAE(lambda = 1), 参见 ppo paper eq(11)
gaes = copy.deepcopy(deltas)
# 倒序计算GAE
for t in reversed(range(len(gaes) - 1)):
gaes[t] = gaes[t] + self.gamma * gaes[t + 1]
return gaes
六、 PPO的目标函数
PPO的最终目标函数由三部分组成,可使用梯度下降求解,而不是像TRPO一样使用共轭梯度法:
- 策略梯度目标函数: L t C L I P ( θ ) L_t^{CLIP}(\theta) LtCLIP(θ)
- 值函数目标函数: L t V F ( θ ) = ( V θ ( s t ) − V t t a r g e t ) 2 L_t^{VF}(\theta)=(V_\theta(s_t)-V_t^{target})^2 LtVF(θ)=(Vθ(st)−Vttarget)2
- 策略模型的熵: S [ π θ ] ( s t ) S_[\pi_\theta](s_t) S[πθ](st)
完整的形式如下:
L
t
P
P
O
2
(
θ
)
=
E
^
t
[
L
t
C
L
I
P
(
θ
)
−
c
1
L
t
V
F
(
θ
)
+
c
2
S
[
π
θ
]
(
s
t
)
]
L_t^{PPO_2}(\theta)=\hat{\mathbb{E}}_t[L_t^{CLIP}(\theta)-c_1L_t^{VF}(\theta)+c_2S_[\pi_\theta](s_t)]
LtPPO2(θ)=E^t[LtCLIP(θ)−c1LtVF(θ)+c2S[πθ](st)]
这部分相应的代码如下:
with tf.variable_scope('assign_op'):
self.assign_ops = []
for v_old, v in zip(old_pi_trainable, pi_trainable):
self.assign_ops.append(tf.assign(v_old, v))
# inputs for train_op
with tf.variable_scope('train_inp'):
self.actions = tf.placeholder(dtype=tf.int32, shape=[None], name='actions')
self.rewards = tf.placeholder(dtype=tf.float32, shape=[None], name='rewards')
self.v_preds_next = tf.placeholder(dtype=tf.float32, shape=[None], name='v_preds_next')
self.gaes = tf.placeholder(dtype=tf.float32, shape=[None], name='gaes')
act_probs = self.Policy.act_probs
act_probs_old = self.Old_Policy.act_probs
# agent通过新策略选择action的概率 probabilities of actions which agent took with policy
act_probs = act_probs * tf.one_hot(indices=self.actions, depth=act_probs.shape[1])
act_probs = tf.reduce_sum(act_probs, axis=1)
# agent通过旧策略选择action的概率 probabilities of actions which agent took with old policy
act_probs_old = act_probs_old * tf.one_hot(indices=self.actions, depth=act_probs_old.shape[1])
act_probs_old = tf.reduce_sum(act_probs_old, axis=1)
with tf.variable_scope('PPO_loss'):
"""
策略目标函数
"""
#
# ratios = tf.divide(act_probs, act_probs_old)
# r_t(θ) = π/πold 为了防止除数为0,这里截取一下值,然后使用e(log减法)来代替直接除法
ratios = tf.exp(
tf.log(tf.clip_by_value(act_probs, 1e-10, 1.0)) - tf.log(tf.clip_by_value(act_probs_old, 1e-10, 1.0)))
# L_CLIP 裁剪优势函数值
clipped_ratios = tf.clip_by_value(ratios, clip_value_min=1 - clip_value, clip_value_max=1 + clip_value)
self.loss_clip = tf.minimum(tf.multiply(self.gaes, ratios), tf.multiply(self.gaes, clipped_ratios))
self.loss_clip = tf.reduce_mean(self.loss_clip)
"""
策略模型的熵
"""
# 计算新策略πθ的熵 S = -p log(p) 这里裁剪防止p=0
self.entropy = -tf.reduce_sum(
self.Policy.act_probs * tf.log(tf.clip_by_value(self.Policy.act_probs, 1e-10, 1.0)), axis=1)
self.entropy = tf.reduce_mean(self.entropy, axis=0) # mean of entropy of pi(obs)
"""
值目标函数
"""
# L_vf = [(r+γV(π(st+1))) - (V(π(st)))]^2
v_preds = self.Policy.v_preds
self.loss_vf = tf.squared_difference(self.rewards + self.gamma * self.v_preds_next, v_preds)
self.loss_vf = tf.reduce_mean(self.loss_vf)
# construct computation graph for loss
# L(θ) = E_hat[L_CLIP(θ) - c1 L_VF(θ) + c2 S[πθ](s)]
# L = 策略目标函数 + 值目标函数 + 策略模型的熵
self.loss = self.loss_clip - c_1 * self.loss_vf + c_2 * self.entropy
# minimize -loss == maximize loss
self.loss = -self.loss
optimizer = tf.train.RMSPropOptimizer(learning_rate=args.ppo_lr, epsilon=1e-5)
self.gradients = optimizer.compute_gradients(self.loss, var_list=pi_trainable)
self.train_op = optimizer.minimize(self.loss, var_list=pi_trainable)