本章节详细介绍 PPO 和 SAC 这类实用算法,并介绍实用离线策略方法让他们更加高效
基于我们上一章节的优化公式
∇θJ(θ)≈t,i∑∇θlogπθ(at,i∣st,i)A^πθ(st,i,at,i)
如果使用 importance weight 来对更重要的样本进行加权,则有:
∇θ′J(θ′)≈t,i∑πθ(ai,t∣si,t)πθ′(ai,t∣si,t)∇θ′logπθ′(at,i∣st,i)A^πθ(st,i,at,i)
可以发现优势函数 A^πθ 是基于旧策略 πθ 和旧数据估计出来的,如果对同一批的数据优化很多不,新策略会逐渐偏离旧策略,此时优势函数就会偏离实际的训练目标了,会导致过拟合的问题。
对于这个问题,可以尽可能让新策略和旧策略更加接近,从而降低偏离的情况。
对同一个状态 s,旧策略和新策略的动作分别是 πθ(⋅∣s) 和 πθ′(⋅∣s) ,可以记 KL 散度为:
DKL(πθ(⋅∣s)∥πθ′(⋅∣s))=a∑πθ(a∣s)logπθ′(a∣s)πθ(a∣s)
实际表示意义为 KL 越小,新旧策略在同一个状态下给出的动作概率分布越接近。
在使用了 KL 散度后优化目标为只允许在就策略的小区域内进行更新。
在原始的 J(θ) 上减去一个 KL 散度的值就可以实现控制更新范围:
J(θ)−βDKL
这是 PPO 的一个变体
对 importance weight 进行裁剪,控制 πθ(ai,t∣si,t)πθ′(ai,t∣si,t) 数值的大小到某个固定的区间内。
这也是 PPO 中的一个核心技巧,参考下文。
PPO 的核心目标函数就是从普通的 policy gradient 中优化出来的
原始的梯度策略目标的梯度为
∇θJ(θ)=Est,at∼πθ[∇θlogπθ(at∣st)Aπθ(st,at)]
最大的问题就是 优势函数是从旧的 数据算的,所以 PPO 的核心就是为了改进这个问题
PPO 中的代替目标为
J~(θ′)≈t,i∑πθ(ai,t∣si,t)πθ′(ai,t∣si,t)A^πθ(st,i,at,i)
其中优势函数前面那个加权的因子称为 importance weight / probability ratio,用于衡量新策略对某个动作的概率改变量。
rt(θ′)=πθ(at∣st)πθ′(at∣st)
这个加权因子虽然能够对让策略更新在旧的策略附近,但是乘法会引入数值的不稳定。
对 importance weight 的值进行裁剪,用来控制训练时候的稳定性
J~(θ′)≈t,i∑clip(πθ(ai,t∣si,t)πθ′(ai,t∣si,t),1−ϵ,1+ϵ)A^πθ(st,i,at,i)
例如设置一个区间 [0.8,1.2] ,限制新策略对某个动作相对于旧策略的概率比例在区间内。
但此时 clip 有可能会让目标函数变得比原来值更大,对于优化过程其实是错误的,所以还需要额外的改进。
注意实际计算中,优势函数本身的值被当做一个常数(不参与梯度计算),所以一旦发生了裁剪则整个一项的梯度都变成了 0。
为了进一步控制梯度,PPO 算法额外再取一次 clip 后的值和原来的值之间更小的那个
J~(θ′)≈t,i∑min(rt(θ′)A^t,clip(rt(θ′),1−ϵ,1+ϵ)A^t)
- 在 A^t>0 时,为了控制优化的策略不要太激进,所以使用上界 (1+ϵ)A^t 来控制,此时最小值就是 (1+ϵ)A^t
- 在 A^t<0 时,例如 rtA^t=1.5×(−10)=−15,把 因数 clip 到 1.2 会得到 −12,反而让目标函数变大了,如果取最小值则还是那个 −15
在此情况下不再是一旦裁剪就梯度归零,而是还需要看最小值实际取的是哪个值。
GAE 是用来估计 A^t 的的,就是上一章节中 演员评论家的三种方式,主要包含:
Monte Carlo, Bootstrapping, N step.
到此为止使用了两种 policy 方式,包括:
- on-policy: 使用当前的 batch 的数据做一次梯度的 step
- off-policy: 使用一个 batch 的数据做多个梯度 step
但是还有一些额外的方法可以进一步强化这个 off-policy,也就是从之前的多个 batch 来执行梯度更新,这样流程就会变成:
- 从策略中收集 experience 并放进 replay buffer:si,ai∼πθ(a∣s)
- 从 replay buffer 中采样一个 batch:si,ai,ri,si’∼R
- 使用 TD 目标更新价值函数:yi=ri+γV^ϕπ(si’),并用该目标更新 V^ϕπ
- 计算优势函数估计:A^π(si,ai)=r(si,ai)+γV^ϕπ(si’)−V^ϕπ(si)
- 估计策略目标函数的梯度:∇θJ(θ)≈N1∑i∇θlogπθ(ai∣si)A^π(si,ai)
- 根据梯度更新策略参数:θ←θ+α∇θJ(θ)
对第 3 步中的 yi=ri+γV^ϕπ(si’) 算法中如果使用这个作为 bootstrapping 算法来更新 V^ϕπ ,那么这个估计实际上拟合的并不是某一个策略的 value function。
因此对此可以有这几个方法:
-
加入权重,例如时间越近的数据则权重更大等
-
只允许当前的 policy 用来作为 value function 的学习标签
-
使用 Q function 而不是 value function (这是最常用的)
回顾一下 Q-function 的公式,在状态 s 下,先执行动作 a,之后再按照当前策略 πθ 行动,最终能获得多少累计回报:
Qπθ(s,a)=r(s,a)+γEs′∼p(⋅∣s,a),a′∼πθ(⋅∣s′)[Qπθ(s′,a′)]
这里第一个动作 a 是从 旧策略中采样的,而新动作是当前策略采样的。
并且这个式子中,第二项中没有使用当前的 policy 的数据以外的信息,所以可以离策训练。
也就是说用 replay buffer 里的旧经验 (s,a,r,s′) 训练当前策略 πθ 的 Q 函数时,可以把旧动作 a 当作第一步动作,然后在下一状态 s′ 处接上当前策略采样的动作 a′,用 Bellman target 构造监督信号训练 critic。