<基礎学習>10/1-3 強化学習 OpenAI Gymでcartpoleゲームのチュートリアル

今は強化学習を勉強しています。
AlphaGoのアルゴリズムにも使われている激アツなやつです。

強化学習を勉強する目的

  • ロボットの動作を強化学習でやってみたい(知人の手伝い)
  • 投資で強化学習を動かしてみたい(自分がやってるやつ)

今日書くこと

以下について、参考にしたサイトを主に紹介します。

やったこ

1.勉強方法の考察

ちまたで流行っているDeep Q-Learning(DQN)をやりたい!
と思っていろいろ勉強したけどわけがわかりません。
以下サイトにたどり着きました。

qiita.com

ここから、実際にpongというゲームをDQNで学習しているという以下サイトを読み、プログラムを動かそうとしました。
postd.cc
が、Pythonのバージョンが違うのか動きません。

知人に相談したところ、「DQNDQN言うけど、お前まずQ-Learningって何かわかる?」と言われ、ちんぷんかんぷんな答えをしてしまいました。

2.理論の勉強

知人のアドバイスに基づき、Q-Learningがあって、Q-LearningのどこがDeep(ニューラルネットワーク化されてるの?)という疑問をまずは解決することにしました。

2-1.Q-Learning

qiita.com

「Q-Learning」のところを読んで、その場にいた別の人とディスカッションすること1時間。
よーやくなんとなくわかりました。

「状況」と「取れる行動」と「その行動をとった時の期待値」のテーブル(Q-Table)が、すべての状況・取れる行動・取った時の期待値に対して存在していて、それをチューニングするみたいです…。
テーブルの数めっちゃ膨大。
囲碁の盤面が1919、それぞれのマスが(白、黒、何もなし)の3通りだから、3**(1919)通りの状況(Q-Table)とその時に取れる行動があるわけですよね…。
AlphaGoではすべてのテーブルを用意するわけではなく、前段階である程度パターンを刈り取っているみたいですが。

2-2.Deep Q-Learning(DQN)

DQNは、Q-LearningのどこがDeepになっているの?→TD誤差を誤差逆伝播している
というのはなんとなくわかったのですが、式変形がわからない。
「まず、Q(s,a)をニューラルネットワーク化します」の下にある式変形の過程が理解できません。今、考え中です。

3.強化学習の実装

最近は理論の勉強とか業界知識の勉強ばかりで、実装をしていませんでした。
なので、手を動かします。
OpenAI Gymに前々から興味があったので、やってみます。

3-1.OpenAI Gymとは

OpenAI Gymとは、一言でいうとAIの性能テストができるところです。
いろんなゲームに対して自分が作ったAIがどれだけの性能が出るのか、試せます。
そのための基盤として、様々なゲームが用意されています。(多分)

3-2.OpenAI Gymのチュートリアル

ゲームはCartPoleをすることにしました。
小学校御用達の「指先でほうきを何秒立てられるか」ゲームのようなイメージですね。

www.youtube.com

導入にあたっては以下のサイトを参考にしました。 ◆OpenAI Gymのインストール(英語)
github.com

動かしてみると以下のようなエラーがでました

OSError: /home/owner/anaconda3/bin/../lib/libstdcsi++.so.6: version `GLIBCXX_3.4.20' not found (required by /home/owner/anaconda3/lib/python3.6/site-packages/atari_py/ale_interface/build/libale_c.so)

ググったら以下サイトが出てきました。
askubuntu.com
僕はAnacondaを使っているのですが、Anacondaにlibgccを入れないとダメみたいです。pip installじゃないです。以下コマンドを打つとちゃんと動きました。
conda install libgcc

◆CartPoleの動作 futurismo.biz
CartPoleは特に問題なく動作しました。

使い方を把握するため、ちょっと応用して2通りを試してみました

パターン1:ランダムに動かす

import gym
env = gym.make('CartPole-v0')
observation = env.reset()
count = 0
epoch_count = 0
total_count = 0
while epoch_count < 20:
    env.render() # 現在の状況を画面表示する
    # ランダムに動かす
    observation, reward, done, info = env.step(env.action_space.sample())

    count += 1
    if done:
        print("Episode finished after {} timesteps".format(count+1))
        total_count += count
        count = 0
        observation = env.reset()
        epoch_count += 1

print("試行回数:{0}, 平均:{1}".format(epoch_count, total_count/epoch_count))

結果
f:id:kurupical:20171004160138p:plain:w400

パターン2:棒の傾きと逆方向に動かす

import gym
env = gym.make('CartPole-v0')
observation = env.reset()
count = 0
epoch_count = 0
total_count = 0
while epoch_count < 20:
    env.render() # 現在の状況を画面表示する

    # 傾いている方と逆に動かす
    if observation[1] > 0:
        observation, reward, done, info = env.step(0)
    else:
        observation, reward, done, info = env.step(1)
    count += 1
    if done:
        print("Episode finished after {} timesteps".format(count+1))
        total_count += count
        count = 0
        observation = env.reset()
        epoch_count += 1

print("試行回数:{0}, 平均:{1}".format(epoch_count, total_count/epoch_count))

結果
f:id:kurupical:20171004160029p:plain:w400

ランダムに動かすより、ちょっと動きがよくなりました。

今後

ただ人様のサイトをペタペタはっているだけのブログになりました。
次回は、強化学習をさせてみてどうだったかをブログにアップします。