RL 实践(7)—— CartPole【TPRO PPO】

news2024/10/6 1:39:18
  • 本文介绍 PPO 这个 online RL 的经典算法,并在 CartPole-V0 上进行测试。由于 PPO 是源自 TPRO 的,因此也会在原理部分介绍 TPRO
  • 参考:张伟楠《动手学强化学习》、王树森《深度强化学习》
  • 完整代码下载:8_[Gym] CartPole-V0 (PPO)

文章目录

  • 1. TPRO(置信域策略优化)方法
    • 1.1 朴素策略梯度方法的问题
    • 1.2 置信域优化法
    • 1.3 TPRO 公式推导
      • 1.3.1 做近似
      • 1.3.2 最大化
    • 1.4 小结
  • 2. PPO(近端策略优化)方法
    • 2.1 PPO 公式推导
      • 2.1.1 做近似
      • 2.1.2 最大化
    • 2.2 伪代码
    • 2.3 用 PPO 方法解决 CartPole 问题
  • 3. 总结

1. TPRO(置信域策略优化)方法

  • 置信域策略优化 (Trust Region Policy Optimization, TRPO) 是一种策略学习方法,跟朴素的策略梯度方法相比有两个优势:
    1. TRPO表现更稳定,收敛曲线不会剧烈波动,而且对学习率不敏感
    2. TRPO 用更少的经验数据(transition 四元组)就能达到与策略梯度方法相同的表现

1.1 朴素策略梯度方法的问题

  • 前文已经介绍了 policy gradient 方法 REINFORCE & Actor-Critic 以及其带 baseline 的改进版本 REINFORCE with baseline & A2C。这些方法的核心思想都是:参数化 agent 策略 π θ \pi_\theta πθ,设计衡量策略好坏的目标函数 J ( θ ) = E s [ V π θ ( s ) ] = E π θ [ ∑ t = 0 ∞ γ t r ( s t , a t ) ] J(\theta)=\mathbb{E}_{s}[V_{\pi_\theta}(s)] = \mathbb{E}_{\pi_\theta}[\sum_{t=0}^\infin \gamma^tr(s_t,a_t)] J(θ)=Es[Vπθ(s)]=Eπθ[t=0γtr(st,at)]通过梯度上升的方法找出最大化这个目标函数的策略参数 θ ∗ = arg max ⁡ θ J ( θ ) \theta^* =\argmax_\theta J(\theta) θ=argmaxθJ(θ),从而得到最优策略 π θ ∗ \pi_{\theta^*} πθ
  • 但是这种算法有一个明显的缺点:注意到在环境中 rollout 时,策略 π θ \pi_\theta πθ 会被重复使用,即使策略只有微小的改变,也可能导致最终收益的巨大变化。当策略网络是深度模型时这种特性尤其明显,因此在沿着策略梯度方向更新参数时
    θ ← θ + β ▽ θ J ( θ ) \theta \leftarrow \theta + \beta \triangledown_\theta J(\theta) θθ+βθJ(θ) 很有可能由于步长 β \beta β 太长导致策略突然显著变差,进而影响训练效果。宏观上看就是朴素的策略梯度方法训练不够稳定
  • 针对以上问题,TPRO 的思想是在更新时找到一块信任区域(trust region),认为在这个区域上更新策略时能够得到某种策略性能的安全性保证,从而避免策略崩溃
    在这里插入图片描述
    为了实现这种安全性保证,我们必须舍弃掉随机梯度上升而改用其他的优化算法,TPRO 选择了置信域方法 (Trust Region Methods)

1.2 置信域优化法

  • 置信域优化法是数值最优化领域中一类经典的算法,历史至少可以追溯到 1970 年。其出发点是:如果对目标函数 J ( θ ) J(\theta) J(θ) 进行优化过于困难,不妨构造一个替代函数 L ( θ ∣ θ n o w ) L(\theta|\theta_{now}) L(θθnow),要求替代函在 θ \theta θ 的当前值 θ n o w \theta_{now} θnow 的邻域 N ( θ n o w ) \mathcal{N}(\theta_{now}) N(θnow) 内和 J ( θ ) J(\theta) J(θ) 十分相似的,通过在这个局部范围内最优化 L ( θ ∣ θ n o w ) L(\theta|\theta_{now}) L(θθnow) 来更新一次 θ \theta θ 值,反复迭代上述过程直到收敛

    其中 N ( θ n o w ) \mathcal{N}(\theta_{now}) N(θnow) 就被称作置信域,顾名思义,在 θ n o w \theta_{now} θnow 的邻域上我们可以信任 L ( θ ∣ θ n o w ) L(\theta|\theta_{now}) L(θθnow),可以拿它来替代目标函数 J ( θ ) J(\theta) J(θ)

    具体而言每轮迭代可以分成两步

    1. 做近似:给定 θ n o w \theta_{now} θnow,构造函数 L ( θ ∣ θ n o w ) L(\theta| \theta_{now}) L(θθnow),使得对于所有的 θ ∈ N ( θ n o w ) θ \in\mathcal{N}(\theta_{now}) θN(θnow)(置信域内取值),函数值 L ( θ ∣ θ n o w ) L(\theta| \theta_{now}) L(θθnow) 与原优化目标 J ( θ ) J(\theta) J(θ) 足够接近
    2. 最大化: 在置信域 N ( θ n o w ) \mathcal{N}(\theta_{now}) N(θnow) 中寻找变量 θ \theta θ 的值,使得替代函数 L L L 的值最大化。即求 θ n e w = arg max ⁡ θ ∈ N ( θ n o w ) L ( θ ∣ θ n o w ) \theta_{new} = \argmax_{\theta \in \mathcal{N}(\theta_{now})}L(\theta|\theta_{now}) θnew=θN(θnow)argmaxL(θθnow)

    注意每一轮迭代中,我们都在构造并求解一个小的约束优化问题,可以如下图示
    在这里插入图片描述

  • 注意到置信域半径控制着每一轮迭代中 θ \theta θ 变化的上限,我们通常会让这个半径随优化过程不断减小来避免 overstep
    在这里插入图片描述

  • 置信域方法是一种算法框架而非一个具体的算法。有很多种方式实现实现置信域方法:

    1. 第一步做近似的方法有多种多样,比如蒙特卡洛、二阶泰勒展开等
    2. 第二步解一个约束最大化问题的方法也很多,包括梯度投影算法、拉格朗日法等
    3. 置信域 N ( θ n o w ) \mathcal{N}(\theta_{now}) N(θnow) 也有多种多样的选择,既可以是球,也可以是两个概率分布的 KL 散度等

1.3 TPRO 公式推导

  • TPRO 是一种将置信域优化方法应用到策略学习中的 Online RL 方法。回顾 policy gradient 算法,优化目标为最大化
    J ( θ ) = E S ∼ d π θ [ V π θ ( S ) ] = E S ∼ d π θ [ E A ∼ π θ ( ⋅ ∣ S ) [ Q π θ ( S , A ) ] ] (1) \begin{aligned} J(\theta) &=\mathbb{E}_{S\sim d^{\pi_{\theta}}}[V_{\pi_\theta}(S)] \\ &=\mathbb{E}_{S\sim d^{\pi_{\theta}}}\big[\mathbb{E}_{A\sim\pi_\theta(·|S)}[Q_{\pi_\theta}(S,A)]\big] \end{aligned} \tag{1} J(θ)=ESdπθ[Vπθ(S)]=ESdπθ[EAπθ(S)[Qπθ(S,A)]](1) 其中 d π θ d^{\pi_{\theta}} dπθ 是策略 π θ \pi_\theta πθ 诱导的状态分布。考虑置信域优化法的迭代过程,每一步我们要构造优化问题:基于当前的参数 θ n o w \theta_{now} θnow 优化 θ \theta θ,故在式1中引入 θ n o w \theta_{now} θnow
    J ( θ ∣ θ n o w ) = E S ∼ d π θ [ E A ∼ π θ ( ⋅ ∣ S ) [ Q π θ ( S , A ) ] ] = E S ∼ d π θ [ E A ∼ π θ n o w ( ⋅ ∣ S ) [ π θ ( A ∣ S ) π θ n o w ( A ∣ S ) ⋅ Q π θ ( S , A ) ] ] (2) \begin{aligned} J(\theta|\theta_{now}) &=\mathbb{E}_{S\sim d^{\pi_{\theta}}}\big[\mathbb{E}_{A\sim\pi_\theta(·|S)}[Q_{\pi_\theta}(S,A)]\big] \\ &=\mathbb{E}_{S\sim d^{\pi_{\theta}}}\left[\mathbb{E}_{A\sim\pi_{\theta_{now}}(·|S)}\left[\frac{ \pi_{\theta}(A|S) }{\pi_{\theta_{now}}(A|S)}\cdot Q_{\pi_\theta}(S,A)\right]\right] \\ \end{aligned} \tag{2} J(θθnow)=ESdπθ[EAπθ(S)[Qπθ(S,A)]]=ESdπθ[EAπθnow(S)[πθnow(AS)πθ(AS)Qπθ(S,A)]](2) 注意 J ( θ ∣ θ n o w ) J(\theta|\theta_{now}) J(θθnow) 是关于 θ \theta θ 的函数,含有 θ n o w \theta_{now} θnow 的成分都可以看做常数,故以上是一个恒等变换。下面开始推导每轮迭代的两个关键步骤

