ポケモンの強化学習AI(7)

データの表現を工夫したけど意味ないっぽい?

ポケモンの最適解を知るため、強化学習を勉強している。

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 でどのポケモンを相手が出しているか理解できていることになる。

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy