OpenAI Gymについて

# はじめに
強化学習とは一体？！とうくらいの初心者向けの資料です。

# OpenAI Gym

https://gym.openai.com/

# OpenAI Gymとは

イーロン・マスクらが率いる、人工知能（AI）を研究する非営利団体「OpenAI」が提供するゲームや課題を練習させることができるプラットフォーム。強化学習の研究環境として使われています。

# 強化学習とは

下記のサイトがおすすめです。
http://blog.brainpad.co.jp/entry/2017/02/24/121500
http://qiita.com/icoxfog417/items/242439ecd1a477ece312

# OpenAI Gym プラットフォーム

## Environments
https://gym.openai.com/envs

もっとも基本的なAI学習環境のAlgorithmicや、Atariのゲームを使用した環境であるAtariなど
様々なGymを配したEnvironmentsが用意されています。


## Gym
AIを実行させる環境です。

https://gym.openai.com/envs/CartPole-v0
こちらはAIの基本的な学習として使用されるCartPole。

摩擦のないトラックに沿って動くカートの上にポールが取り付けられていて、カートに左右どちらかに負荷をあたえることによりバランスをとり、なるべくポールが立っていられるようにするのが目的。
ポールが垂直から15度を超えると終了するか、またはカートが中心から2.4ユニット以上移動すると終了です。


パックマンも存在したりします。https://gym.openai.com/envs/MsPacman-v0

ページの下の方を見ていただくとわかると思いますが、
下記をアップロード・公表をしたり評価を競ったりすることができます。
・目的に則したAIの訓練データ(json形式)
・AIの訓練データを作成するアルゴリズム

# インストール

もっとも簡単なインストール方法は

```
pip install gym
```

下記のスクリプトが実行可能ならばOKです。

```cartpole.py
import gym
env = gym.make('CartPole-v0')
env.reset()
for _ in range(1000):
    env.render()
    env.step(env.action_space.sample())
```

こちらのスクリプトを実行させて、画面表示されたらOKです。
最低限のインストールはこちらで可能ですが、Atariのゲーム環境は使用できないです。

```
(Mac)
brew install cmake boost boost-python sdl2 swig wget

(Ubuntu)
apt-get install -y python-numpy python-dev cmake zlib1g-dev libjpeg-dev xvfb libav-tools xorg-dev python-opengl libboost-all-dev libsdl2-dev swig
```

今度はパックマン環境で稼働させてみます。

```pacman.py
import gym
env = gym.make('MsPacman-v0')
env.reset()
for _ in range(1000):
    env.render()
    env.step(env.action_space.sample())
```
画面表示されたらOKです。

詳しくは
https://github.com/openai/gym#installing-everything

※Windowsの場合はBashをインストールする必要がある模様。
http://qiita.com/onelittlenightmusic/items/11eefde5ddad57fd0727

# 動かしてみる

下記のように変更してみます。

```cartpole2.py
import gym
from gym import wrappers
env = gym.make('CartPole-v0')
for i_episode in range(20):
    observation = env.reset()
    for t in range(100):
        env.render()
        action = env.action_space.sample() # ここをカスタマイズするのが目的
        observation, reward, done, info = env.step(action)
        if done:
            print("Episode finished after {} timesteps".format(t+1))
            break
```

最初に申し上げますと
最適化されたactionを見つけるのが目的です。
そのために各要素の状態を出力してみます。


```cartpole2.py
import gym

env = gym.make('CartPole-v0')
for i_episode in range(20):
    observation = env.reset()
    for t in range(100):
        env.render()
        print("episode:{} timestep:{}".format(i_episode, t))
        
        action = env.action_space.sample() # ここをカスタマイズするのが目的
        observation, reward, done, info = env.step(action)
        
        print("action:{} type:{}".format(action, type(action))) #action
        print("observation:{}".format(observation)) #観測結果
        print("reward:{}".format(reward)) #報酬
        print("done:{}".format(done)) #episodeの終了かどうか
        print("info:{}".format(info)) #info
        
        if done:
            print("Episode finished after {} timesteps".format(t+1))
            break
```


```※cartpole2.pyの実行の出力
episode:8 timestep:14
action:1 type:<class 'int'>
observation:[-0.06585942 -0.62644917  0.19415687  1.19997887]
reward:1.0
done:False
info:{}
```

## 各要素の説明
observation (object)：環境の観察を表す環境固有のオブジェクト。例えば、カメラからのピクセルデータ、ロボットの関節角度および関節速度、またはボードゲームにおけるボード状態。
reward (float)：前回の行動によって得られた報酬の額。規模は環境によって異なりますが、目標は常に報酬を増やすことです。
done（boolean）：環境を再度リセットするかどうか。ほとんどの（ただしすべてではない）タスクは、明確に定義されたエピソードに分割され、真であることは、エピソードが終了したことを示します。 （たとえば、ポールがあまりにも遠くに傾いた、またはあなたの最後の人生を失ったなど）。
info（dict）：デバッグに役立つ診断情報。これは、学習に役立つこともあります（たとえば、環境の最後の状態変化の生の確率を含む可能性があります）。ただし、代理店の正式な評価では、これを学習に使用することはできません。

※下記の和訳より
https://gym.openai.com/docs

## actionの目的・意味
最適化されたactionを見つけるのがそもそもの目的です。

ではactionの中身はいったい？

各Gymにおけるactionを出力してみると
(1)CartPole-v0の場合のactionはInt型で値は0もしくは1
(2)MsPacman-v0の場合のactionはInt型で値は0～8
となっています。

理由は各gymのページの要約を見てみますと
下記のとおりと思われます。

(1)
https://gym.openai.com/envs/CartPole-v0
The system is controlled by applying a force of +1 or -1 to the cart. 
カートに対して+1もしくは-1を加えて制御するのが目的。よって0,1の2種で判別する

(2)
https://gym.openai.com/envs/MsPacman-v0
Each action is repeatedly performed for a duration of k frames, where k is uniformly sampled from {2,3,4}.
各actionはサンプリングされた2〜4フレーム期間内にわたって繰り返し実行される(和訳)
この和訳だけではよくわからないのですが、
いろいろ動かした上での筆者の理解としては
0〜8はindex番号でそれぞれのindexに対応したアクションが内包されている模様。

## 最適化されたjsonデータ作成には
学習データの抽出には下記を追加すれば出力されます。

```
import gym
from gym import wrappers
env = gym.make('CartPole-v0')
env = wrappers.Monitor(env, '/tmp/cartpole-experiment-1') # 追加
for i_episode in range(20):
    observation = env.reset()
    for t in range(100):
        env.render()
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)
        if done:
            print("Episode finished after {} timesteps".format(t+1))
            break
```

## 独自カスタマイズ
ここからがOpenAI Gymの本来の目的です。
上記の例ではあくまでもデフォルトで与えられているenv.action_space.sample()(ランダムにactionを生成する)を使用していますが、ここをカスタマイズします。

observationを活かしたactionの例としては

```cartpole3.py
import gym
from gym import wrappers

# カスタマイズされたaction
def get_action(observation):
    for i in range(observation.size):
        sum = observation[i]
    return 1 if sum > 0 else 0

# 実行
env = gym.make('CartPole-v0')
for i_episode in range(20):
    observation = env.reset()
    for t in range(100):
        env.render()
        action = get_action(observation)
        observation, reward, done, info = env.step(action)
        if done:
            print("Episode finished after {} timesteps".format(t+1))
            break
```

サイト上にアップされているものにはkerasやtenrflowを利用して最適化を試みているものもあるようです。