思考の本棚

機械学習のことや読んだ本の感想を整理するところ

シミュレーションコンペで強化学習を始める時のTips

はじめに

この記事はKaggle Advent Calender 2021の17日目の記事です。この記事はKaggleで開催されるシミュレーションコンペに、強化学習アプローチで取り組もうと思った時に役立つ情報をまとめたものです。強化学習に初めて取り組む方を基本的には想定しており内容もそちらに合わせています。

初めに自己紹介させていただくと、私はkutoというアカウントでKaggleに取り組んでいて今年Kaggle Masterになることができました。過去に2つのシミュレーションコンペに参加し強化学習アプローチで取り組みました。過去のコンペ参加の振り返りは以下に書いてますので興味があればご覧ください。 kutohonn.hatenablog.com kutohonn.hatenablog.com

これらの経験を通して得た強化学習の知見を共有できればと思います。なおここでいうシミュレーションコンペとはゲームAIコンペを想定しており、ヒューリスティック・最適化要素の強いコンペ(ex;サンタコンペ)はここでは想定していないことをご了承ください。またこの記事では強化学習アルゴリズムの説明などはおこないません。

目次

一般的なコンペとの違い

評価方法

ここが通常の大きく異なる点だと思います。一般的なコンペはコンペごとに評価指標があり、PublicデータとPrivateデータに対する推論結果をその評価指標で評価することでスコアが算出されます。シミュレーションコンペの場合はコンペごとの評価指標はありません。代わりに他の参加者が提出したsubmissionとの対戦結果から評価されます。対戦相手は自分と同等のスコア帯の人とランダムに当たるようになっています。ただし提出してすぐは自分のsubmissionがどれくらいのスコア帯かというのが分かりません。そこでKaggleでは、序盤は対戦相手のスコア帯の幅を大きくとってたくさん対戦させ、徐々に対戦相手のスコア帯の幅を小さく減衰させることで適切なスコアに収束させる仕組みをとっています。 これは妥当な評価方法であるとは思いますが、一方で序盤の対戦結果のスコアへの影響が大きく、同じsubmissionでもスコアが+-50くらい変動することもあるのでそこには注意が必要です。

submission形式

シミュレーションコンペではagentという関数を持った.pyファイルをsubmissionすることでスコアが評価されます。この提出形式はコンペによって仕様が異なりますがコンペごとにテンプレートが共有されているのでそちらを参考にすれば良いと思います。

# agent.py

def agent(observation, configuration):
    # observation(ゲームの状態)からaction(とる行動)を算出する処理(ex;モデルの推論)
    return action

一例として直近で行われていたLuxAIコンペでは独自の処理を上記のようにagent.pyのagent関数内に記述し、
①ホストが用意したそのほかのスクリプト
②agent.py
③(使う場合は)学習済みモデル
を圧縮ファイルとして提出するという方式でした。

計算資源が必要(強化学習の文脈)

シミュレーションコンペに強化学習で取り組もうと思った時にハードルとなるのがこの点だと思います。 強化学習機械学習と比べると圧倒的に学習効率が悪いです。機械学習だと通常数時間で学習が終わるのでそれだけ試行錯誤のサイクルを早く回せますが、強化学習の場合は学習効率が悪いので、CPUをたくさん用意して並列に対戦を行い学習させるというのがスタンダードになっており、それでも学習に数日というのがザラにあります。そのため試行錯誤を増やすためには計算資源(特にCPU数)が必要となります。 参考までに今年開催されたHungry Geeseコンペで1stだったチームは、1GPUと64CPUで3週間+1GPUと288CPUで4日学習させていたようです。 このように聞くと計算資源のない人が強化学習で勝つのは難しいのではと思われるかもしれません。ただ先日終了したLuxAI Challengeというコンペで1stだったチームは2GPU+8CPUという強化学習では決して十分とは言えない計算資源で素晴らしい成果を残していることは希望になるのではないかと思います。以降の記事でも計算資源が少ない状態で戦う方法を説明しようと思います。

基本的な強化学習の概要

ここでは用語の説明も兼ねて強化学習の基本的な概要について多くの方がイメージしやすいサッカーゲームを例にして説明したいと思います。

環境(Environment)

環境とはゲームルールなども含むゲームエンジンのようなもので、 この環境から現在のゲーム状態を受け取って後述するAgentを動かし対戦したり学習させたりします。

エージェント(Agent)

プレイヤーが操作する対象のことです。サッカーゲームではアクティブプレイヤーがこれに該当します。

状態(State)

選手の位置や向き、ボールの位置、速度などのゲームの状態を表すもので、環境から出力されます。 状態の形式は画像であったりベクトルであったりと様々です。この状態をAgentに入力として渡します。ちなみに強化学習ではこの状態の価値を計算することがあります。状態の価値とは現在のゲーム状態がプレイヤーにとってどの程度有利かあるいは不利かを表すものと思ってください。この状態の価値を強化学習では状態価値(State Value)あるいは単に価値(Value)といったりします。

