強化学習でスーパーマリオエージェントを作ってみる
スーパーマリオブラザーズをプレイするエージェントを作って遊んでみたいと思います。
openAI gymを利用します。
以下の記事を参考にやってみます。
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()
でてきた!
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)
とりあえずはこれで、ランダムに動くマリオエージェントの動作を確認できました。