1.3.1 做近似

  • 原始优化目标 J ( θ ∣ θ n o w ) J(\theta|\theta_{now}) J(θθnow) d π θ d^{\pi_{\theta}} dπθ Q θ Q_\theta Qθ 都不知道,无法直接优化,需要进行三步近似来构造替代函数
    1. 用当前策略 π θ n o w \pi_{\theta_{now}} πθnow 诱导的状态分布 d π θ n o w d^{\pi_{\theta_{now}}} dπθnow 近似 d π θ d^{\pi_{\theta}} dπθ,原始优化目标近似为
      E S ∼ d π θ n o w [ E A ∼ π θ n o w ( ⋅ ∣ S ) [ π θ ( A ∣ S ) π θ n o w ( A ∣ S ) ⋅ Q π θ ( S , A ) ] ] \mathbb{E}_{S\sim d^{\pi_{\theta_{now}}}}\left[\mathbb{E}_{A\sim\pi_{\theta_{now}}(·|S)}\left[\frac{ \pi_{\theta}(A|S) }{\pi_{\theta_{now}}(A|S)}\cdot Q_{\pi_\theta}(S,A)\right]\right] ESdπθnow[EAπθnow(S)[πθnow(AS)πθ(AS)Qπθ(S,A)]]
    2. 用 MC 近似消去上式中的两个期望。具体而言,先用当前策略 π θ n o w \pi_{\theta_{now}} πθnow 和环境交互收集一条轨迹
      s 1 , a 1 , r 1 , s 2 , a 2 , r 2 , . . . , s n , a n , r n s_1, a_1, r_1, s_2, a_2, r_2,...,s_n, a_n, r_n s1,a1,r1,s2,a2,r2,...,sn,an,rn 此轨迹满足 s t ∼ d π θ n o w , a t ∼ π θ n o w ( ⋅ ∣ s t ) s_t\sim d^{\pi_{\theta_{now}}}, a_t\sim \pi_{\theta_{now}}(·|s_t) stdπθnow,atπθnow(st),故每个 ( s t , a t ) (s_t,a_t) (st,at) 二元组都能构造一个无偏 MC 估计
      π θ ( a t ∣ s t ) π θ n o w ( a t ∣ s t ) ⋅ Q π θ ( a t , s t ) \frac{ \pi_{\theta}(a_t|s_t) }{\pi_{\theta_{now}}(a_t|s_t)}\cdot Q_{\pi_\theta}(a_t,s_t) πθnow(atst)πθ(atst)Qπθ(at,st) 用这些无偏估计的期望(均值)来近似原始优化目标,得到
      1 n ∑ t = 1 n π θ ( a t ∣ s t ) π θ n o w ( a t ∣ s t ) ⋅ Q π θ ( a t , s t ) \frac{1}{n}\sum_{t=1}^n \frac{ \pi_{\theta}(a_t|s_t) }{\pi_{\theta_{now}}(a_t|s_t)}\cdot Q_{\pi_\theta}(a_t,s_t) n1t=1nπθnow(atst)πθ(atst)Qπθ(at,st)
    3. 用真实 return 对 Q π θ ( a t , s t ) Q_{\pi_\theta}(a_t,s_t) Qπθ(at,st) 进行 MC 近似,具体而言
      Q π θ ( a t , s t ) ⟹ Q π θ n o w ( a t , s t ) ⟹ u t = r t + γ r t + 1 + γ 2 r t + 2 + . . . + γ n − t r n Q_{\pi_\theta}(a_t,s_t) \quad\Longrightarrow\quad Q_{\pi_{\theta_{now}}}(a_t,s_t) \quad\Longrightarrow\quad u_t=r_t + \gamma r_{t+1} + \gamma^2 r_{t+2} + ...+ \gamma^{n-t} r_{n} Qπθ(at,st)Qπθnow(at,st)ut=rt+γrt+1+γ2rt+2+...+γntrn
  • 综上得到对优化目标 J ( θ ∣ θ n o w ) J(\theta|\theta_{now}) J(θθnow) 的近似
    L ( θ ∣ θ n o w ) = 1 n ∑ t = 1 n π θ ( a t ∣ s t ) π θ n o w ( a t ∣ s t ) ⋅ u t (3) L(\theta|\theta_{now}) = \frac{1}{n}\sum_{t=1}^n \frac{ \pi_{\theta}(a_t|s_t) }{\pi_{\theta_{now}}(a_t|s_t)}\cdot u_t \tag{3} L(θθnow)=n1t=1nπθnow(atst)πθ(atst)ut(3) 注意近似过程中假设了 π θ \pi_{\theta} πθ π θ n o w \pi_{\theta_{now}} πθnow 极其接近,以至于可以认为二者诱导的状态分布一致,这样就能完全避免策略优化后进入坏状态引发 1.1 节的 overstep 问题。因此需要强调置信域:只有 θ \theta θ 靠近 θ n o w \theta_{now} θnow 时才是有效近似

1.3.2 最大化

  • 每轮迭代中,求解以下约束优化问题
    max ⁡ θ L ( θ ∣ θ n o w ) s.t θ ∈ N ( θ n o w ) . \max_\theta L(\theta|\theta_{now}) \quad \text{s.t} \quad\theta\in\mathcal{N}(\theta_{now}). θmaxL(θθnow)s.tθN(θnow). 我们认为在置信域 N ( θ n o w ) \mathcal{N}(\theta_{now}) N(θnow) d π θ n o w d^{\pi_{\theta_{now}}} dπθnow 近似 d π θ d^{\pi_{\theta}} dπθ,这个约束越紧,就越能避免 1.1 节的 overstep 问题

  • 邻域(置信域) N ( θ n o w ) \mathcal{N}(\theta_{now}) N(θnow) 的选取方法通常有两种

    1. 简单地设置一个关于参数的欧式距离的阈值 △ \triangle ,即 ∣ ∣ θ − θ n o w ∣ ∣ 2 ≤ △ ||\theta-\theta_{now}||_2 \leq \triangle ∣∣θθnow2 这时置信域是以 θ n o w \theta_{now} θnow 为球心, △ \triangle 为半径的超球。这种选择可以让约束优化问题的求解容易一些
    2. 另一种方式是设置一个关于策略的 KL 散度的阈值 △ \triangle ,即
      E S ∼ d π θ n o w D KL [ π θ n o w ( ⋅ ∣ S ) ∣ ∣ π θ ( ⋅ ∣ S ) ] ≤ △ \mathbb{E}_{S\sim d^{\pi_{\theta_{now}}}} D_\text{KL}\big[\pi_{\theta_{now}}(·|S) || \pi_{\theta}(·|S) \big] \leq \triangle ESdπθnowDKL[πθnow(S)∣∣πθ(S)] 此 KL 散度同样用 1.3.1 节中 π θ n o w \pi_{\theta_{now}} πθnow 交互得到的轨迹来做 MC 近似计算,即
      1 n ∑ t = 1 n D KL [ π θ n o w ( ⋅ ∣ s t ) ∣ ∣ π θ ( ⋅ ∣ s t ) ] ≤ △ \frac{1}{n} \sum_{t=1}^n D_\text{KL}\big[\pi_{\theta_{now}}(·|s_t) || \pi_{\theta}(·|s_t) \big] \leq \triangle n1t=1nDKL[πθnow(st)∣∣πθ(st)] 这种做法可以直接约束策略的变化程度。实践表明这种置信域设定表现较好,对于 RL 来说,约束 “行为上的距离” 可能比约束 “参数上的距离” 更加合适
  • 综上得到每轮迭代的约束优化问题为
    max ⁡ θ 1 n ∑ t = 1 n π θ ( a t ∣ s t ) π θ n o w ( a t ∣ s t ) ⋅ u t s.t. 1 n ∑ t = 1 n D KL [ π θ n o w ( ⋅ ∣ s t ) ∣ ∣ π θ ( ⋅ ∣ s t ) ] ≤ △ where s t ∼ d π θ n o w , a t ∼ π θ n o w ( ⋅ ∣ s t ) \begin{aligned} &\max_\theta&&\frac{1}{n}\sum_{t=1}^n \frac{ \pi_{\theta}(a_t|s_t) }{\pi_{\theta_{now}}(a_t|s_t)}\cdot u_t \\ &\text{s.t.} &&\frac{1}{n} \sum_{t=1}^n D_\text{KL}\big[\pi_{\theta_{now}}(·|s_t) || \pi_{\theta}(·|s_t) \big] \leq \triangle \\ & \text{where} && s_t\sim d^{\pi_{\theta_{now}}}, a_t\sim \pi_{\theta_{now}}(·|s_t) \end{aligned} θmaxs.t.wheren1t=1nπθnow(atst)πθ(atst)utn1t=1nDKL[πθnow(st)∣∣πθ(st)]stdπθnow,atπθnow(st) 这个问题求解起来很麻烦,大概思路是

    1. 对优化目标在 θ n o w \theta_{now} θnow 处进行一阶泰勒展开
    2. 对约束函数在 θ n o w \theta_{now} θnow 处进行二阶泰勒展开
    3. 用拉格朗日乘子法转换为无约束优化问题,通过 KKT 条件得到 θ \theta θ 的最优解

    其中二阶泰勒展开带来的黑塞矩阵尺寸很大,编程时要使用共轭梯度法进行处理;另外由于泰勒展开近似得不到精确解,还要用线性搜索来确保约束条件满足,这些问题导致 TPRO 实现复杂,没有大规模流行