行動(Action)

行動はAgentへの操作のことで右に走る、パスを出すなどが行動に当たります。 強化学習ではこの行動を学習・推論することになります。 状態を受け取ったAgentは推論により行動を出力し、行動を環境に返すとゲーム状態が遷移して新しい状態が環境から出力されるというサイクルにより対戦が行われます。ちなみにある状態のおける行動確率を方策(Policy)といったりします。

報酬(Reward)

機械学習でいう目的関数に該当するもので、最大化したいものを自分で設定します。 報酬として考えられる例を以下に示します。

報酬 説明
勝敗 勝ったら+1, 負けたら-1
得点 1点入れたら+1, 取られたら-1
ゴールまでの距離 相手ゴールに10m近づくたびに+0.1

報酬に関しては次の項目でもう少し詳しく触れようと思います。   

強化学習に取り組む際のTips

ここでは強化学習に取り組む際に最初にすべきことや工夫の余地がある点をまとめています。

1. 過去コンペの解法チェック

必須です。過去のコンペでは強化学習の他に、模倣学習、モンテカルロ木探索、ルールベース(アルゴリズムベース)の手法などが用いられています。

2. 模倣学習(Imitation Learning)

シミュレーションコンペのアプローチとして模倣学習というものがあります。 名前の通り行動を模倣するように学習する教師あり学習です。 シミュレーションコンペでは参加者が提出したAgentの対戦ログがMeta Kaggleに格納されるようになっています。 ここから上位チームの対戦ログを取得し、状態を特徴量、行動を正解ラベルとして教師あり学習をすることで上位チームの方策を模倣することができます。もちろん完全に模倣することはできないのですがこれだけでも良いAgentが作れるケースが多いです。模倣学習にはGBDTやNNが使われるケースがありますがここではNNによる模倣学習を想定しています。 個人的には強化学習に取り組む前に模倣学習を初めに取り組むのが良いのではと考えています。そのように考える理由は以下です。

  • 通常の機械学習と同じなのでとっつきやすい
    模倣学習は通常の教師あり学習と同じなので、シミュレーションコンペが初めての方にも取り組みやすいアプローチだと思います。また強化学習はKaggle Notebookで実施されることは少ないので共有されているコードが少ない一方、模倣学習はnotebookで完結することもあり過去コンペで有益なnotebookが共有されています。そちらを参考にするとスムーズに取り組むことができると思います。

  • 事前学習モデルとして強化学習でも利用可能
    強化学習はそこそこ強いAgentを作るのにもかなりの学習コストを要します。一方模倣学習は数時間の学習でそこそこ強いAgentを作ることができるので、模倣学習で学習したネットワークを強化学習モデルに引き継ぎfine-tuningすることで序盤の学習を省略するというアプローチをとることができます。ただしfine-tuning時にうまくAgentの方策を引き継げず弱体化する場合もあるのでその場合は強化学習のハイパーパラメータを調整する必要があるかもしれません。

  • 試行錯誤しやすい
    強化学習は学習効率が悪いのでモデルがうまく学習できているかの評価にも時間がかかってしまいます。そのため新しい特徴量やモデルのアーキテクチャを選定するための試行錯誤をするのが難しいです。一方模倣学習は数時間で学習を終えることができるため試行錯誤しやすく、模倣学習で有用な特徴量やアーキテクチャ強化学習でも有用であると考えられます。なので模倣学習で試行錯誤をして、強化学習を実施するというフローがとれるのは利点ではないかと思います。

関連するリンク

  • Simulations Episode Scraper Match Downloader
    Meta Kaggleにある参加者の対戦ログから上位チームのデータを取得する方法についてのnotebookです。 模倣学習や後述する対戦結果のEDAを行う際に有用です。

  • Lux AI with Imitation Learning | Kaggle
    Lux AIで共有された模倣学習のnobteookです。非常に綺麗に整理されたコードで模倣学習に取り組む際に参考になると思います。

3. 強化学習フレームワークを使用する

強化学習の実装は結構複雑なので、既存の強化学習フレームワークを使用するのが良いと思います。ただし最新の強化学習アルゴリズムが実装されていない場合もあるのでそれらを利用する際は論文実装を参照する必要がありそうです。 以下で私が知っている範囲で主要なフレームワークを紹介します。

Stable baselines

github.com

  • 知名度の高いフレームワーク
  • TensorFlow versionとPyTorch versionの両方がある
  • 自由度もそれなりにある
  • ログをとるのが簡単でwandbなども対応。
  • 分散強化学習も可能

