前回の記事で考えたゲームをGymに登録していきます。
Gymへのゲーム環境の登録方法は以下です。
- gym.Envを継承して、ゲーム環境のクラスを作る。
まずはgym.Envを継承して、以下のプロパティ・メソッドを実装したクラスを作ります。
プロパティ | 意味 |
action_space | Agentがどんな行動を選択できるかを表す。(出力層) |
observation_space | Agentが観測できるゲーム環境のパラメータ。(入力層) |
reward_range | 報酬の最小値から最大値の範囲。 |
メソッド | 意味 |
_step(self,action) | action(Agentの行動)に対する結果(observation, reward, done, info)を返す。 |
_reset(self) | ゲーム環境を初期化する |
_render(self, mode, close) | ゲーム環境を可視化する |
_close(self) | 環境を閉じて、後処理をする |
_seed(self,seed) | ランダムシードを固定する |
_close(), _seed()はなくても良いようです。
最初間違えて、reward_rangeの設定範囲外の報酬を与えていましたが問題なく学習していたので、これもあまり関係ないのかな。
上記のメソッドの中で一番難しいのは、_stepの返り値のreward(報酬)の決め方だと思います。以下ソースコードでは111行目~123行目で定義しています。
今回のゲームの報酬は、
①(HEROが死んだときの報酬) << (BOSSを倒した時の報酬) となるようにしました。
②HEROが死んだ時場合は相手に与えたダメージが大きいほど報酬が多くなる
③BOSSを倒すまでにかかったターン数が多い場合は報酬を少し減らす。
という考えのもと設定しました。
報酬の②の考え方は、BOSSを倒す経験ができなかった場合に、呪文を連打して死んでいくAIができそうですが、まあ、後で調整しようと思います(笑)。
↓ソースコード ( env.py )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# coding: utf-8 import sys import gym import numpy as np import gym.spaces class BOSS(): #行動の種類 # ダメージ(回復量) 消費MP #0:大呪文 40, 25 #1:攻撃 10, 0 HP_MAX = 200. MP_MAX = 100. def __init__(self): self.hp = self.HP_MAX self.mp = self.MP_MAX def select_action(self): if self.mp >= 25.: return 0 #0:大呪文 else: return 1 #1:攻撃 class HERO(): #行動の種類 # ダメージ(回復量) 消費MP #0:呪文 20, 10 #1:回復 -50, 5 #2:攻撃 10, 0 HP_MAX = 100. MP_MAX = 100. def __init__(self): self.hp = self.HP_MAX self.mp = self.MP_MAX class battle(gym.Env): def __init__(self): super().__init__() # action_space, observation_space, reward_range を設定する self.action_space = gym.spaces.Discrete(3) # Heroの行動の数 self.observation_space = gym.spaces.Box( low = 0., # 最小値 high = 100., # 最大値 shape=(2,) # 観測値 -> ( 自分のHP, MP, ) ) self.reward_range = [-500., 500.] # WIN or LOSE self._reset() def _reset(self): # 諸々の変数を初期化する self.HERO = HERO() self.BOSS = BOSS() self.done = False self.steps = 0 return self._observe() def _step(self, action): # 1ステップ進める処理を記述。戻り値は observation, reward, done(ゲーム終了したか), info(追加の情報の辞書) boss_action = self.BOSS.select_action() # ①敵の行動 if boss_action == 0: # 大呪文 if self.BOSS.mp >= 25.: self.BOSS.mp -= 25. self.HERO.hp -= 40. elif boss_action == 1: # 攻撃 self.HERO.hp -= 10. # ②自分の行動 if self.HERO.hp > 0: # 生きてれば行動可能 if action == 0: # 呪文 if self.HERO.mp >= 10.: self.BOSS.hp -= 20. self.HERO.mp -= 10. elif action == 1: # 回復 if self.HERO.mp >= 5.: if self.HERO.hp < self.HERO.HP_MAX: self.HERO.hp += 50. self.HERO.mp -= 5. elif action == 2: # 攻撃 self.BOSS.hp -= 10. # ③ターン数を進める self.steps += 1 # ④hp調整 if self.BOSS.hp < 0: self.BOSS.hp = 0 if self.HERO.hp < 0: self.HERO.hp = 0 elif self.HERO.hp > self.HERO.HP_MAX: # 回復しすぎていた場合に調整 self.HERO.hp = self.HERO.HP_MAX observation = self._observe() reward = self._get_reward() self.done = self._is_done() return observation, reward, self.done, {} def _render(self, mode='human', close=False): # human の場合はコンソールに出力。ansiの場合は StringIO を返す outfile = StringIO() if mode == 'ansi' else sys.stdout outfile.write( "HERO hp:"+str(self.HERO.hp)+",\tmp:"+ str(self.HERO.mp) + "\tBOSS hp:"+ str(self.BOSS.hp) +",\ mpt"+ str(self.BOSS.mp) +'\n') return outfile def _close(self): pass def _seed(self, seed=None): pass def _get_reward(self): # 報酬を返す。報酬の与え方が難しいが、ここでは # - HEROが死んだら (-50 + 与えたダメージ/10) pt # - HEROが生きてたら +0pt # - ↑+魔王を倒したら +(50 - かかったターン数) * 5) pt # とした if self.HERO.hp <= 0.: return -100. + ( self.BOSS.HP_MAX - self.BOSS.hp )/10 else: if self.BOSS.hp <= 0.: return (50. - self.steps) * 5 else: return 0. def _observe(self): observation = np.array([self.HERO.hp, self.HERO.mp],) return observation def _is_done(self): if ( (self.HERO.hp <= 0.) | (self.BOSS.hp <= 0.) ): return True else: return False |
次回、エージェント(AI)の設定をして、実際に強化学習していきたいと思います。
OpenAI Gym/Baselines 深層学習・強化学習 人工知能プログラミング 実践入門 [ 布留川 英一 ] 価格:3,520円 |
コメント