1.4 小结

  • 置信域方法指的是一大类数值优化算法,通常用于求解非凸问题。对于一个最大化问题,算法重复两个步骤——做近似、最大化——直到算法收敛
  • 置信域策略优化(TRPO)是一种利用置信域算法优化策略的 On-policy Online RL 方法,它的优化目标和策略梯度方法相同,每次策略训练仅使用上一轮策略采样的数据,是 policy-based 类算法中十分有代表性的工作之一。直觉性地理解,TRPO 给出的观点是:由于策略的改变导致数据分布的改变,这大大影响深度模型实现的策略网络的学习效果,所以通过划定一个可信任的策略学习区域,保证策略学习的稳定性和有效性
  • TRPO中有两个需要调的超参数:一个是置信域的半径 △ \triangle ,另一个是求解最大化问题的数值算法的学习率。通常来说, △ \triangle 在算法的运行过程中要逐渐缩小。虽然TRPO需要调参,但是TRPO对超参数的设置并不敏感,即使超参数设置不够好,TRPO的表现也不会太差。相比之下,策略梯度算法对超参数更敏感
  • TPRO 的优势在于更好的稳定性和更高的样本效率;缺点在于每步迭代求解约束优化问题的过程繁琐,算法实现复杂 ,其后续工作 PPO 很好地解决了此问题,成为了非常流行的 Online RL 方法

2. PPO(近端策略优化)方法

  • PPO 基于 TRPO 的思想,但是其算法实现更加简单。大量的实验结果表明,PPO 能和 TRPO 学习得一样好且收敛更快,这使得 PPO 和 SAC、TD3 一起成为三大最流行的强化学习算法。如果我们想要尝试在一个新的环境中使用强化学习,可以首先尝试这三个算法
  • PPO 算法框架和 TPRO 无异,其核心思想在于将 “最大化” 操作中的约束优化问题转换为无约束优化来简化问题