HandyRL

github.com

PFRL

github.com

Ray

github.com

  • PyTorch, Tensorflowに対応
  • 分散強化学習, Multi-Agent, 模倣学習など多様な機能
  • configファイルを用意して動かす

4. 分散強化学習を行う

Agentを強くするためには対戦数が重要なので分散環境で並列に学習ができる分散強化学習を採用するのが良いと思います。強化学習の有名なアルゴリズムとしてDQN(Deep Q Network)がありますが、通常のDQNは分散学習ができないので分散学習に対応したものを使うことで学習効率を上げることができます。過去の上位解法(Football2nd, HungryGeese1st, LuxAI1st)を見るとIMPALAという分散強化学習手法を利用しているケースをよく見かけるためこちらを初手で考えてみるのも良いと思います。 ただし分散強化学習はCPU数が多いほど効果を発揮するのでKaggle環境やColab環境で行う際は注意が必要です。

5. 報酬設計

報酬設計は強化学習において非常に重要なポイントです。
先ほどのサッカーゲームを例に説明します。 報酬は通常勝敗などのシンプルなものが良いとされています。 ただし勝敗を報酬とするとまだ何も学習していないAgentはゴールまでたどり着くことが難しく、学習初期は報酬を得ることができず学習が進まないことが考えられます。そのような時に補助的な形で「ボールと相手ゴールまでの距離」などを報酬として追加してやることでボールを相手ゴールに近づければ良いことを学習することができます。「ボールと相手ゴールまでの距離」のような報酬はゲームが終了する前に受け取ることができるので即時報酬とも呼ばれます。即時報酬はAgentにとって欲しい行動を誘発するのに重要ですが、Agentの学習が進んでいくとノイズとなってしまう可能性があります。この例で言うと本来はゴールをすることが目的なのに遠い位置からボールをとりあえず相手ゴールの向かった大きく蹴ったり、パスをせずにゴールに向かってずっと走ったりなどです。

こういったことからAgentが弱い段階では補助的に即時報酬を与え、そこそこ強いAgentができたらシンプルな報酬に切り替えるというのが良さそうです。また学習を安定させるために報酬をclipingするケースもあります。reward clipingで調べると関連する情報が見つかると思います。

6. 学習する行動を工夫

Agentが取ることのできる行動は通常ゲーム環境で予め設定されています。ただし戦略上あまり必要のない行動であれば省略したり、行動空間を階層化することで学習効率を高めることができます。例えば過去にFootballコンペの6位解法では17個あるAgentの行動のうち、8方向の移動行動(4方向と斜め4方向)を1つの移動行動として扱い、移動行動が選ばれたら次にどの方向かを決定するという行動空間を階層化させるアプローチをとっていました。逆に行動を細分化するアプローチも考えられます。LuxAIコンペの1位解法ではTransfer Actionという元から与えられている1つの行動を扱う資源の種類(3種類)や方角(4方向)で細分化し3×4=12個の行動として扱うようにしていました。 このようにAgentが学習する行動をどのように扱うかというのも工夫する点となります。

関連するリンク

  • A way to boost your learning
    LuxAIで使われていた移動行動を学習させるための工夫に関するdiscussionです。 移動行動を1つの行動にまとめて学習するというもので模倣学習、強化学習で使えるようです。ゲームAIコンペの場合離散的な移動行動を扱う場合が多いのでこの手法はこれから出てくるシミュレーションコンペでも使えるかもしれません。

7. モデルのアーキテクチャを工夫

ここは基本的に機械学習と同じと考えていただいて構いません。ただし強化学習でpretrained modelや大規模モデルを使うケースは少なくResNetベースのモデルがよく使われている印象です。

8. 入力特徴量を工夫

こちらも基本的に機械学習と同じと考えていただいて構いません。 ゲーム状態を十分に表現できる形式であれば良いと思います。 基本的にはNNで特徴抽出するので凝った特徴量を作る必要はないと思いますが、過去コンペでは特徴量エンジニアリングにより学習効率をあげてスコアが伸びた事例もあるようです。 また強化学習にはstackといって過去の状態を現在の状態に重ねてそれをモデルに入力する手法も存在しています。(DQNの論文とかに使われています。)

9. ハイパーパラメータのチューニング

強化学習アルゴリズムのチューニングが必要なケースが多いです。上位チームはモデルの挙動を考え、適切なパラメータになるように実験してチューニングしている印象です。とはいえパラメータのチューニングは強化学習アルゴリズムの知識が必要となるため、初心者がいきなりここに取り組むのは難しいと思います。なのでデフォルト値でとりあえずは試してみて、どうしても学習がうまくいっていない様子であればチューニングするというのが1つの手だと思います。

関連するリンク

