分别使用常规控制和强化学习方法解决cartpole swing-up问题

分别使用常规控制和强化学习方法解决cartpole swing-up问题

  • 使用常规方法控制
  • 使用强化学习来控制(重点说明)
    • ① 首先使用[spinningup](https://spinningup.openai.com/en/latest/)写好的算法来训练
  • ② 使用[stable baselines3](https://github.com/DLR-RM/stable-baselines3)提供的算法来训练
  • 参考

分别使用常规控制和强化学习方法解决cartpole swing-up问题_第1张图片
对于做强化学习的小伙伴,常见的是cartpole的平衡问题。可阅读论文Stephenson, 1908; Donaldson, 1960; Widrow, 1964; Michie & Chambers, 1968.
比平衡问题更加具有挑战性的是cartpole的swing-up问题,就是上图gif显示的控制策略,从pole垂下自然状态,通过控制cart使pole竖直平衡(具体来说通过控制施加在cart上的外力来控制pole竖直平衡)。具体阅读论文 Kimura & Kobayashi, 1999; Doya, 2000.

插播:倒立摆的艺术表演

【倒立摆合集】一、二、三阶倒立摆

使用常规方法控制

我们将物体的受力画出来

分别使用常规控制和强化学习方法解决cartpole swing-up问题_第2张图片
我们通过拉格朗日算法得出F的表达式。这需要将问题拆解成cart和pole两个小问题,然后分别得出他们的动能和势能关系。
首先从cart开始。
由于cart只能在平面上运动,所以其势能为0.
V c a r t = 0 V_{cart}=0 Vcart=0
cart的动能表达式也很简单
T c a r t = 1 2 M x ˙ 2 T_{cart}=\frac{1}{2} M \dot{x}^2 Tcart=21Mx˙2
M是cart的质量。

pole的势能是
V p o l e = m g l cos ⁡ ( θ ) V_{pole}=mgl \cos(\theta) Vpole=mglcos(θ)
m , g , l m,g,l m,g,l分别是pole的质量,受到的重力和长度。
但是pole的动能就很复杂,因为他与cart有关
T p o l e = m θ ˙ 2 l 2 + ( 2 cos ⁡ ( θ ) θ ˙ x ˙ l + x ˙ 2 ) 2 T_{pole}=\frac{m \dot \theta^2 l^2 + (2 \cos(\theta) \dot \theta \dot{x} l + \dot{x}^2)}{2} Tpole=2mθ˙2l2+(2cos(θ)θ˙x˙l+x˙2)

然后构造拉格朗日式子
L = T c a r t + T p o l e − V c a r t − V p o l e L=T_{cart}+T_{pole}-V_{cart}-V_{pole} L=Tcart+TpoleVcartVpole
使用欧拉-拉格朗日等式
d d t ∂ L ∂ q i ˙ = ∂ L ∂ q i \frac{d}{dt} \frac{ \partial{L} }{ \partial{\dot{q_i}} } = \frac{\partial L}{\partial q_i} dtdqi˙L=qiL
经过一些运算,就可以得出如下结果
x ¨ = F + m sin ⁡ ( θ ) ( g cos ⁡ ( θ ) + l θ ˙ 2 ) M + m sin ⁡ ( θ ) 2 \ddot{x}=\frac{F+m\sin(\theta)(g\cos(\theta)+l\dot{\theta}^2)}{M+m\sin(\theta)^2} x¨=M+msin(θ)2F+msin(θ)(gcos(θ)+lθ˙2)
θ ¨ = − F cos ⁡ ( θ ) + ( M + m ) g sin ⁡ ( θ ) + l m θ ˙ 2 s i n ( θ ) cos ⁡ ( θ ) l ( M + m sin ⁡ ( θ ) 2 ) \ddot{\theta}=-\frac{F\cos(\theta)+(M+m)g\sin(\theta)+lm\dot{\theta}^2sin(\theta)\cos(\theta)}{l(M+m\sin(\theta)^2)} θ¨=l(M+msin(θ)2)Fcos(θ)+(M+m)gsin(θ)+lmθ˙2sin(θ)cos(θ)
求得的 F F F就是施加在cart上的力。

使用强化学习来控制(重点说明)

看了上面的数学方程,相信是一股劝退的力量,仅仅是简单的cartpole swingup问题,数学解析式就要涉及数学推倒以及物理学的应用,这对于大部分人是一个阻碍。

那么有没有可以降低门槛的方式呢?可以让我在推不出数学解析式的情况下实现这个控制呢?强化学习就是一个很实际很简单的实现方式,它屏蔽了我们对于数学表达式的需求,使用一种类似人类学习某个知识的方法,从不断试错与总结经验中习得技能。不过话说回来,虽然强化学习免去了我们对于系统物理学、数学表达式的精确应用和推倒,但是却引入了强化学习这个方法,其实强化学习同样也是一个门槛(尬笑),也涉及到很多的算法,以及环境的封装等问题,门槛也不低。那么强化学习的优势在哪呢?对于cartpole这类简单的传统控制问题,使用常规控制同样也能取得非常好的效果(见文章开头提供的视频),但是对于类似atari游戏、dota2等高维输入信号的问题,强化学习已经取得了非常好的效果,但是如果使用常规控制,至少目前还没有特别成功的应用案例。

总体来说:
① 强化学习是一种普适性的学习方法,对于多种问题都能很好的解决,而且强化学习算法学习到的策略甚至在多数情况下,比人类的表现要好的多。
② 强化学习让工程师在对某个实际问题不是特别专业时,也能够使用强化学习技术编写程序解决。比如AlphaGo系统,开发工程师大多对围棋并不精深,只是请了一个外部的围棋参谋,就可以将人类的经验编写成程序,使程序也以一种像人类经验学习过程的学习方式学会下围棋。
③ 强化学习目前还处在快速的发展期,新的算法不断被提出,新的应用不断开发出来,从常规控制问题到机械臂、机器人的控制,从游戏控制到工业控制,强化学习都在不同的程度的应用着。

使用强化学习方法来训练agent,我们一般使用OpenAI Gym的API,使用Gym的step(), reset(), render(), close()API封装环境,然后就可以直接使用强化学习算法使用这4个接口来进行训练了。
环境的封装不是一个简单的任务,对于reward的评价、持续控制时电机力的设置、系统动力的方程式(如果使用刚体动力学仿真环境,可以忽略这步)等都是有些难以编程的。
我们在网上找到了两份可用的比较好的封装好的环境。

  1. Cart-Pole Swing-Up,对应的代码为jfpettit/cartpole-swingup-envs
  2. angelolovatto/gym-cartpole-swingup

第二份代码的action只有连续控制形式,所以得用适用于连续动作的强化学习算法来控制,比如PPO、TRPO等,第一份代码分别有连续动作和离散动作输出,可以适用于不同类型的强化学习算法。

① 首先使用spinningup写好的算法来训练

spinningup是openai官方出的包含强化学习基础知识、数学理论、经典论文、算法实现等一系列全栈参考教材,质量极高。对于新手学习强化学习、了解强化学习的数学基础以及基础算法实现是很有帮助的,缺点就是实现的算法较少、封装的不是很彻底(相对于stable baselines)。而且spinningup的代码目前不支持Windows,且代码已经长时间不更新了。

根据spinningup的安装说明,可以很容易的安装成功,mujoco暂且可以不安装。
根据运行实验的说明,我们知道怎么来使用spinningup封装好的算法。
同时在安装说明页面的最后,我们可以知道怎么来把训练结果用视频和图表的形式表现出来。
分别使用常规控制和强化学习方法解决cartpole swing-up问题_第3张图片
对于想仔细了解spinningup代码细节的小伙伴,建议把spinningup的源码clone下来细细品味。

我们使用PPO算法来进行训练,PPO算法的性能是非常出众的。使用jfpettit/cartpole-swingup-envs环境。上文提到的两个环境都可以,任选一个即可。

使用spinningup的ppo算法来训练cartpole-swingup的代码为:

NOTE:前提要安装好spinningup和cartpole-swingup-envs。

from spinup import ppo_pytorch as ppo
import torch
import torch.nn as nn
import gym
import cartpole_swingup_envs

env_fn=lambda:gym.make('CartPoleSwingUpContinuous-v0')
ac_kwargs=dict(hidden_sizes=[64,64],activation=nn.ReLU)
logger_kwargs=dict(output_dir='output',exp_name='cartpole_swingup')
ppo(env_fn=env_fn,ac_kwargs=ac_kwargs,steps_per_epoch=5000,
    epochs=300,logger_kwargs=logger_kwargs)

代码根据spinningup官方的TensorFlow实例修改而来。

分别使用常规控制和强化学习方法解决cartpole swing-up问题_第4张图片
上图是训练过程。

训练完成后,我们根据spinningup的复现结果代码实例,将训练好的结果通过视频的形式表现出来。

python -m spinup.run test_policy output

不幸的是,这里出现了读不懂的错误。已经提交了issue,但是目前还没有回复。

NOTE:这个错误鉴于我使用的是Python3.7,而spinningup推荐Python3.6,也有博主说spinningup只能在Python3.6下才能完全正常运行,所以感兴趣的小伙伴可以在Python3.6环境下试一下是否有错误。

② 使用stable baselines3提供的算法来训练

stable-baselines(TensorFlow 1.x版本)和stable-baselines3(pytorch版本)是对openai的baselines的大修改。baselines的缺点饱受诟病:代码非常不易读、耦合性太强、测试不充分等等。sb吸取baselines的教训,充分在易读性、易用性以及性能方面进行了优化,所以是目前较为优秀的强化学习算法包。

根据sb3的安装说明,轻易的即可安装成功。
根据sb3的代码实例,我们同样编写使用PPO算法训练cartpole-swingup-envs的代码。

import gym
from stable_baselines3 import A2C,PPO
import cartpole_swingup_envs

env=gym.make('CartPoleSwingUpContinuous-v0')
model=PPO('MlpPolicy',env,verbose=1)
model.learn(total_timesteps=1000000)

obs=env.reset()
for i in range(9000):
    action,_state=model.predict(obs,deterministic=True)
    obs,reward,done,info=env.step(action)
    env.render()
    if done:
        obs=env.reset()

分别使用常规控制和强化学习方法解决cartpole swing-up问题_第5张图片
训练过程如图。
训练结束后,就会运行上面代码的这部分代码

obs=env.reset()
for i in range(9000):
    action,_state=model.predict(obs,deterministic=True)
    obs,reward,done,info=env.step(action)
    env.render()
    if done:
        obs=env.reset()

以我们非常熟悉的gym标准方式以视频的方式输出训练结果。

强化学习PPO算法训练cartpole-swingup(倒立摆)


完整代码请戳这里


NOTE:关于cartpole-swingup这部分,仅以此文短短的说明,是不足以完全解释完全的,更多的细节以及实现的思考,请仔细阅读环境+算法这两部分的代码。关于环境的封装技巧,我们略过了,但是这是非常重要的一部分,关系到能不能训练成功,但是不是一时半会可以说完的,关于我们上文使用的环境的封装细节,请参考cartpole-swingup这篇文章。PPO算法的原理、代码的实现也请仔细阅读spinningup、stable baselines的实现。


参考

  1. SWING-UP OF AN INVERTED PENDULUM ON A CART
  2. Florian, R. (2005). Correct equations for the dynamics of the cart-pole system

你可能感兴趣的