2.1 PPO 公式推导

  • 前文 1.3 节推 TPRO 优化目标时是从 policy gradient 法的原始优化目标开始推导的,那样推比较简单,得到优化目标为
    J ( θ ∣ θ n o w ) = E S ∼ d π θ [ E A ∼ π θ n o w ( ⋅ ∣ S ) [ π θ ( A ∣ S ) π θ n o w ( A ∣ S ) ⋅ Q π θ ( S , A ) ] ] J(\theta|\theta_{now}) = \mathbb{E}_{S\sim d^{\pi_{\theta}}}\left[\mathbb{E}_{A\sim\pi_{\theta_{now}}(·|S)}\left[\frac{ \pi_{\theta}(A|S) }{\pi_{\theta_{now}}(A|S)}\cdot Q_{\pi_\theta}(S,A)\right]\right] J(θθnow)=ESdπθ[EAπθnow(S)[πθnow(AS)πθ(AS)Qπθ(S,A)]] 但 TPRO 和 PPO 的原始论文中使用了另一种推导方法,最后得到的优化目标略有不同,为
    J ( θ ∣ θ n o w ) = E S ∼ d π θ [ E A ∼ π θ n o w ( ⋅ ∣ S ) [ π θ ( A ∣ S ) π θ n o w ( A ∣ S ) ⋅ A π θ n o w ( S , A ) ] ] J(\theta|\theta_{now}) = \mathbb{E}_{S\sim d^{\pi_{\theta}}}\left[\mathbb{E}_{A\sim\pi_{\theta_{now}}(·|S)}\left[\frac{ \pi_{\theta}(A|S) }{\pi_{\theta_{now}}(A|S)}\cdot A_{\pi_{\theta_{now}}}(S,A)\right]\right] J(θθnow)=ESdπθ[EAπθnow(S)[πθnow(AS)πθ(AS)Aπθnow(S,A)]] 其中 A ( S , A ) A(S,A) A(S,A) 函数是前文 RL 实践(6)—— CartPole【REINFORCE with baseline & A2C】 中介绍的优势函数 A π ( s , a ) = △ Q π ( s , a ) − V π ( s ) A_\pi(s,a) \stackrel{\triangle}{=} Q_\pi(s,a) - V_\pi(s) Aπ(s,a)=Qπ(s,a)Vπ(s) 这两种优化目标都是可行的,由于 TPRO 和 PPO 的论文都用了后者,这里也推导一下这个目标
  • 推导的出发点是希望借助当前参数 θ n o w \theta_{now} θnow 推导出新的 θ \theta θ 可以使得 J ( θ ) ≥ J ( θ n o w ) J(\theta)\geq J(\theta_{now}) J(θ)J(θnow)。这里优化目标设定为在初始状态分布 S 0 S_0 S0 下的状态价值期望 J ( θ ) = E S 0 [ V π θ ( S 0 ) ] J(\theta) = \mathbb{E}_{S_0}[V_{\pi_\theta}(S_0)] J(θ)=ES0[Vπθ(S0)],有
    J ( θ ) = E S 0 [ V π θ ( S 0 ) ] = E s t ∼ d π θ [ ∑ t = 0 ∞ γ t V π θ ( s t ) − ∑ t = 1 ∞ γ t V π θ ( s t ) ] = − E s t ∼ d π θ [ ∑ t = 0 ∞ γ t ( γ V π θ ( s t + 1 ) − V π θ ( s t ) ) ] \begin{aligned} J(\theta) & =\mathbb{E}_{S_{0}}\left[V_{\pi_{\theta}}\left(S_{0}\right)\right] \\ & =\mathbb{E}_{s_t\sim d^{\pi_{\theta}}}\left[\sum_{t=0}^{\infty} \gamma^{t} V_{\pi_{\theta}}\left(s_{t}\right)-\sum_{t=1}^{\infty} \gamma^{t} V_{\pi_{\theta}}\left(s_{t}\right)\right] \\ & =-\mathbb{E}_{s_t\sim d^{\pi_{\theta}}}\left[\sum_{t=0}^{\infty} \gamma^{t}\left(\gamma V_{\pi_{\theta}}\left(s_{t+1}\right)-V_{\pi_{\theta}}\left(s_{t}\right)\right)\right] \end{aligned} J(θ)=ES0[Vπθ(S0)]=Estdπθ[t=0γtVπθ(st)t=1γtVπθ(st)]=Estdπθ[t=0γt(γVπθ(st+1)Vπθ(st))] 考虑到策略诱导的状态分布和初始分布 S 0 S_0 S0 无关,当期望括号内仅和初始状态有关时,这个期望所关于的分布可以任意取,这样我们可以推导新旧策略的目标函数之间的差距
    J ( θ ) − J ( θ n o w ) = E S 0 [ V π θ ( S 0 ) ] − E S 0 [ V π θ n o w ( S 0 ) ] = E s t ∼ d π θ [ ∑ t = 0 ∞ γ t r ( s t , a t ) ] + E s t ∼ d π θ [ ∑ t = 0 ∞ γ t ( γ V π θ n o w ( s t + 1 ) − V π θ n o w ( s t ) ) ] = E s t , a t ∼ d π θ [ ∑ t = 0 ∞ γ t [ r ( s t , a t ) + γ V π θ n o w ( s t + 1 ) − V π θ n o w ( s t ) ] ] = E s t , a t ∼ d π θ [ ∑ t = 0 ∞ γ t A π θ n o w ( s t , a t ) ] = 1 1 − γ E S ∼ d π θ [ E A ∼ π θ ( ⋅ ∣ s t ) [ A π θ n o w ( S , A ) ] ] \begin{aligned} J\left(\theta\right)-J(\theta_{now}) & =\mathbb{E}_{S_{0}}\left[V_{\pi_{\theta}}\left(S_{0}\right)\right]-\mathbb{E}_{S_{0}}\left[V_{\pi_{\theta_{now}}}\left(S_{0}\right)\right] \\ & =\mathbb{E}_{s_t\sim d^{\pi_{\theta}}}\left[\sum_{t=0}^{\infty} \gamma^{t} r\left(s_{t}, a_{t}\right)\right]+\mathbb{E}_{s_t\sim d^{\pi_{\theta}}}\left[\sum_{t=0}^{\infty} \gamma^{t}\left(\gamma V_{\pi_{\theta_{now}}}\left(s_{t+1}\right)-V_{\pi_{\theta_{now}}}\left(s_{t}\right)\right)\right] \\ & =\mathbb{E}_{s_t,a_t\sim d^{\pi_{\theta}}}\left[\sum_{t=0}^{\infty} \gamma^{t}\left[r\left(s_{t}, a_{t}\right)+\gamma V_{\pi_{\theta_{now}}}\left(s_{t+1}\right)-V_{\pi_{\theta_{now}}}\left(s_{t}\right)\right]\right]\\ & =\mathbb{E}_{s_t,a_t\sim d^{\pi_{\theta}}}\left[\sum_{t=0}^{\infty}\gamma^t A_{\pi_{\theta_{now}}}(s_t,a_t) \right]\\ &=\frac{1}{1-\gamma}\mathbb{E}_{S\sim d^{\pi_{\theta}}}\left[\mathbb{E}_{A\sim\pi_{\theta}(·|s_t)}\left[A_{\pi_{\theta_{now}}}(S,A)\right]\right] \end{aligned} J(θ)J(θnow)=ES0[Vπθ(S0)]ES0[Vπθnow(S0)]=Estdπθ[t=0γtr(st,at)]+Estdπθ[t=0γt(γVπθnow(st+1)Vπθnow(st))]=Est,atdπθ[t=0γt[r(st,at)+γVπθnow(st+1)Vπθnow(st)]]=Est,atdπθ[t=0γtAπθnow(st,at)]=1γ1ESdπθ[EAπθ(st)[Aπθnow(S,A)]] 故只要能找到一个新策略 π θ \pi_\theta πθ 使得 1 1 − γ E s t ∼ d π θ [ E a t ∼ π θ ( ⋅ ∣ s t ) [ A π θ n o w ( s t , a t ) ] ] ≥ 0 \frac{1}{1-\gamma}\mathbb{E}_{s_t\sim d^{\pi_{\theta}}}\left[\mathbb{E}_{a_t\sim\pi_{\theta}(·|s_t)}\left[A_{\pi_{\theta_{now}}}(s_t,a_t)\right]\right]\geq 0 1γ1Estdπθ[Eatπθ(st)[Aπθnow(st,at)]]0,就能保证策略性能单调递增 J ( θ ) ≥ J ( θ n o w ) J(\theta) \geq J(\theta_{now}) J(θ)J(θnow)。去掉其中常数部分再用重要度采样改为用 π θ n o w \pi_{\theta_{now}} πθnow 采样动作,就得到了 TPRO/PPO 的优化目标函数
    J ( θ ∣ θ n o w ) = E S ∼ d π θ [ E A ∼ π θ n o w ( ⋅ ∣ S ) [ π θ ( A ∣ S ) π θ n o w ( A ∣ S ) ⋅ A π θ n o w ( S , A ) ] ] J(\theta|\theta_{now}) = \mathbb{E}_{S\sim d^{\pi_{\theta}}}\left[\mathbb{E}_{A\sim\pi_{\theta_{now}}(·|S)}\left[\frac{ \pi_{\theta}(A|S) }{\pi_{\theta_{now}}(A|S)}\cdot A_{\pi_{\theta_{now}}}(S,A)\right]\right] J(θθnow)=ESdπθ[EAπθnow(S)[πθnow(AS)πθ(AS)Aπθnow(S,A)]]

