見出し画像

ポーカーAI開発 part1 〜自分と対戦して賢くなるAIを作ってみた〜

こんにちは!ナガメ研究所です。
先日、TwitterにAIと対戦した動画を投稿しました。まだ見てない方は先にこちらをご覧ください。※音がでます
この記事では、強化学習の内容に触れつつ、どういった工夫をしてきたかを書いていきます。

問題となった点

今回、ML-agentsの"self-play"を用いて、AI同士を対戦させて強いAIをつくることを目指しました。その過程で、うまく学習できなかったパターンを上げてみます。

オール・インしかしない

学習がある程度進むと、オール・インしかしないAIができあがりました。ポーカーは運の要素を含んでいるので、ハンドが弱くても勝ってしまうことがあります。普通、試行回数が増えてくるとそれは良い戦略ではなくなるような気もしますが、一度一つの選択肢しかしなくなるとそれ以降他の選択肢を取らないようになってしまう現象が起きました。

ELOレートが下降し続ける

原因は不明ですが、負け続けてしまうことがありました。self-playでは自分自身や、過去の自分と戦い、勝てるように学習が進むはずです。どこかで頭打ちになるのは分かりますが、下がり続ける事はあるのでしょうか?

工夫点

上記課題を解決するために、いくつか初期の設定から変更を行いました。ただ、ちゃんと実験してないのでどれが一番効いたのかは検証できていません。学習1回で半日かかってるので、時間があれば効果検証したいと思います。

入力値について

これまで、数値をそのまま入力していたのを、正規化しました。例えば、スタート時のバンクロール1000、現在500の場合、(500-1000)/1000=-0.5となり、-1~1の値に収まるようにしています。これまで500と大きな値を入力していたのですが、小さい範囲に収めたほうが計算しやすいと何かでみたので試してみました。
同様に、プログラム上は手札も数値で表していたのですが(♡Aは11などの数値に割り振っていた)、これをワンホットベクトルに直しました。ワンホットベクトルとは、トランプ52枚を52個の数値の配列で表し、対応する番目の値を1,他をゼロとする方法です。
自分・相手のバンクロール、ポット、相手の行動、ターンまでのカード、自分のハンドすべてを-1~1やワンホットベクトルにしました。これはかなり学習に影響を与えているようで、順調に学習が進むようになったと思います。

出力について

AIはcheck, call, fold raise, raise値の5つを出力しますが、最初はすべて連続値(-1~1の間の小数点を含む値)で出力させ、最も値の大きい項目を選択するようにしていました。行動できない項目が選択された場合は、次に大きい値の項目を選択するようにしました。
しかし、これも学習が進むに連れて1しか出力しないなど、期待していた出力を得られませんでした。また、学習が進んでも行動できない選択肢を選んでしまうことや、連続値の出力は学習が難しいことから、出力を離散値(0,1,2,3などの整数)に変更し、選択肢をMaskする”WriteDiscreteActionMask”関数を適用しました。
これにより、出力サイズも減り、シンプルになったことでコードもすっきりしました。離散値で一つだけ選ぶようにしているので、どの選択肢と悩んでいるかなどが分かりにくくなりましたが、そのうち値を抽出できないか試してみます。
また、べット(レイズ)のサイズですが、1単位で出力すると大きすぎるため、持ち点を40分割し、40個の離散値から選択するようにしました。

学習環境について

ポーカーの学習環境で設定すべきパラメーターは主に以下の3つです。

  • BBサイズとバンクロール

  • 報酬

今回は、一人200BBにしています。工夫点としては、ゲームスタート時の初期バンクロールをランダムにしています。これは、毎回200BBからスタートするより多様なパターンを経験できるようにするためです。
二人のバンクロールは200BB*2で合計400BBあるので、一人は1BB~399BBの間でランダムに決定し、もう一人が残りのバンクロールを持ってゲームスタートです。
初期バンクロールを毎回ランダムに決定するのは、所感としてはかなり良いように思えます。バンクロールが少ないときや多い場合に、どう行動すればよいか効率よく学習してくれることを狙っています。
報酬は、相手のバンクロールをゼロにすると1,ゼロにされると-1です。また、50ゲームやって勝敗がつかない場合、二人のバンクロールの平均との差を合計で割ることで-1~1の間で正規化し、報酬として与えています。

今後

入力にワンホットベクトルや連続値を混ぜていいのかはよくわかっていません。統一すべきな気もしますが、そこらへんのノウハウがまとまってるサイトとかないかな・・・。
報酬の与え方については、まだ検討の余地があるように思えます。AI同士の試合を見ていると、3ゲームくらいでバンクロールがゼロになってしまっており、上限としている50ゲーム白熱して戦うのは約100万回試合してわずか30回でした。先程Twitterに載せた動画を見てもわかる通り、べットサイズが大きいことで短期決戦となっているようです。
真に強いポーカーAIを作るのなら、これで勝てているならば問題ありません。しかし、もっとfoldしてくれたり駆け引きを楽しむためにも、他の指標を設けて報酬として加えるのが良いような気がします。
なにかアイデアがあれば、ぜひコメントお待ちしております。では。

この記事が気に入ったらサポートをしてみませんか?