ゲーム感覚で学べる強化学習ツールキット「Gym」を試す

2019.07.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コンニチハ、千葉です。

巷でDeepRacerが話題で、すごく流行しています!DeepRacerとは、強化学習を遊んで学べるAWSサービスの1つです。自動運転に関するモデルを強化学習で作り、仮想上または現実のコースを走行させることができます。AWS Summitで大会が開かれており、優勝者がre:Inventに招待され、世界大会も開催されます。すごく燃えますね!

https://aws.amazon.com/jp/deepracer/league/

今回はローカル端末で機械学習を学べる「Gym」で感覚をつかみ、DeepRacerにフィードバックできればなーと思いやってみました。

Gymとは?

Gymは強化学習アルゴリズムを開発し比較するためのツールキットです。ウォーキングからピンボールのようなゲームを通して、機械学習を学ぶことをサポートします。

いろんな種類の環境が用意されています。https://gym.openai.com/envs/#classic_control

棒のバランスをとるようなものから、インベーダーゲームのような2Dゲームまで、数がかなりあります!絵を見てるだけで楽しそうですね。

やってみた

環境

  • MacOS Mojave(10.14.5)
  • Python 3.5以上をインストール

インストール

インストールは簡単です。 環境に合わせてパッケージをイストールしましょう。 https://github.com/openai/gym#installing-everything

$ python3 --version
Python 3.6.5
$ brew install cmake boost boost-python sdl2 swig wget
$ pip3 install gym

動作させてみる

今回は、カートの上にポールを立たせるための問題をやってみます。

import gym
from gym import wrappers

env = gym.make('CartPole-v0')
env = wrappers.Monitor(env, "./movie", force=True)
for i_episode in range(1):
    observation = env.reset()
    for t in range(1000):
        env.render()
        print(observation)
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)
        if done:
            print("Episode finished after {} timesteps".format(t+1))
            break
env.close()

2D、3Dの環境を利用する場合はMuJoCoライセンスが必要になります。今回試しているものはライセンスなくても大丈夫です。

実行すると、こんな映像が見れます。一瞬で動画は終了しています。これは各環境ごとにdoneの条件が指定されており、今回は棒が倒れると判断されたため一瞬で動画が終了しています。

パラメータの整理

では、棒が立つようにアルゴリズムを考えましょう。 まず、この環境にはどんなパラメータがあるか整理します。

observation(オブジェクト型)

環境観察を表す環境特有のオブジェクト。例えば、カメラからのピクセルデータ、ロボットの関節角度および関節速度、またはボードゲームにおけるボード状態。今回のカートポール問題だと4つの状態を取得できます。

  • 0 Cart Position -4.8 4.8
  • 1 Cart Velocity -Inf Inf
  • 2 Pole Angle -24 deg 24 deg
  • 3 Pole Velocity At Tip -Inf Inf

アクション

棒にアクションを加えます。observationにより状態を取得し、状態によりどのようなアクションをするか決めます。角度や速度により、カートを右or左に動かします。

  • 0 Push cart to the left
  • 1 Push cart to the right

reward(不動小数点型)

前の行動によって達成された報酬の量。規模は環境(今回だとカートポール問題)によって異なりますが、目標は常に総報酬を増やすことです。 今回のカートポート問題であれば、棒が垂直に立つようにすると報酬が増えます。

done(真偽値)

環境をresetすべきかを判断します。これは環境ごと(今回だとカートポール問題)に異なります。(例えば、多分ポールが傾きすぎたらゲームオーバー)

info(ディクショナリー型)

デバッグに役立つ診断情報、学習に役立つことがあります(たとえば、環境の最後の状態変化の背後にある生の確率が含まれる場合があります)。ただし、エージェントの公式評価はこれを学習に使用することを許可されていません。

自分のアルゴリズムでやってみる

私は初心者なので、アルゴリズムの考え方はいろいろあると思いますが、とりあえず自分が思いつく方針で、アルゴリズムを作ってみました。

  • Cart Position:カートの場所が、どこにあるかです。なるべく真ん中になるようにした方がよさそうです。でないと、フィールドからはみ出るので環境のリセットが必要になります。つまりゲームオーバー。
  • Cart Velocity:カートの速度です。カート速度が速くなると、棒も不安定になると思うので、なるべく値が低い方が望ましそうです。
  • Pole Angle: ポールの角度です。-41.8度(左)から+41.8度(右)の間で取得できます。角度が12度以上でゲームオーバーです。この値が0に近いほどいい状態になりそうです。
  • Pole Velocity At Tip:棒の選択速度です。こちらも、速度が速くなると不安定になるので、なるべく低い値が望ましそうです。

整理すると

  • Cart Position:0に近づける
  • Cart Velocity:値を低く保つ
  • Pole Angle:0に近づける
  • Pole Velocity At Tip:値を低く保つ

今回はシンプルに、棒がまっすぐになるようにすることだけ考えて、アクションを指定してみました。

  • 棒の角度が-になったらカートを左に押す
  • 棒の角度が+になったらカードを右に押す
import gym
from gym import wrappers

env = gym.make('CartPole-v0')
env = wrappers.Monitor(env, "./movie", force=True)
for i_episode in range(5):
    observation = env.reset()
    for t in range(1000):
        env.render()
        print(observation)

        # 棒の角度が-になったらカートを左に押す、棒の角度が+になったらカードを右に押す
        if observation[2] > 0.05:
            action = 1
        elif observation[2] < -0.05:
            action = 0
        else:
            action = 1
        observation, reward, done, info = env.step(action)
        if done:
            print("Episode finished after {} timesteps".format(t+1))
            break
env.close()

1秒は生存してくれるようになりました。

あたりまえですが、全然だめですねw

ChainerRLで深層強化学習してみる

ChainerRLのガイドを元に、深層強化学習してみました。

ChainerRLを使っみたところ、かなりいい感じで棒が立つようになりました!

さいごに

機械学習をさくっと試すことができました。結構簡単に試せるので、機械学習気になってる方はやってみてはいかがでしょうか。

そして今日、7/7は私の誕生日。そして、クラスメソッドの創立記念日。誕生記念ブログでした。 最後まで読んでいただきありがとうございました!

参考