2.1.1 做近似

  • 得到替代函数的方法完全类似 1.3.1 节,进行三次近似即可。具体而言
    1. 用当前策略 π θ n o w \pi_{\theta_{now}} πθnow 诱导的状态分布 d π θ n o w d^{\pi_{\theta_{now}}} dπθnow 近似 d π θ d^{\pi_{\theta}} dπθ,原始优化目标近似为
      E S ∼ d π θ n o w [ E A ∼ π θ n o w ( ⋅ ∣ S ) [ π θ ( A ∣ S ) π θ n o w ( A ∣ S ) ⋅ A π θ n o w ( S , A ) ] ] \mathbb{E}_{S\sim d^{\pi_{{\theta_{now}}}}}\left[\mathbb{E}_{A\sim\pi_{\theta_{now}}(·|S)}\left[\frac{ \pi_{\theta}(A|S) }{\pi_{\theta_{now}}(A|S)}\cdot A_{\pi_{\theta_{now}}}(S,A)\right]\right] ESdπθnow[EAπθnow(S)[πθnow(AS)πθ(AS)Aπθnow(S,A)]]

    2. 用 MC 近似消去上式中的两个期望。具体而言,先用当前策略 π θ n o w \pi_{\theta_{now}} πθnow 和环境交互收集一条轨迹
      s 1 , a 1 , r 1 , s 2 , a 2 , r 2 , . . . , s n , a n , r n s_1, a_1, r_1, s_2, a_2, r_2,...,s_n, a_n, r_n s1,a1,r1,s2,a2,r2,...,sn,an,rn 此轨迹满足 s t ∼ d π θ n o w , a t ∼ π θ n o w ( ⋅ ∣ s t ) s_t\sim d^{\pi_{\theta_{now}}}, a_t\sim \pi_{\theta_{now}}(·|s_t) stdπθnow,atπθnow(st),故每个 ( s t , a t ) (s_t,a_t) (st,at) 二元组都能构造一个无偏 MC 估计
      π θ ( a t ∣ s t ) π θ n o w ( a t ∣ s t ) ⋅ A π θ n o w ( a t , s t ) \frac{ \pi_{\theta}(a_t|s_t) }{\pi_{\theta_{now}}(a_t|s_t)}\cdot A_{\pi_{\theta_{now}}}(a_t,s_t) πθnow(atst)πθ(atst)Aπθnow(at,st) 用这些无偏估计的期望(均值)来近似原始优化目标,得到
      1 n ∑ t = 1 n π θ ( a t ∣ s t ) π θ n o w ( a t ∣ s t ) ⋅ A π θ n o w ( a t , s t ) \frac{1}{n}\sum_{t=1}^n \frac{ \pi_{\theta}(a_t|s_t) }{\pi_{\theta_{now}}(a_t|s_t)}\cdot A_{\pi_{\theta_{now}}}(a_t,s_t) n1t=1nπθnow(atst)πθ(atst)Aπθnow(at,st)

    3. 最后我们考虑如何估计优势函数 A π θ n o w ( a t , s t ) A_{\pi_{\theta_{now}}}(a_t,s_t) Aπθnow(at,st)。目前比较常用的方法是 广义优势估计(Generalized Advantage Estimation,GAE),先简介一下 GAE

      首先将 TD Error 表示为 δ t = r t + γ V ( s t + 1 ) − V ( s t ) \delta_t = r_t + \gamma V(s_{t+1})-V(s_t) δt=rt+γV(st+1)V(st),其中 V V V 是一个已经学习的状态价值函数,根据多步 TD 思想有
      A t ( 1 ) = δ t = − V ( s t ) + r t + γ V ( s t + 1 ) A t ( 2 ) = δ t + γ δ t + 1 = − V ( s t ) + r t + γ r t + 1 + γ 2 V ( s t + 2 ) A t ( 3 ) = δ t + γ δ t + 1 + γ 2 δ t + 2 = − V ( s t ) + r t + γ r t + 1 + γ 2 r t + 2 + γ 3 V ( s t + 3 ) ⋮ ⋮ A t ( k ) = ∑ l = 0 k − 1 γ l δ t + l = − V ( s t ) + r t + γ r t + 1 + … + γ k − 1 r t + k − 1 + γ k V ( s t + k ) \begin{array}{ll} A_{t}^{(1)}=\delta_{t} & =-V\left(s_{t}\right)+r_{t}+\gamma V\left(s_{t+1}\right) \\ A_{t}^{(2)}=\delta_{t}+\gamma \delta_{t+1} & =-V\left(s_{t}\right)+r_{t}+\gamma r_{t+1}+\gamma^{2} V\left(s_{t+2}\right) \\ A_{t}^{(3)}=\delta_{t}+\gamma \delta_{t+1}+\gamma^{2} \delta_{t+2} & =-V\left(s_{t}\right)+r_{t}+\gamma r_{t+1}+\gamma^{2} r_{t+2}+\gamma^{3} V\left(s_{t+3}\right) \\ \vdots & \vdots \\ A_{t}^{(k)}=\sum_{l=0}^{k-1} \gamma^{l} \delta_{t+l} & =-V\left(s_{t}\right)+r_{t}+\gamma r_{t+1}+\ldots+\gamma^{k-1} r_{t+k-1}+\gamma^{k} V\left(s_{t+k}\right) \end{array} At(1)=δtAt(2)=δt+γδt+1At(3)=δt+γδt+1+γ2δt+2At(k)=l=0k1γlδt+l=V(st)+rt+γV(st+1)=V(st)+rt+γrt+1+γ2V(st+2)=V(st)+rt+γrt+1+γ2rt+2+γ3V(st+3)=V(st)+rt+γrt+1++γk1rt+k1+γkV(st+k) GAE 将这些不同步数的优势估计进行指数加权平均:
      A t G A E = ( 1 − λ ) ( A t ( 1 ) + λ A t ( 2 ) + λ 2 A t ( 3 ) + ⋯   ) = ( 1 − λ ) ( δ t + λ ( δ t + γ δ t + 1 ) + λ 2 ( δ t + γ δ t + 1 + γ 2 δ t + 2 ) + ⋯   ) = ( 1 − λ ) ( δ ( 1 + λ + λ 2 + ⋯   ) + γ δ t + 1 ( λ + λ 2 + λ 3 + ⋯   ) + γ 2 δ t + 2 ( λ 2 + λ 3 + λ 4 + … ) + ⋯   ) = ( 1 − λ ) ( δ t 1 1 − λ + γ δ t + 1 λ 1 − λ + γ 2 δ t + 2 λ 2 1 − λ + ⋯   ) = ∑ l = 0 ∞ ( γ λ ) l δ t + l \begin{aligned} A_{t}^{G A E} & =(1-\lambda)\left(A_{t}^{(1)}+\lambda A_{t}^{(2)}+\lambda^{2} A_{t}^{(3)}+\cdots\right) \\ & =(1-\lambda)\left(\delta_{t}+\lambda\left(\delta_{t}+\gamma \delta_{t+1}\right)+\lambda^{2}\left(\delta_{t}+\gamma \delta_{t+1}+\gamma^{2} \delta_{t+2}\right)+\cdots\right) \\ & =(1-\lambda)\left(\delta\left(1+\lambda+\lambda^{2}+\cdots\right)+\gamma \delta_{t+1}\left(\lambda+\lambda^{2}+\lambda^{3}+\cdots\right)+\gamma^{2} \delta_{t+2}\left(\lambda^{2}+\lambda^{3}+\lambda^{4}+\ldots\right)+\cdots\right) \\ & =(1-\lambda)\left(\delta_{t} \frac{1}{1-\lambda}+\gamma \delta_{t+1} \frac{\lambda}{1-\lambda}+\gamma^{2} \delta_{t+2} \frac{\lambda^{2}}{1-\lambda}+\cdots\right) \\ & =\sum_{l=0}^{\infty}(\gamma \lambda)^{l} \delta_{t+l} \end{aligned} AtGAE=(1λ)(At(1)+λAt(2)+λ2At(3)+)=(1λ)(δt+λ(δt+γδt+1)+λ2(δt+γδt+1+γ2δt+2)+)=(1λ)(δ(1+λ+λ2+)+γδt+1(λ+λ2+λ3+)+γ2δt+2(λ2+λ3+λ4+)+)=(1λ)(δt1λ1+γδt+11λλ+γ2δt+21λλ2+)=l=0(γλ)lδt+l 其中, λ ∈ [ 0 , 1 ] \lambda \in[0,1] λ[0,1] 是在 GAE 中额外引入的一个超参数

      1. λ = 0 \lambda=0 λ=0 时, A t G A E = δ t = r t + γ V ( s t + 1 ) − V ( s t ) A_{t}^{G A E} = \delta_t = r_t + \gamma V(s_{t+1})-V(s_t) AtGAE=δt=rt+γV(st+1)V(st) 是仅仅只看一步差分得到的优势
      2. λ = 1 \lambda=1 λ=1 时, A t G A E = ∑ l = 0 ∞ γ l δ t + l = ∑ l = 0 ∞ γ l r t + l − V ( s t ) A_{t}^{G A E}=\sum_{l=0}^{\infty} \gamma^{l} \delta_{t+l}=\sum_{l=0}^{\infty} \gamma^{l} r_{t+l}-V\left(s_{t}\right) AtGAE=l=0γlδt+l=l=0γlrt+lV(st) 是看每一步差分得到优势的完全平均值。

      利用 GAE 估计优势函数 A π θ n o w ( a t , s t ) A_{\pi_{\theta_{now}}}(a_t,s_t) Aπθnow(at,st) 时,需要计算 π n o w \pi_{now} πnow 交互得到的轨迹每个 timestep的 TD error δ t \delta_t δt,为此需要引入价值网络(critic)来估计 V θ n o w V_{\theta_{now}} Vθnow,得到所有 δ t \delta_t δt 后直接代入 GAE 公式 A t G A E = ∑ l = 0 ∞ ( γ λ ) l δ t + l A_{t}^{G A E}=\sum_{l=0}^{\infty}(\gamma \lambda)^{l} \delta_{t+l} AtGAE=l=0(γλ)lδt+l 即可

