強化学習でスーパーマリオエージェントを作ってみる

スーパーマリオブラザーズをプレイするエージェントを作って遊んでみたいと思います。
openAI gymを利用します。
以下の記事を参考にやってみます。

becominghuman.ai

1. FCEUXのインストール。

$ sudo apt install fceux

2. openAI用environmentをクローン。

$ git clone https://github.com/ppaquette/gym-super-mario

3. environmentをコピー
openAI gymのパッケージが置かれている場所に上記environmentをコピー。

$ cp -R ~/gym/mario/gym-super-mario/ppaquette_gym_super_mario/ ~/anaconda3/envs/tensorflow/lib/python3.6/site-packages/gym/envs

4. gymのenvironmentに手動で追加。
/gym/envs/__init__.py

register(
    id='SuperMarioBros-1-1-v0',
    entry_point='gym.envs.ppaquette_gym_super_mario:MetaSuperMarioBrosEnv'
)

5. マリオが出てくるか確認

import gym

env = gym.make('SuperMarioBros-1-1-v0')
env.reset()

f:id:oktok:20180819203014p:plain
でてきた!

6. とりあえず、ランダムに動くエージェントを作ってみる

import gym

env = gym.make('SuperMarioBros-1-1-v0')
observation = env.reset()
while True:
    action = env.action_space.sample()  # choose random action
    observation, reward, done, info = env.step(action)  # feedback from environment

・・・ところが env.action_space.sample() が常に[0,0,0,0,0,0]を返してしまい、マリオがまったく動かない。
pdbで追ってみると、どうもnp_random.randで生成した0.0~1.0の小数を整数型にキャストしているからみたい。

class MultiDiscrete(gym.Space):
    def __init__(self, nvec):
        """
        nvec: vector of counts of each categorical variable
        """
        self.nvec = np.asarray(nvec, dtype=np.int32)
        assert self.nvec.ndim == 1, 'nvec should be a 1d array (or list) of ints'
        gym.Space.__init__(self, (self.nvec.size,), np.int8)
    def sample(self):
        return (gym.spaces.np_random.rand(self.nvec.size) * self.nvec).astype(self.dtype)

なのでキャストの前に0.5を足しておく。
※ただこの対処で良いのか不明・・。使い方を間違えているような気がする・・。

class MultiDiscrete(gym.Space):
    def __init__(self, nvec):
        """
        nvec: vector of counts of each categorical variable
        """
        self.nvec = np.asarray(nvec, dtype=np.int32)
        assert self.nvec.ndim == 1, 'nvec should be a 1d array (or list) of ints'
        gym.Space.__init__(self, (self.nvec.size,), np.int8)
    def sample(self):
        return (gym.spaces.np_random.rand(self.nvec.size) * self.nvec + 0.5).astype(self.dtype)

とりあえずはこれで、ランダムに動くマリオエージェントの動作を確認できました。

次からは強化学習アルゴリズムを実装してマリオを動かしてみたいと思います。