強化学習アルゴリズムの一つであるPPO(Proximal Policy Optimization)のハイパーパラメータをチューニングする際のエッセンスがまとめられた記事です。

10. 対戦回数を増やす

強化学習は対戦型ゲームAIの場合対戦を行うことで良い方策をAgentが学んでいきます。強化学習は学習のパラメータが正しく設定されている場合は対戦を多く積み重ねることがAgentの性能向上に直結します。 対戦回数を増やすには以下のような方法があります。

  • 対戦時間を長くする
  • 計算資源を用意し分散環境で並列に対戦させる
  • 対戦相手の推論を高速化させる
  • 検証用の対戦の頻度・回数を減らす

1つ目2つ目はそのままの通りです。
3つ目は対戦相手の推論速度が強化学習の速度のボトルネックになるケースがあるので、そのような時はjitやonnxruntimeを使用して推論を高速化させることで時間当たりの対戦回数を増やすことができます。
4つ目については強化学習の場合、学習のための対戦とは別に現在のモデルがどの程度育ったかを評価するために評価用の環境で特定の対戦相手と戦わせます。(機械学習で言うところのvalidationに該当)この対戦により勝率などをチェックして学習がうまくいっているかなどをチェックするのですがこの対戦自体は学習には利用されないのでこの頻度を少なくし、1回当たりの対戦回数を減らすことで学習にリソースを割くというものです。ただし評価のための対戦も重要なのでここは自分の状況を見てということになりそうです。

11. 対戦相手の調整

強化学習では対戦相手を誰にするかも重要です。 単一のAgentを対戦相手として学習するとその相手にだけ過学習するため複数の多様なAgentを用意する必要があります。 以下のような対戦相手を用意して複数の敵と対戦することで汎用的に強いAgentを作ることができるようになります。

  • 公開notebookのAgent
  • ゲームエンジンに用意されているAgent(ない場合もある)
  • 自分と同じAgent(自己対戦, self-playと呼ばれる)
  • 過去の自分のAgent

self-playは過去コンペの上位解法でもよく使われており、同じレベル帯の相手と対戦でき、現状の自分より強くなるポテンシャルを持っているので 有用な場合が多いです。ただしself-playの場合、自分と敵が同じ戦略のため方策の更新がサイクルしてしまい学習が進まないケースもあるようです。その場合はハイパーパラメータや学習方法を見直す必要もありそうです。

12. ログをとる

強化学習機械学習と比べて学習が不安定なため複数の評価指標をモニタリングすると改善策が取りやすいです。 一番わかりやすい指標として対戦時の報酬や勝率がありこれらをモニタリングすることでAgentの学習が順調に進んでいるかを確認することができます。またそのほかにも学習時のLossや状態価値などモニタリングすべき指標は複数存在しており、それらを観察することで現状の学習方法の問題点などを見つけることにつながります。これらの指標はフレームワークであらかじめ記録されるものもあればそうでないものもあるので適宜自身で実装する必要があります。
(指標のモニタリングの一例) f:id:kutohonn:20211216210953p:plain

13. 対戦結果のEDA&対戦の様子を見る

これは強化学習に限った話ではなくシミュレーションコンペで重要な点だと思います。 他のコンペと違い、シミュレーションコンペでは提出後に対戦というアウトプットがあるのでその結果を注意深く観察することで、上位チームがどういう戦略をとっているかを理解することにつながると思います。 対戦の様子はLBの右側にある再生ボタンを押すと対象チームのBest ScoreのAgentの過去の対戦結果を動画で見ることができます。 f:id:kutohonn:20211215235901p:plain

またそれ以外の対戦結果はKaggle DatasetのMeta Kaggleに全参加者の対戦ログがjson形式で格納されているのでそのデータを取得しEDAをすることで上位チームや自分のAgentの分析が可能です。

14. モンテカルロ木探索(MCTS)

モンテカルロ木探索とは効率的にゲーム状態を探索して有効な手を決定する探索アルゴリズムです。 Alpha Zeroで使われていることで有名でKaggleでもHungry GeeseやLuxAIの上位解法で利用されています。モンテカルロ木探索は模倣学習や強化学習の出力と組み合わせて使用されるケースが多い印象です。

関連するリンク
- 10th Place Solution
Hungry Geese10位のsazumaさんのnotebookです。模倣学習とモンテカルロ木探索(MCTS)によるアプローチがとても綺麗なコードでまとまっている貴重なnotebookだと思います。

おわりに

Kaggleで強化学習に取り組む際に役立つ情報をまとめてみました。私は2度シミュレーションコンペに参加していますがシミュレーションコンペ、そして強化学習はとても面白いです! なかなかとっつきづらい領域ではありますがこの記事がシミュレーションコンペや強化学習に関心を持つきっかけになると嬉しいです。 読んでいただきありがとうございました。