2.1.2 最大化

  • 最大化这一步是 PPO 和 TPRO 唯一的区别,首先二者的置信域约束优化问题均可表示为
    max ⁡ θ E S ∼ d π θ n o w E A ∼ π θ n o w ( ⋅ ∣ S ) [ π θ ( A ∣ S ) π θ n o w ( A ∣ S ) ⋅ A π θ n o w ( S , A ) ] s.t. E S ∼ d π θ n o w D KL [ π θ n o w ( ⋅ ∣ S ) ∣ ∣ π θ ( ⋅ ∣ S ) ] ≤ △ \begin{aligned} &\max_\theta &&\mathbb{E}_{S\sim d^{\pi_{{\theta_{now}}}}}\mathbb{E}_{A\sim\pi_{\theta_{now}}(·|S)}\left[\frac{ \pi_{\theta}(A|S) }{\pi_{\theta_{now}}(A|S)}\cdot A_{\pi_{\theta_{now}}}(S,A)\right] \\ &\text{s.t.} &&\mathbb{E}_{S\sim d^{\pi_{\theta_{now}}}} D_\text{KL}\big[\pi_{\theta_{now}}(·|S) || \pi_{\theta}(·|S) \big] \leq \triangle \end{aligned} θmaxs.t.ESdπθnowEAπθnow(S)[πθnow(AS)πθ(AS)Aπθnow(S,A)]ESdπθnowDKL[πθnow(S)∣∣πθ(S)]
    1. TRPO 使用泰勒展开近似、共轭梯度、线性搜索等方法直接求解约束优化问题
    2. PPO 使用拉格朗日乘子法、限制目标函数等方式去除约束,然后就可以直接用梯度下降简单地求解无约束最优化问题
  • 具体来说,PPO 有两种形式,一是 PPO-惩罚,二是 PPO-截断,我们接下来对这两种形式进行介绍:
    1. PPO-惩罚:用拉格朗日乘数法直接将 KL 散度的限制放进了目标函数中,将原问题转换为无约束优化问题。迭代过程中根据真实的 KL 散度值(约束效果)不断更新 KL 散度前的拉格朗日乘数(调节约束强度)。第 k k k 轮优化函数为:
      arg max ⁡ θ E S ∼ d π θ k E A ∼ π θ k ( ⋅ ∣ S ) [ π θ ( A ∣ S ) π θ k ( A ∣ S ) ⋅ A π θ k ( S , A ) − β D KL [ π θ k ( ⋅ ∣ S ) ∣ ∣ π θ ( ⋅ ∣ S ) ] ] \argmax_\theta \mathbb{E}_{S\sim d^{\pi_{{\theta_{k}}}}}\mathbb{E}_{A\sim\pi_{\theta_{k}}(·|S)}\left[\frac{ \pi_{\theta}(A|S) }{\pi_{\theta_{k}}(A|S)}\cdot A_{\pi_{\theta_{k}}}(S,A)-\beta D_\text{KL}\big[\pi_{\theta_{k}}(·|S) || \pi_{\theta}(·|S) \big] \right] θargmaxESdπθkEAπθk(S)[πθk(AS)πθ(AS)Aπθk(S,A)βDKL[πθk(S)∣∣πθ(S)]] d k = D KL [ π θ k ( ⋅ ∣ S ) ∣ ∣ π θ ( ⋅ ∣ S ) ] d_k = D_\text{KL}\big[\pi_{\theta_{k}}(·|S) || \pi_{\theta}(·|S) \big] dk=DKL[πθk(S)∣∣πθ(S)] β \beta β 的更新规则如下
      β k + 1 = { β k 2 , d k < δ 1.5 2 β k , d k > 1.5 δ β k , o t h e r w i s e \beta_{k+1}=\left\{ \begin{aligned} \frac{\beta_k}{2}, && d_k < \frac{\delta}{1.5} \\ 2\beta_k, && d_k >1.5 \delta \\ \beta_k, && otherwise \end{aligned} \right. βk+1= 2βk,2βk,βk,dk<1.5δdk>1.5δotherwise 其中 δ \delta δ 是事先设定的一个超参数,用于限制学习策略和之前一轮策略的差距
    2. PPO-截断:直接在目标函数中进行限制,以保证新的参数和旧的参数的差距不会太大。第 k k k 轮优化函数为:
      arg ⁡ max ⁡ θ E S ∼ d π θ k E A ∼ π θ k ( ⋅ ∣ S ) [ min ⁡ ( π θ ( A ∣ S ) π θ θ k ( A ∣ S ) A π θ k ( S , A ) ,    clip ⁡ ( π θ ( A ∣ S ) π θ k ( A ∣ S ) , 1 − ϵ , 1 + ϵ ) A π θ k ( S , A ) ) ] \underset{\theta}{\arg \max }\mathbb{E}_{S\sim d_{\pi_{{\theta_{k}}}}}\mathbb{E}_{A\sim\pi_{\theta_{k}}(·|S)}\left[\min \left(\frac{\pi_{\theta}(A \mid S)}{\pi_{\theta_{\theta_{k}}}(A \mid S)} A_{\pi_{\theta_{k}}}(S, A), \space\space\operatorname{clip}\left(\frac{\pi_{\theta}(A \mid S)}{\pi_{\theta_{k}}(A \mid S)}, 1-\epsilon, 1+\epsilon\right) A_{\pi_{\theta_{k}}}(S, A)\right)\right] θargmaxESdπθkEAπθk(S)[min(πθθk(AS)πθ(AS)Aπθk(S,A),  clip(πθk(AS)πθ(AS),1ϵ,1+ϵ)Aπθk(S,A))] 其中 clip ( x , l , r ) : = max ⁡ ( min ⁡ ( x , r ) , l ) \text{clip}(x,l,r):=\max(\min(x,r),l) clip(x,l,r):=max(min(x,r),l),即把 x x x 限制在 [ l , r ] [l,r] [l,r] 内,上式中 ϵ \epsilon ϵ 是一个超参数,表示进行截断的范围。注意 min 操作中的两个选择,后者就是把前者 clip 到 [ 1 − ϵ , 1 + ϵ ] [1-\epsilon, 1+\epsilon] [1ϵ,1+ϵ] 而已。直接将两个系数的曲线如下画出来
      在这里插入图片描述
      其中绿色虚线是 π θ ( A ∣ S ) π θ θ k ( A ∣ S ) \frac{\pi_{\theta}(A \mid S)}{\pi_{\theta_{\theta_{k}}}(A \mid S)} πθθk(AS)πθ(AS),蓝色虚线是 clip ⁡ ( π θ ( A ∣ S ) π θ θ k ( A ∣ S ) , 1 − ε , 1 + ε ) \operatorname{clip}\big(\frac{\pi_{\theta}(A \mid S)}{\pi_{\theta_{\theta_{k}}}(A \mid S)}, 1-\varepsilon, 1+\varepsilon\big) clip(πθθk(AS)πθ(AS),1ε,1+ε),红色实线是优势函数 A ( s t , a t ) A(s_t,a_t) A(st,at) 不同取值时 min ⁡ \min min 操作选出的系数。以左图 A ( s , a ) > 0 A(s,a)>0 A(s,a)>0 的情况为例分析
      1. A ( s , a ) > 0 A(s,a)>0 A(s,a)>0意味着状态 s s s 处动作 a a a 带来了好处,所以为了鼓励 a a a 出现系数应尽量大,但是不要超过 1 + ϵ 1+\epsilon 1+ϵ (就是说 s t s_t st 处选择 a t a_t at 的概率不要比现在高超过 1 + ϵ 1+\epsilon 1+ϵ 倍 ),以免策略网络出现 overstep
      2. 系数小于 1 时说明网络还处于欠拟合状态,并没有学到此时应在 s s s 位置鼓励选择动作 a a a,这时就不用限制了。所以注意到红色线有上限而无下限
  • 大量实验表明,PPO-截断总是比 PPO-惩罚表现得更好

2.2 伪代码

  • PPO-截断的伪代码如下
    在这里插入图片描述

2.3 用 PPO 方法解决 CartPole 问题

  • 本节实验使用 gym 自带的 CartPole-V0 环境。这是一个经典的一阶倒立摆控制问题,agent 的任务是通过左右移动保持车上的杆竖直,若杆的倾斜度数过大,或者车子离初始位置左右的偏离程度过大,或者坚持时间到达 200 帧,则游戏结束
    在这里插入图片描述
    关于此环境动作状态空间、奖励函数及初始状态分布等的详细说明请参考 CartPole-V0
  • 下面给出完整代码
    import gym
    import torch
    import random
    import torch.nn.functional as F
    import numpy as np
    import matplotlib.pyplot as plt
    from tqdm import tqdm
    from gym.utils.env_checker import check_env
    from gym.wrappers import TimeLimit 
    
    class PolicyNet(torch.nn.Module):
        ''' 策略网络是一个两层 MLP '''
        def __init__(self, input_dim, hidden_dim, output_dim):
            super(PolicyNet, self).__init__()
            self.fc1 = torch.nn.Linear(input_dim, hidden_dim)
            self.fc2 = torch.nn.Linear(hidden_dim, output_dim)
    
        def forward(self, x):
            x = F.relu(self.fc1(x))             # (1, hidden_dim)
            x = F.softmax(self.fc2(x), dim=1)   # (1, output_dim)
            return x
    
    class VNet(torch.nn.Module):
        ''' 价值网络是一个两层 MLP '''
        def __init__(self, input_dim, hidden_dim):
            super(VNet, self).__init__()
            self.fc1 = torch.nn.Linear(input_dim, hidden_dim)
            self.fc2 = torch.nn.Linear(hidden_dim, 1)
    
        def forward(self, x):
            x = F.relu(self.fc1(x))
            x = self.fc2(x)
            return x
    
    class PPO(torch.nn.Module):
        def __init__(self, state_dim, hidden_dim, action_range, actor_lr, critic_lr, lmbda, epochs, eps, gamma, device):
            super().__init__()
            self.actor = PolicyNet(state_dim, hidden_dim, action_range).to(device)
            self.critic = VNet(state_dim, hidden_dim).to(device) 
            self.actor_optimizer = torch.optim.Adam(self.actor.parameters(), lr=actor_lr)
            self.critic_optimizer = torch.optim.Adam(self.critic.parameters(), lr=critic_lr)
            
            self.device = device
            self.gamma = gamma
            self.lmbda = lmbda      # GAE 参数
            self.epochs = epochs    # 一条轨迹数据用来训练的轮数
            self.eps = eps          # PPO 中截断范围的参数
            self.device = device        
    
        def take_action(self, state):
            state = torch.tensor(state, dtype=torch.float).to(self.device)
            state = state.unsqueeze(0)
            probs = self.actor(state)
            action_dist = torch.distributions.Categorical(probs)
            action = action_dist.sample()
            return action.item()
    
        def compute_advantage(self, gamma, lmbda, td_delta):
            ''' 广义优势估计 GAE '''
            td_delta = td_delta.detach().numpy()
            advantage_list = []
            advantage = 0.0
            for delta in td_delta[::-1]:
                advantage = gamma * lmbda * advantage + delta
                advantage_list.append(advantage)
            advantage_list.reverse()
            return torch.tensor(np.array(advantage_list), dtype=torch.float)
    
        def update(self, transition_dict):
            states = torch.tensor(np.array(transition_dict['states']), dtype=torch.float).to(self.device)
            actions = torch.tensor(transition_dict['actions']).view(-1, 1).to(self.device)
            rewards = torch.tensor(transition_dict['rewards'], dtype=torch.float).view(-1, 1).to(self.device)
            next_states = torch.tensor(np.array(transition_dict['next_states']), dtype=torch.float).to(self.device)
            dones = torch.tensor(transition_dict['dones'], dtype=torch.float).view(-1, 1).to(self.device)
    
            td_target = rewards + self.gamma * self.critic(next_states) * (1-dones)
            td_delta = td_target - self.critic(states)
            advantage = self.compute_advantage(self.gamma, self.lmbda, td_delta.cpu()).to(self.device)
            old_log_probs = torch.log(self.actor(states).gather(1, actions)).detach()
    
            # 用刚采集的一条轨迹数据训练 epochs 轮
            for _ in range(self.epochs):
                log_probs = torch.log(self.actor(states).gather(1, actions))
                ratio = torch.exp(log_probs - old_log_probs)
                surr1 = ratio * advantage
                surr2 = torch.clamp(ratio, 1 - self.eps, 1 + self.eps) * advantage  # 截断
                actor_loss = torch.mean(-torch.min(surr1, surr2))                   # PPO损失函数
                critic_loss = torch.mean(F.mse_loss(self.critic(states), td_target.detach()))
                
                # 更新网络参数
                self.actor_optimizer.zero_grad()
                self.critic_optimizer.zero_grad()
                actor_loss.backward()
                critic_loss.backward()
                self.actor_optimizer.step()
                self.critic_optimizer.step()
    
    if __name__ == "__main__":
        def moving_average(a, window_size):
            ''' 生成序列 a 的滑动平均序列 '''
            cumulative_sum = np.cumsum(np.insert(a, 0, 0)) 
            middle = (cumulative_sum[window_size:] - cumulative_sum[:-window_size]) / window_size
            r = np.arange(1, window_size-1, 2)
            begin = np.cumsum(a[:window_size-1])[::2] / r
            end = (np.cumsum(a[:-window_size:-1])[::2] / r)[::-1]
            return np.concatenate((begin, middle, end))
    
        def set_seed(env, seed=42):
            ''' 设置随机种子 '''
            env.action_space.seed(seed)
            env.reset(seed=seed)
            random.seed(seed)
            np.random.seed(seed)
            torch.manual_seed(seed)
    
        state_dim = 4               # 环境观测维度
        action_range = 2            # 环境动作空间大小
        actor_lr = 1e-3
        critic_lr = 1e-2
        num_episodes = 500
        hidden_dim = 128
        gamma = 0.98
        lmbda = 0.95
        epochs = 10
        eps = 0.2
        device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
    
        # build environment
        env_name = 'CartPole-v0'
        env = gym.make(env_name, render_mode='rgb_array')
        check_env(env.unwrapped)    # 检查环境是否符合 gym 规范
        set_seed(env, 0)
    
        # build agent
        agent = PPO(state_dim, hidden_dim, action_range, actor_lr, critic_lr, lmbda, epochs, eps, gamma, device)
    
        # start training
        return_list = []
        for i in range(10):
            with tqdm(total=int(num_episodes / 10), desc='Iteration %d' % i) as pbar:
                for i_episode in range(int(num_episodes / 10)):
                    episode_return = 0
                    transition_dict = {
                        'states': [],
                        'actions': [],
                        'next_states': [],
                        'next_actions': [],
                        'rewards': [],
                        'dones': []
                    }
                    state, _ = env.reset()
    
                    # 以当前策略交互得到一条轨迹
                    while True:
                        action = agent.take_action(state)
                        next_state, reward, terminated, truncated, _ = env.step(action)
                        next_action = agent.take_action(next_state)
                        transition_dict['states'].append(state)
                        transition_dict['actions'].append(action)
                        transition_dict['next_states'].append(next_state)
                        transition_dict['next_actions'].append(next_action)
                        transition_dict['rewards'].append(reward)
                        transition_dict['dones'].append(terminated or truncated)
                        state = next_state
                        episode_return += reward
                                            
                        if terminated or truncated:
                            break
                        #env.render()
    
                    # 用当前策略收集的数据进行 on-policy 更新
                    agent.update(transition_dict)
    
                    # 更新进度条
                    return_list.append(episode_return)
                    pbar.set_postfix({
                        'episode':
                        '%d' % (num_episodes / 10 * i + i_episode + 1),
                        'return':
                        '%.3f' % episode_return,
                        'ave return':
                        '%.3f' % np.mean(return_list[-10:])
                    })
                    pbar.update(1)
    
        # show policy performence
        mv_return_list = moving_average(return_list, 29)
        episodes_list = list(range(len(return_list)))
        plt.figure(figsize=(12,8))
        plt.plot(episodes_list, return_list, label='raw', alpha=0.5)
        plt.plot(episodes_list, mv_return_list, label='moving ave')
        plt.xlabel('Episodes')
        plt.ylabel('Returns')
        plt.title(f'{agent._get_name()} on CartPole-V0')
        plt.legend()
        plt.savefig(f'./result/{agent._get_name()}.png')
        plt.show()                           
    
  • 收敛曲线如下所示
    在这里插入图片描述
    可见 PPO 的收敛速度和稳定性都比 前文 介绍的 REINFORCE with baseline 和 A2C 方法好得多

3. 总结

  • 置信域策略优化(TRPO)是一种利用置信域算法优化策略的 On-policy Online RL 方法,它的优化目标和策略梯度方法相同,每次策略训练仅使用上一轮策略采样的数据,是 policy-based 类算法中十分有代表性的工作之一。直觉性地理解,TRPO 给出的观点是:由于策略的改变导致数据分布的改变,这大大影响深度模型实现的策略网络的学习效果,所以通过划定一个可信任的策略学习区域,保证策略学习的稳定性和有效性
  • 近端策略优化 (PPO) 是 TRPO 的一种改进算法,它在实现上简化了 TRPO 中的复杂计算,并且它在实验中的性能大多数情况下会比 TRPO 更好,因此目前常被用作一种常用的基准算法。需要注意的是,TRPO 和 PPO 都属于在线策略学习算法,即使优化目标中包含重要性采样的过程,但其只是用到了上一轮策略的数据,而不是过去所有策略的数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/880589.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

超过2个G的视频怎么发给朋友?快来学视频压缩

影响视频体积大小的主要因素无非就是比特率、码率、格式以及视频时长等&#xff0c;当我们的视频文件过大无法通过平台或者软件发送给朋友的时候&#xff0c;就可以借助压缩的方法解决问题&#xff0c;下面就给大家分享几个压缩技巧&#xff0c;一起来看看吧。 方法一&#xff…

LeetCode 热题 100(四):48. 旋转图像、240. 搜索二维矩阵 II、234. 回文链表

一.48. 旋转图像 题目要求&#xff1a;就是一个顺时针的旋转过程。 思路&#xff1a;观察矩阵&#xff0c;得出翻转前第i行的第J个元素 等于 翻转后倒数第i列的第J个元素&#xff0c;举例说明&#xff0c;第1行第2个元素为“2”&#xff0c;翻转后到了 倒数第1列的第2个元素…

AIGC|AGI究竟是什么?为什么大家都在争先入场?

一、AI大语言模型进入爆发阶段 2022年12月ChatGPT突然爆火&#xff0c;原因是其表现出来的智能化已经远远突破了我们的常规认知。虽然其呈现在使用者面前仅仅只是一个简单的对话问答形式&#xff0c;但是它的内容化水平非常强大&#xff0c;甚至在某些方面已经超过人类了&#…

多主题自适应知识变现博客论坛,支持docker一键部署

iblog 给大家推荐一个多主题自适应&#xff0c;支持付费收款的博客论坛系统&#xff0c;支持docker一键部署&#xff0c;支持企业微信通知。 前端 多主题 自适应 个人页 后端 H2 console 运行命令 docker run -d --name iblog --restartalways -p 8080:8080 -e consoletrue …

易服客工作室:Pixwell主题 – 现代杂志/WordPress新闻主题

PixWell主题概述 Pixwell主题是一个强大、多用途和现代的WordPress杂志主题&#xff0c;具有像素完美的设计、出色的功能、完全响应和移动友好。它非常灵活&#xff0c;非常适合食谱、时尚、旅行、技术、个人或任何其他很棒的杂志和博客网站。 该主题与 Elementor、Cooked&am…

SAP MM学习笔记22- 购买发注的项目种类(明细Category)

SAP中控制购买流程的是购买发注页面中购买发注明细行的项目种类&#xff08;明细Category&#xff09;栏目。 ・项目种类&#xff08;明细Category&#xff09;有&#xff1a; 1&#xff0c; 标准 2&#xff0c;K 受托品 3&#xff0c;L 外注 4&#xff0c;S 仕入先直送…

Linux系统中基于NGINX的代理缓存配置指南

作为一名专业的爬虫程序员&#xff0c;你一定知道代理缓存在加速网站响应速度方面的重要性。而使用NGINX作为代理缓存服务器&#xff0c;能够极大地提高性能和效率。本文将为你分享Linux系统中基于NGINX的代理缓存配置指南&#xff0c;提供实用的解决方案&#xff0c;助你解决在…

Blender增强现实3D模型制作指南【AR】

推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 将静态和动画 3D 内容集成到移动增强现实 (AR) 体验中是增强用户沉浸感和参与度的高效方法。 然而&#xff0c;为 AR 创建 3D 对象可能相当艰巨&#xff0c;尤其是对于那些缺乏 3D 建模经验的人来说。 与添加视频或照片 AR…

智慧工地源码,PC+APP源码,项目管理端+企业监管端+数据大屏端

智慧工地概念 智慧工地是一种崭新的工程全生命周期管理理念&#xff0c;是指运用信息化手段&#xff0c;通过对工程项目进行精确设计和施工模拟&#xff0c;围绕施工过程管理&#xff0c;建立互联协同、智能生产、科学管理的施工项目信息化生态圈&#xff0c;并将此数据在虚拟…

python3 0基础学习笔记

0基础学习笔记&#xff0c;临时有事暂停后边会继续学习 基础内容1. 条件语句 if - elif - else2. 错误铺捉try - except(一种保险策略&#xff09;3. 四种开发模式4. 函数&#xff1a;def用来定义函数的5. 最大值最小值函数&#xff0c;max &#xff0c;min6. is 严格的相等&am…

神经网络基础-神经网络补充概念-02-逻辑回归

概念 逻辑回归是一种用于二分分类问题的统计学习方法&#xff0c;尽管名字中带有"回归"一词&#xff0c;但实际上它用于分类任务。逻辑回归的目标是根据输入特征来预测数据点属于某个类别的概率&#xff0c;然后将概率映射到一个离散的类别标签。 逻辑回归模型的核…

echarts绘制仪表盘

代码展示&#xff1a; /**绘制仪表盘图表 */function drawInstrument(id) {setTimeout(()> {var chart echarts.init(document.getElementById(id)); var option {series: [{name: 风险指数,type: gauge,center: [50%, 60%],radius: 90%,min: chartData.min,max: chartDat…

捷码低代码+智慧水务:降本增效,灵活应变

数字经济正在强势崛起&#xff0c;已成为未来经济发展的主要动力。如何通过数字化转型获得最大收益&#xff0c;成为当下各行业最关心的问题。水务行业&#xff0c;作为我国的传统行业&#xff0c;也迎来数字化转型的快速发展期。如何利用新技术&#xff0c;实现以创新为核心的…

Android splash.img的制作

在device\qcom\common\display\logo下找到logo_gen.py如果没有安装Python&#xff0c;先执行以下命令 sudo apt-get install python-imaging将需要制作logo的图片拷贝到logo_gen.py的同级目录 需要注意的是图片分辨率应该与设备屏分辨率一致运行如下命令生成splash.img,执行 py…

相约天津!全国智能汽车竞赛百度创意组总决赛通知

“全国大学生智能汽车竞赛”是教育部倡导的大学生科技A类竞赛&#xff0c;中国高等教育学会将其列为含金量最高的大学生竞赛之一&#xff0c;为《全国普通高校大学生竞赛排行榜》榜单内赛事。 飞桨共承办了百度完全模型组和百度智慧交通组两大赛道。下文为百度智慧交通组具体安…

NeMo 声纹识别VPR-实战

声纹识别(VPR) ,生物识别技术的一种,也称为说话人识别 ,是从说话人发出的语音信号中提取声纹信息,从应用上看,可分为: 说话人辨认(Speaker Identification):用以判断某段语音是若干人中的哪一个所说的,是“多选一”问题;说话人确认(Speaker Verification):用以确认某…

【Git】本地搭建Gitee、Github环境

本地 &#xff08;Local&#xff09; 1、使用命令生成公钥&#xff08;pub文件&#xff09; 1. $ ssh-keygen -t rsa -C "xxxxxxxemail.com" -f "github_id_rsa" 2. $ ssh-keygen -t rsa -C "xxxxxxxemail.com" -f "gitee_id_rsa" …

一文预览 | 8 月 16 日 NVIDIA 在 WAVE SUMMIT深度学习开发者大会 2023精彩亮点抢先看!

由深度学习技术及应用国家工程研究中心主办&#xff0c;百度飞桨和文心大模型承办的 WAVE SUMMIT深度学习开发者大会2023&#xff0c;将于 8 月 16 日在北京与大家见面。NVIDIA 作为技术合作伙伴&#xff0c;将携手百度飞桨参与这场技术盛会。 在这次大会中&#xff0c;NVIDIA…

重磅发布!曙光存储“3+N”,绿色存力新选择

8月9-10日&#xff0c;2023年数据中心市场年会在京举办。会上&#xff0c;中科曙光存储产品事业部总监石静发表《绿色存力 打通绿色数据中心最后一站》主题演讲。“在今天&#xff0c;数据中心正在成为‘高能耗’产业&#xff0c;绿色节能从可选项走向必选项。曙光存储跨越绿色…

论文复现--关于多视角动作捕捉工具箱 --XRMoCap的研究

分类&#xff1a;动作捕捉 github地址&#xff1a;https://github.com/openxrlab/xrmocap 所需环境&#xff1a; Ubuntu18.04&#xff0c;conda22.9.0&#xff0c;CUDA11.4 目录 环境配置 环境配置 conda create -n XRmocap python3.7 -y conda activate XRmocap# install ffm…