ポケモンの最適解を知るため、強化学習を勉強している。
DQN の強化学習において、報酬は「勝敗」や「ポケモンの死亡・討伐」に加えて、「受けた・与えたダメージ」を入れると学習が進みやすいということが分かったので、複数のポケモンで実装した。といっても、最初にやっていたように 6:6 だとまだ学習が安定しなそうなので、とりあえず 2:2 で実験した。AI の対戦相手は、前と変わらず JustAttackPlayer
(ランダムな攻撃出すだけ)にしている。
報酬はこれ。
- 勝利:
+1
- 敗北:
-1
- 討伐:
+0.3
- 死亡:
-0.3
- 与ダメージ:
sigmoid(ダメージ割合) - 0.5
- 受ダメージ:
-1 * (sigmoid(ダメージ割合) - 0.5)
AI と JustAttackPlayer
の手持ちポケモンはこうだ。
- AI
- サンダース
- 10 万ボルト
- にどげり
- ミサイルばり
- のしかかり
- スターミー
- なみのり
- 10 万ボルト
- サイコキネシス
- ふぶき
- サンダース
- 敵
JustAttackPlayer
- サイドン
- じしん
- なみのり
- のしかかり
- いわなだれ
- サンダース
- 10 万ボルト
- にどげり
- ミサイルばり
- のしかかり
- サイドン
JustAttackPlayer
は、攻撃しかしてこないので、 AI の取るべき最適な行動は下記に限定できる。
- スターミーに交代する
- スターミーで「なみのり」でサイドンを撃破
- 敵サンダースに「なみのり」を当てる
- 敵サンダースの「10 万ボルト」を食らって退場
- サンダースを死に出し、同キャラ対決に持ち込む
- 「のしかかり」を撃ちまくる
急所の有無で多少変わってくるが、上記が最も勝率が高いのは自明である。
とりあえず実行した結果
予想に反して、正しく交代してくれなかった。1:1 バトルは正しい行動を学んでいんたので、恐らく「交代」という概念を理解できていないように思える。「交代」そして「場に出ているポケモン」という概念を理解させるには、状態の表現形式を変更する必要があるように見えるので、これを改善することにした。。
現在、「状態」の表現としては、下記をフラットな list
にしている。
- AI が場に出しているポケモンのインデックス
- AI のポケモン 1 の ID
- AI のポケモン 1 の残り HP
- AI のポケモン 1 のわざ 1 の ID
- AI のポケモン 1 のわざ 2 の ID
- AI のポケモン 1 のわざ 3 の ID
- AI のポケモン 1 のわざ 4 の ID
- AI のポケモン 2 の ID
- AI のポケモン 2 の残り HP
- AI のポケモン 2 のわざ 1 の ID
- AI のポケモン 2 のわざ 2 の ID
- AI のポケモン 2 のわざ 3 の ID
- AI のポケモン 2 のわざ 4 の ID
- 敵が場に出しているポケモンのインデックス
- 敵のポケモン 1 の ID
- 敵のポケモン 1 の残り HP
- 敵のポケモン 1 のわざ 1 の ID
- 敵のポケモン 1 のわざ 2 の ID
- 敵のポケモン 1 のわざ 3 の ID
- 敵のポケモン 1 のわざ 4 の ID
- 敵のポケモン 2 の ID
- 敵のポケモン 2 の残り HP
- 敵のポケモン 2 のわざ 1 の ID
- 敵のポケモン 2 のわざ 2 の ID
- 敵のポケモン 2 のわざ 3 の ID
- 敵のポケモン 2 のわざ 4 の ID
このうち、「場に出ているポケモン」の情報は下記だ。
- AI が場に出しているポケモンのインデックス
- 敵が場に出しているポケモンのインデックス
これを廃止し、各ポケモンに「場に出ているかどうか」というフラグを付与するように修正した。修正後の状態表現はこんな感じ。
- AI のポケモン 1 の ID
- AI のポケモン 1 が場に出ているか(出ている=1, 出ていない=0)
- AI のポケモン 1 の残り HP
- AI のポケモン 1 のわざ 1 の ID
- AI のポケモン 1 のわざ 2 の ID
- AI のポケモン 1 のわざ 3 の ID
- AI のポケモン 1 のわざ 4 の ID
- AI のポケモン 2 の ID
- AI のポケモン 2 が場に出ているか(出ている=1, 出ていない=0)
- AI のポケモン 2 の残り HP
- AI のポケモン 2 のわざ 1 の ID
- AI のポケモン 2 のわざ 2 の ID
- AI のポケモン 2 のわざ 3 の ID
- AI のポケモン 2 のわざ 4 の ID
- 敵のポケモン 1 の ID
- 敵のポケモン 1 が場に出ているか(出ている=1, 出ていない=0)
- 敵のポケモン 1 の残り HP
- 敵のポケモン 1 のわざ 1 の ID
- 敵のポケモン 1 のわざ 2 の ID
- 敵のポケモン 1 のわざ 3 の ID
- 敵のポケモン 1 のわざ 4 の ID
- 敵のポケモン 2 の ID
- 敵のポケモン 2 が場に出ているか(出ている=1, 出ていない=0)
- 敵のポケモン 2 の残り HP
- 敵のポケモン 2 のわざ 1 の ID
- 敵のポケモン 2 のわざ 2 の ID
- 敵のポケモン 2 のわざ 3 の ID
- 敵のポケモン 2 のわざ 4 の ID
こうすると、 飛躍的に改善された??。100,000 エピソード程度で学習させたところ、学習結果を使うと、 JustAttackPlayer
に対して 勝率 90% を超えており、各行動もまともだった。具体的な評価値は下記の通り。
ターン 0
- AI: サンダース
- 敵: サイドン
行動 | 評価値 |
---|---|
スターミーに交代 | 0.94966813 |
10 万ボルト | 0.51513492 |
のしかかり | 0.40763852 |
にどげり | 0.47395807 |
ミサイルばり | 0.30495806 |
スターミーに交代を選んでいるので、正しい。
ターン 1
- AI: スターミー
- 敵: サイドン
行動 | 評価値 |
---|---|
サンダースに交代 | 0.32844415 |
なみのり | 1.15809028 |
ふぶき | 0.8655689 |
サイコキネシス | 0.69057423 |
10 万ボルト | 0.80103038 |
「なみのり」を選んでいるので、正しい。 「10 万ボルト」が「サイコキネシス」より高いのが気になるが、エピソード数が少なかったからかもしれない。
エピソード数を増やしてみた
喜んだ矢先だったが、検証のためエピソード数を 300,000 に増やしてみたところ、逆に悪化してしまった。スターミーがサイドンに対して「ふぶき」を打つなど。局所最適解にはまってしまったのだろうか?
試しに 1,000,000 エピソードで試したところ、悪いままだった。恐らく、先程良い結果になったのはエピソード数とランダムが重なった偶然かもしれない。
次回
やはり「ポケモンの交代」の表現方法が悪いのだろうか?ここを突破しないと、次に進めないので、どうしたものか… 一旦、下記を試したいと考えている。
- 1:1 で学習
- AI をスターミーに固定
- 敵
JustAttackPlayer
は、 100,000 エピソードずつ違うポケモンを選出 - 最後、ランダムなポケモンを相手に勝てるかを実験
最後のランダムなポケモンに対して最適な行動が取れれば、ID でどのポケモンを相手が出しているか理解できていることになる。