Amazon Web Services ブログ

Amazon SageMaker の強化学習を使用して AI で駆動する Battlesnake を構築する

Battlesnake は、従来のスネークゲームを基礎にした AI コンペティションで、複数の AI を搭載したスネークが生き残りをかけて競います。Battlesnake は、あらゆるレベルの開発者のコミュニティを魅了しています。何百ものスネークが競い合い、オンラインの Battlesnake グローバルアリーナでランキング上位に入ることを目指します。Battlesnake はまた、1,000 人以上の開発者と非開発者が参加するオフラインイベントを開催しており、その様子は Twitch でストリーミング配信されています。開発者のチームは、コンペティションのためにスネークを作り、新しい技術スキルを学び、協力することを学び、楽しんでいます。チームは、最先端の深層強化学習 (RL) アルゴリズムから独自のヒューリスティックベースの戦略まで、さまざまな戦略を駆使してスネークを構築できます。

この記事では、Amazon SageMaker を使用して RL ベースのスネークを構築する方法を説明します。

従来のスネークゲームでは、スネークを上下左右に移動するようにコントロールします。スネークが壁、別のスネーク、またはスネーク自身の体にぶつかると、スネークは死にます。スネークが食物を食べると、体が長くなります。従来のスネークゲームと比べると、Battlesnake にはいくつか違う点があります。まず、スネークを制御するのは、プログラムです。2 頭のスネークが正面衝突すると、小さいスネークが死にます。また、飢えメカニズムがあります。100 手動いて食物を食べられなかったスネークは死にます。そのため、生存率を最大にする、他のスネークを積極的に攻撃する、または他のスネークを避けようとすることはすべて、プレイヤーが採用している実践的な戦略です。スネークはプログラムされたウェブサーバーとして実装され、Battlesnake エンジンはゲームの現在の状態を考慮して次の動きをクエリします。詳細については、Battlesnake ウェブサイトの「開始方法」を参照してください。

この記事では、SageMaker Battlesnake スターターパックを使用して、スネークの構築に必要な時間と労力を節約する方法を示します。SageMaker Battlesnake スターターパックは、RL でトレーニングされた AI 搭載のスネークを提供します。スターターパックは、独自の RL ポリシーと、RL アルゴリズムの上にカスタムヒューリスティックベースのルールを構築するツールをトレーニングするための環境も提供します。さらに、AI ボットをデプロイおよびホストするウェブインフラストラクチャが自動的に生成されます。SageMaker Battlesnake スターターパックでは、周囲のインフラストラクチャを気にすることなく、AI の開発に集中できます。

Amazon SageMaker Battlesnake スターターパックは、AWS CloudFormationquick-create リンクを使用します。これにより、GitHub repo から AWS マネジメントコンソールへ 1 クリックデプロイを行えます。スタックを作成すると、次の 3 つのレイヤーと開発環境がデプロイされます。

  • 最初のレイヤーは Amazon API Gateway です。これは、snake HTTP API を Battlesnake エンジンに公開します
  • 2 番目のレイヤーは、Battlesnake API を RL エージェントの内部表現に転写する AWS Lambda 関数です
  • 3 番目のレイヤーは、スネークをホストする Amazon SageMaker エンドポイントです
  • 開発環境は、Amazon SageMaker ノートブックインスタンス内で実行される Jupyter ノートブックで構成されています

次の図は、ランタイム AI インフラストラクチャを示しています。

SageMaker Battlesnake スターターパックは次のことを行います。

  • 開発環境と AI を搭載したスネークを含むフレームワークをデプロイできます。
  • 新しいヒューリスティックベースのルールを変更および評価して、スネークの行動を変更するツールを提供します
  • カスタム RL エージェントを再トレーニングおよび最適化するためのトレーニングスクリプトが含まれています

この記事を最後までお読みいただけると、RL の基本と RL フレームワークで Battlesnake をモデル化する方法を理解し、オンライングローバルアリーナで他のスネークと競合できるスネークを持てるようになっていることでしょう。

Battlesnake で強化学習

このセクションでは、強化学習の基本と、SageMaker Battlesnake スターターパックが RL フレームワークの Battlesnake 環境をどのようにモデル化するかをレビューします。

強化学習の概要

強化学習は、逐次的な意思決定問題に対する戦略を開発します。事前に指定された報酬シグナルが与えられると、RL エージェントは環境と対話します。その目標は、受け取った状態に基づいてアクションを実行し、予想される累積報酬を最大化することです。アクションを実行する戦略は、ポリシー (π(a|s)) と呼ばれます。開始点が t=0 で、(スネークが死ぬ) 終了点が t=T であると仮定します。各ゲームでは、状態 (s t)、アクション (a t)、報酬 (r t)、および次の状態 (st + 1) のリストを含むエピソードを作成します。したがって、累積報酬は次の式で表すことができます。

この方程式では、γ は将来の報酬の割引係数です。

RL の概念と数学的定式化の詳細については、「深層強化学習による財務上の意思決定の自動化」を参照してください。

Battlesnake 環境を理解する

Battlesnake エージェントを構築するには、複数のエージェントに対応するために、記述された RL フレームワークの拡張が必要です。次の図は、Battlesnake エージェントをトレーニングするためのマルチエージェント RL 問題を示しています。

SageMaker Battlesnake スターターパックでは、オープンソースの OpenAI Gym インターフェイスを使用して環境をカスタマイズできます。snake_gym.py というカスタムファイルは LocalEnv/battlesnake_gym/battlesnake_gym / フォルダにあり、前述のすべてのエンティティを指定します。次のコードは、状態空間 (map_size、スネークの数と位置、および食物の位置によって定義され、observation_space として示される) とアクション空間 (上、下、左、右) を定義します。

# Custom environment file in Open AI Gym

class BattlesnakeGym(gym.Env):
    def __init__(self, observation_type="flat-51s", map_size=(15, 15),
                 number_of_snakes=4,
                 snake_spawn_locations=[], food_spawn_locations=[],
                 verbose=False, initial_game_state=None, rewards=SimpleRewards()):
        
        # Action space
        self.action_space = MultiAgentActionSpace(
            [spaces.Discrete(4) for _ in range(number_of_snakes)])
        
        # Observation space
        self.observation_type = observation_type
        if "flat" in self.observation_type:
            self.observation_space = spaces.Box(low=0, high=2,
                                                shape=(self.map_size[0],
                                                       self.map_size[1],
                                                       self.number_of_snakes+1),
                                                dtype=np.uint8)
        elif "bordered" in self.observation_type:
            self.observation_space = spaces.Box(low=0, high=2,
                                                shape=(self.map_size[0]+2,
                                                       self.map_size[1]+2,
                                                       self.number_of_snakes+1),
                                                dtype=np.uint8)
        
        (...)

Battlesnake ジムのデフォルトの状態表示では、マルチチャネル画像を使用します。最初のチャネルは食物の位置を表し、2 番目のチャンネルはエージェントが制御しているスネークの位置を表し、3 番目のチャンネルは他のスネークの位置を表します。環境の表現は LocalEnv/battlesnake_gym/battlesnake_gym/snake.py で定義されています。次の画像をご覧ください。

step() メソッドは、各スネークによって実行されるアクションを行い、状態遷移を実行することで、結果として新しい状態と報酬を取得します。次のコードで状態遷移を定義できます。

def step(self, actions, episodes=None):
    # setup reward dict
    reward = {}
    snake_info = {}

    # Reduce health and move
    for i, snake in enumerate(self.snakes.get_snakes()):
        reward[i] = 0
        if not snake.is_alive():
            continue

        # Reduce health by one
        snake.health -= 1
        if snake.health == 0:
            snake.kill_snake()
            reward[i] += self.rewards.get_reward("starved", i, episodes)
            snake_info[i] = "starved"
            continue

        action = actions[i] 
        is_forbidden = snake.move(action)
        if is_forbidden:
            snake.kill_snake()
            reward[i] += self.rewards.get_reward("forbidden_move", i, episodes)
            snake_info[i] = "forbidden move"
      
    # check for food and collision
    (...)
      
    return self._get_observation(), reward, snake_alive_dict, {'current_turn': self.turn_count,
                                                                'snake_health': snakes_health,
                                                                'snake_info': snake_info}

LocalEnv/battlesnake_gym/battlesnake_gym/rewards.py で報酬関数をカスタマイズできます。デフォルトでは、ジムは次の報酬定義をサポートしています。

  • 別のターンを生き延びる ("another_turn")
  • 食物を食べる ("ate_food")
  • ゲームに勝つ ("won")
  • ゲームに負けた ("died")
  • 別のスネークを食べる ("ate_another_snake")
  • 壁にぶつかる ("hit_wall")
  • 別のスネークを襲う ("hit_other_snake")
  • 自分にぶつかる ("hit_self")
  • 別のスネークに食べられる ("was_eaten")
  • 別のスネークに襲われる ("other_snake_hit_body")
  • 北を向いているときに南に移動するなど、禁止された移動を実行する ("forbidden_move")
  • 飢えで死ぬ ("starved")

強化学習アルゴリズム

RL ポリシーを学習するためのアルゴリズムは数多くあります。SageMaker Battlesnake スターターパックは、ディープ Q ラーニング (DQN) と呼ばれる古典的な方法を提供します。Q は品質を表しており、現在の状態 s を考えると、あるアクション a が将来の報酬を得るのにどれだけ良いかを表します。数学的には、Q 値は次の方程式として定義されます。

この方程式では、s’ は次の状態を示します。基本的に、前の方程式で考えられるすべてのアクションと考えられるすべての次の状態を検討し、特定のアクションを実行することで与えられる最大値を取得します。

Q (s’a) はここでも Q (s”,a) に左右されます。したがって、Q 値はすべての将来の状態の Q 値に左右されます。次の方程式を参照してください。

次の式を使用して Q 関数を学習します。

この方程式では、α は学習率です。更新プロセスは Q ラーニングと呼ばれます。これにより、timestep t での現在の Q 値と t+1 での Q 値に基づいて Q 値を更新でき、α は新しく取得した情報が古い情報をどの程度上書きするかを制御します。理論的分析により、α の穏やかな条件下では、無限のランダムアクション選択を想定して、更新が最適ポリシー π* に収束することが証明されています。

実際には、環境にはかなりの数の状態がある可能性があり、すべての Q 値をテーブルに記録することは現実的ではありません。入力は現在の状態の画像であるため、これは Battlesnake にも当てはまります。Q テーブルの保存と更新に必要なメモリ量と時間は、すべての入力画像が異なる可能性があるため、現実的なものではありません。この問題を軽減するために、ニューラルネットワークで Q 値を概算することができます。これにより、ディープ Q ラーニングが可能になります。具体的には、ゲームの状態が入力として提供され、考えられるすべてのアクションの Q 値が出力として提供されます。この記事では、アテンションおよび連結ベースの Q ネットワークを提供します。このネットワークは、そのまま使用することも、カスタムスネークの出発点として使用することもできます。ネットワークは LocalEnv/battlesnake_src/networks/qnetworks.py にあります。

SageMaker Battlesnake スターターパックには、記載されている RL フレームワークでトレーニングされたモデルが含まれています。この記事には次の手順が含まれます。

  1. このトレーニングされたモデルとそれを改善できる開発環境をデプロイする
  2. スネークの行動をカスタマイズするための新しいヒューリスティックベースのルールを評価する
  3. RL アルゴリズムをカスタマイズおよび調整する

ステップ 1: Amazon SageMaker Battlesnake スターターパックをデプロイする

このセクションには、次の手順が含まれています。

  1. Amazon SageMaker Battlesnake スターターパックを起動して、スタータースネークと、スネークをカスタマイズする開発環境をデプロイします。
  2. API Gateway を Battlesnake エンジンにリンクします。これで、スネークは Battlesnake アリーナで競うことができます。

Battlesnake スターターパックをデプロイする

スターターパックをデプロイするには、次の手順を実行します。

  1. GitHub リポジトリで [Deploy environment] に移動します。
  2. 希望するリージョンで [deploy] を選択します。

Battlesnake エンジンは us-west-2 で実行されます。レイテンシーを最小限に抑えるために同じリージョンにデプロイすることもできます。

[deploy] を選択した後、CloudFormation スタック作成プロセスに入るはずです。

  1. [Parameters] で、使用するデフォルトの Amazon EC2 インスタンスタイプを定義できます。

インスタンスタイプ m5.xlarge と m4.xlarge は、Amazon SageMaker の無料利用枠の一部です。ただし、デフォルトでは、新しい AWS アカウントでは使用できません。AWS を初めてご利用いただく場合は、代わりに t2.medium インスタンスを使用できます。このインスタンスは、Battlesnake のユースケースにとって費用効果が高く、十分に強力です。

  1. [Parameters] では、スネークの色、頭部の形状、尻尾の形状も定義できます。

次のような、さまざまな色と形状のスネークの画像が表示されます。

次のスクリーンショットは、選択可能なさまざまなスネークの形状を示しています。

詳細については、Battlesnake ウェブサイトの「スネークのカスタマイズ」を参照してください。

  1. [Capabilities and transforms] セクションで、すべての権限を選択します。
  2. [Create stack] を選択します。

これで、Battlesnake 環境作成ページが表示されます。約 10 分後、ステータス CREATE_COMPLETE が表示されます。

スタックに再度移動する必要がある場合は、AWS CloudFormation コンソールに移動して [BattlesnakeEnvironment] を選択します。

  1. [Outputs] タブで、[CheckSnakeStatus] の横のリンクを選択します。

スネーク作成のステータスを示すウェブページにリダイレクトされるはずです。次の行は、スネークが作成されているときのウェブページの例を示しています。

スネークのステータス: 準備ができていません

Sagemaker エンドポイントステータス: 作成中

AWS マネジメントコンソールの Amazon SageMaker サービスページにアクセスして、詳細情報を確認できます。

約 15 分後、snake status:ready が表示されます。これは、Amazon SageMaker エンドポイントの作成が完了したことを示しています。これで、Battlesnake エンジンに応答できるウェブサーバーがデプロイされました。

スネークを作成して Battlesnake エンジンにリンクするには、次の手順を実行します。

  1. Battlesnake ウェブサイトでスネークを作成します。
  2. Name には、希望する名前を入力します。
  3. URL には、SnakeAPI の URL を入力します。

この URL は、CloudFormation スタックの Outputs タブで利用できます。

  1. オプションで、説明とタグを入力します。
  2. オプションで、他の人が自分のスネークをゲームに追加できるかどうかを選択します。
  3. [Save] を選択します。

これで、既存のスネークに対してスネークをテストできます。次の動画は Battlesnake のゲームを示しています。

スネークの My SageMaker Snake は遅いけれども安定しており、最終的には勝ちます。詳細については、Battlesnake のウェブサイトで「このゲームの詳細」を参照してください。

次のスクリーンキャストは、このステップの完全な手順を示しています。動画は、待ち時間をスキップするように編集されています。

開発環境のナビゲート

動作するスネークがいるので、開発環境の探索を開始できます。CloudFormation スタックの [Outputs] タブで、次のキーを確認できます。

  • SourceEditionInNotebook – Jupyter ノートブックの開発環境のソースディレクトリへのリンク。
  • HeuristicsDevEnvironment – ヒューリスティック開発ノートブックへのリンク。詳細はこの記事のステップ 2 にあります。
  • ModelTrainingEnvironment – RL トレーニングノートブックへのリンク。詳細はこの記事のステップ 3 にあります。

スターターパック環境

スターターパックは、ローカル開発ディレクトリを作成します。SourceEditionInNotebook を開いて [battlesnake/LocalEnv] に移動するとアクセスできます。

LocalEnv では、次のファイルを変更して、SageMaker スターターパックトレーニング、ヒューリスティック開発、および評価をカスタマイズできます。

  • battlesnake_gym/battlesnake_gym / – このディレクトリ内のファイルは、OpenAI Gym に基づいて Battlesnake RL 環境を定義します。このディレクトリは、Amazon SageMaker トレーニングジョブにコピーされます。ディレクトリには、次のファイルが含まれています。

    • food.py は、食物の産卵メカニズムと食物表現を処理します。
    • rewards.py は報酬機能を定義します。
    • snake.py は、スネークの動きのメカニズム、表現、および死の状態を定義します。
    • snake_gym.py は、スネーク、食物、環境間の相互作用を定義します。RL エージェントもこのファイルと対話します。
  • battlesnake_inference/ – このディレクトリ内のファイルは、モデルの推論に使用される Amazon SageMaker エンドポイントを定義します。次のファイルが含まれます。

    • battlesnake_heuristics.py は、RL エージェントの決定をオーバーライドできるユーザー定義のカスタムルールを定義します。
    • predict.py は、Amazon SageMaker エンドポイントへのエントリポイントです。ネットワークのアーティファクトをロードし、ネットワークから決定を取得し、ヒューリスティックモジュールをアクティブ化します。
  • battlesnake_src/ – このディレクトリ内のファイルは、RL トレーニングジョブを定義します。このディレクトリは、Amazon SageMaker トレーニングジョブにコピーされます。ディレクトリには、次のファイルが含まれています。

    • train.py は、トレーニングジョブへのエントリポイントです。エージェントと環境のハイパーパラメータを定義します。また、トレーニングループを開始します。
    • dqn_run.py は、ディープ Q ラーニングトレーニングループを定義します。
    • networks/agent.py は RL エージェントを定義します。エージェントは、Q ネットワークと環境の間の対話を実行します (アクションを取得し、学習するため)。
    • networks/qnetworks.py は、RL エージェントが使用するニューラルネットワーク (Q ネットワーク) を定義します。

ステップ 2: スネークの行動をカスタマイズする

このセクションでは、スネークの基本ルールとして役立つヒューリスティックを記述する方法を示します。これらの基本ルールは、ディープラーニングモデルが行う特定の有害な決定を無効にします。たとえば、次のスクリーンショットは 2 つのスネークを示しています。ユーザーのスネーク (短い方) が 1 つの決定により特定の死 (下ると長いスネークを襲う) につながる状況にある場合、ヒューリスティックベースのルールは、ユーザーのスネークが下るのではなく、確実に上がるようにします。

他の例には、特定の動きの決定が壁とぶつかることになるかどうか、またはスネークがより短いスネークを捕食できるかどうかを決定するルールが含まれます。

ヒューリスティックベースのルールは、Amazon SageMaker エンドポイント内で呼び出されます。エンドポイントは、アクションのためにディープラーニングモデルにクエリを実行します。ディープラーニングモデルのアクションと環境の状態は、オーバーライドアクションのためにヒューリスティックコードに送られます。

ヒューリスティックの開発

ヒューリスティックを開発するには、ヒューリスティック開発ノートブック (HeuristicsDevEnvironment で定義) を開きます。このノートブックは、モデルを (ヒューリスティックを使用して) シミュレートし、スネークを段階的に視覚化し、新しいヒューリスティックをデプロイします。

ヒューリスティックコードのテンプレートは、LocalEnv/battlesnake_inference/battlesnake_heuristics.py にあります。これは、メインの run 関数を持つクラスで構成されています。次のコードを参照してください。

import numpy as np
import random

class MyBattlesnakeHeuristics:
    '''
    The BattlesnakeHeuristics class allows you to define handcrafted rules of the snake.
    '''
    FOOD_INDEX = 0
    def __init__(self):
        pass
    
    def go_to_food_if_close(self, state, json):
        # Example heuristic to move towards food if it's close to you.

        # Get the position of the snake head
        your_snake_body = json["you"]["body"]
        i, j = your_snake_body[0]["y"], your_snake_body[0]["x"]
        
        # Set food_direction towards food
        food = state[:, :, self.FOOD_INDEX]
        
        # Note that there is a -1 border around state so i = i + 1, j = j + 1
        if -1 in state:
            i, j = i+1, j+1
        
        food_direction = None
        if food[i-1, j] == 1:
            food_direction = 0 # up
        if food[i+1, j] == 1:
            food_direction = 1 # down
        if food[i, j-1] == 1:
            food_direction = 2 # left
        if food[i, j+1] == 1:
            food_direction = 3 # right
        return food_direction
    
    def run(self, state, snake_id, turn_count, health, json, action):
        '''
        The main function of the heuristics.
        
        Parameters:
        -----------
        `state`: np.array of size (map_size[0]+2, map_size[1]+2, 1+number_of_snakes)
        Provides the current observation of the gym.
        Your target snake is state[:, :, snake_id+1]
    
        `snake_id`: int
        Indicates the id where id \in [0...number_of_snakes]
    
        `turn_count`: int
        Indicates the number of elapsed turns
    
        `health`: dict
        Indicates the health of all snakes in the form of {int: snake_id: int:health}
        
        `json`: dict
        Provides the same information as above, in the same format as the battlesnake engine.
        
        `action`: np.array of size 4
        The qvalues of the actions calculated.The 4 values correspond to [up, down, left, right]
        '''
        log_string = ""
        # The default `best_action` to take is the one that provides has the largest Q value.
        # If you think of something else, you can edit how `best_action` is calculated
        best_action = int(np.argmax(action))
                
        # Example heuristics to eat food that you are close to.
        if health[snake_id] < 30:
            food_direction = self.go_to_food_if_close(state, json)
            if food_direction:
                best_action = food_direction
                log_string = "Went to food if close."
                
        # TO DO, add your own heuristics
        
        assert best_action in [0, 1, 2, 3], "{} is not a valid action.".format(best_action)
        return best_action, log_string

ただし、独自のヒューリスティックを書き始める前に、ステップ 2 の残りを読んでください。

run 関数は、環境の表現を次の引数として受け取ります。

  • state – 環境を表すことができる画像形式
  • json – 環境も表すことができる辞書形式
  • snake_id – スネークの ID を示す整数
  • turn_count – 現在のターン数を示す整数
  • health – 各スネークの健康状態を表す辞書
  • action – 4 つの潜在的なアクション (上、下、左、右) を表す Q 値を示す (サイズ 4 の) numpy 配列。アクションは、ニューラルネットワークの出力です。

前述のコードでは、単純なヒューリスティックの例 go_to_food_if_close を見ることができます。スネークの体力が 30 未満で、スネークの横に食物がある場合、スネークは食物に向かって移動します。このルールの目的は、あなたのスネークが飢えて死ぬ可能性を減らすことです。

独自のヒューリスティックを作成するには、環境の各表現を使用する利点と欠点を理解する必要があります。たとえば、さまざまな座標間で可能な動きや距離を調べる場合 (スネークが壁に隣接しているかどうかを判断する場合など)、画像表現は適切です。ただし、画像表現ではスネークの体の順序は失われます。辞書表現により、各スネークの頭と尻尾に簡単にアクセスできます。ヒューリスティックの例は、各表現方法の利点を示しています。

スネークの頭部は、json 引数 (i, j = your_snake_body[0]["y"], your_snake_body[0]["x"]) から取得しました。逆に、画像表現で頭部の座標を取得する場合は、o (m*n) アルゴリズムを使用して画像を反復処理し、頭部を検索します。

近くの食物に向かう動きの方向は、画像表現から得られます (if food[i-1, j] == 1: ...)。json 引数を使用して食物を検索するには、o(n) アルゴリズムを使用して、可能な方向ごとに食物のリストを反復処理する必要があります。

したがって、json リスト定義と state イメージの使用のバランスを取ることにより、モデルの決定をオーバーライドするヒューリスティックベースのルールを作成できます。

ヒューリスティックのテスト

ヒューリスティックを評価するには、ヒューリスティック開発ノートブックを使用できます。このノートブックは、ヒューリスティックを使用してモデルをシミュレートし、すべてのイベントを段階的に再生します。まず、ノートブックの OpenAI Gym の定義セクションで環境の初期条件を定義します。初期条件を定義するには、USE_INITIAL_STATETrue に設定し、Battlesnake API に基づいて食物とスネークの座標を指定します。こちらにinitial_state を定義する簡単な方法があります。次のコードを参照してください。

USE_INITIAL_STATE = False

# Sample initial state for the situation simulator
initial_state = {
    "turn": 4,
    "board": {
                "height": 11,
                "width": 11,
                "food": [{"x": 1, "y": 3}],
                "snakes": [{
                                "health": 90,
                                "body": [{"x": 8, "y": 5}],
                           },
                           {
                                "health": 90,
                                "body": [{"x": 1, "y": 6}],
                           },
                           {
                                "health": 90,
                                "body": [{"x": 3, "y": 3}],
                            },
                            {
                                "health": 90,
                                "body": [{"x": 6, "y": 4}],
                            },
                            ]
            }
}

if USE_INITIAL_STATE == False:
    initial_state = None
    
map_size = (11, 11)
number_of_snakes = 4
env = BattlesnakeGym(map_size=map_size, number_of_snakes=number_of_snakes, observation_type="bordered-51s",
                     initial_game_state=initial_state)

ノートブックを処理すると、トレーニングされたニューラルネットワークが読み込まれ、各スネークの動作がシミュレートされます。シミュレーションの再生セクションでセルを実行した後、ステップバイステップのビジュアライザーを見ることができます。ビジュアライザーの次のスクリーンキャストは、各ステップを段階的に繰り返し表示してから、自動的に再生します。

 

視覚化プロセス中に、スネークが特定の状況を処理できないことがわかった場合、get_env_json() を含む次のセルを実行できます。これにより、環境の現在の状態を表す辞書が出力されます。辞書を OpenAI Gym の定義セクションの initial_state に直接コピーし、特定の状況での問題に対処するための特定のヒューリスティックを記述できます。

ヒューリスティックのデプロイ

ヒューリスティックを終了したら、新しいヒューリスティックを使用して Amazon SageMaker エンドポイントを作成できます。Amazon SageMaker セッションを定義し、アップロードしていないトレーニング済みのモデルのアーティファクトがある場合は、「モデルを再トレーニングした場合に実行」というタイトルのセルのみを実行します (詳細については、この記事のステップ 3 を参照してください)。ノートブックを続行して、Amazon SageMaker エンドポイントを更新します。

新しい Amazon SageMaker エンドポイントのデプロイには最大 10〜15 分かかり、Battlesnake エンジンでスネークを更新する必要はありません。

ステップ 3: 強化学習トレーニング環境のカスタマイズ

このセクションでは、Battlesnake のディープ RL をトレーニングし、ハイパーパラメータ最適化 (HPO) を実行して最適なモデルを見つけ、更新されたモデルを Amazon SageMaker エンドポイントにデプロイする方法を説明します。

モデルのトレーニング

このステップでは、SagemakerModelTraining ノートブック (ModelTrainingEnvironment で定義) を使用します。ノートブックの次の 2 つのパラメータを定義できます。

  • run_hpo フラグは、単一のトレーニングジョブを実行すべきか HPO を実行すべきかを決定します。
  • map_size パラメータは、トレーニングする環境のマップのサイズを決定します。現在のニューラルネットワークは、単一のマップサイズに制限されています。

次のコードを参照してください。

run_hpo = False
map_size = (15, 15)

ジョブのハイパーパラメーターを定義」セルでトレーニングするハイパーパラメータを定義できます。各パラメータの詳細については、GitHub リポジトリをご覧ください。次のコードを参照してください。

map_size_string = "[{}, {}]".format(map_size[0], map_size[1])
static_hyperparameters = {
    'qnetwork_type': "attention",
    'seed': 111,
    'number_of_snakes': 4,
    'episodes': 10000,
    'print_score_steps': 10,
    'activation_type': "softrelu",
    'state_type': 'one_versus_all',
    'sequence_length': 2,
    'repeat_size': 3,
    'kernel_size': 3,
    'starting_channels': 6,
    'map_size': map_size_string,
    'snake_representation': 'bordered-51s',
    'save_model_every': 700,
    'eps_start': 0.99,
    'models_to_save': 'local'
}

ここでモデルをトレーニング」セルに MXNet 推定関数を作成して、トレーニングジョブを開始できます。インスタンスタイプによっては、このプロセスに数時間かかる場合があります。次のコードを参照してください。

estimator = MXNet(entry_point="train.py",
                  source_dir='battlesnake_src',
                  dependencies=["battlesnake_gym/"],
                  role=role,
                  train_instance_type=train_instance_type,
                  train_instance_count=1,
                  output_path=s3_output_path,
                  framework_version="1.6.0",
                  py_version='py3',
                  base_job_name=job_name_prefix,
                  metric_definitions=metric_definitions,
                  hyperparameters=static_hyperparameters
                 )

estimator.fit()

Amazon SageMaker コンソールの Training Jobs セッションタブで起動したプレフィックス job_name_prefix が付いたトレーニングジョブが表示されます。トレーニングジョブを選択すると、トレーニングの実行に関する詳細情報が表示されます。それには、たとえば Amazon CloudWatch Logs、metric_definitions で定義されたメトリクスのリアルタイムの視覚化、モデル出力およびアーティファクト用の Amazon S3 ロケーションリンクがあります。

モデルの調整

HPO ジョブを実行する場合は、ハイパーパラメータ範囲を定義して繰り返し処理する必要があります。以前に定義した static_hyperparameters でハイパーパラメータ最適化を実行することもできます。次のコードを参照してください。

hyperparameter_ranges = {
    'buffer_size': IntegerParameter(1000, 6000),
    'update_every': IntegerParameter(10, 20),
    'batch_size': IntegerParameter(16, 256),

    'lr_start': ContinuousParameter(1e-5, 1e-3),
    'lr_factor': ContinuousParameter(0.5, 1.0),
    'lr_step': IntegerParameter(5000, 30000),
    
    'tau': ContinuousParameter(1e-4, 1e-3),
    'gamma': ContinuousParameter(0.85, 0.99),
    
    'depth': IntegerParameter(10, 256),
    'depthS': IntegerParameter(10, 256),
}

HPO を実行することを選択した場合でも、単一のトレーニングジョブを実行することを選択した場合でも、モデルアーティファクトは Amazon S3 に保存されます。このノートブックは、トレーニング済みのモデルアーティファクトを Amazon S3 から自動的にダウンロードし、パッケージ化し、処理して、Amazon SageMaker エンドポイントを自動的に更新します。Battlesnake エンジンでスネークを更新する必要はありません。

まとめ

Battlesnake の使命は、あらゆるレベルの開発者が友達と楽しみ、新しいスキルを学び、コミュニティを構築することです。SageMaker Battlesnake スターターパックは、このミッションに基づいて構築され、すべてのレベルの開発者を対象としています。決定ツリーまたは RL に基づいてスネークを構築する場合は、SageMaker Battlesnake スターターパックを使用できます。

この記事では、Battlesnake アリーナにスネークをデプロイして、他のスネークや開発環境と競争し、カスタム設定でモデルを変更およびアップグレードする方法を説明しました。歴史的に、ヒューリスティックベースの決定ツリーで構築されたスネークは、オフラインの Battlesnake コンテストで機械学習ベースのスネークよりも優れていました。最近、RL ベースのスネークがオンライングローバルアリーナのランキングで上位に来る傾向があります。SageMaker Battlesnake スターターパックを試して、今年はハイブリッド RL とヒューリスティックスネークが勝利するかどうかをご自身で確かめてみてください!


著者について

Jonathan Chung は AWS のアプライドサイエンティストです。彼は、ゲームや文書分析などのさまざまなアプリケーションにディープラーニングを適用することに取り組んでいます。彼の趣味は料理と世界中の歴史的な都市を訪れることです。

 

 

 

Xavier Raffin は AWS のソリューションアーキテクトで、お客様がビジネスを変革し、業界をリードするクラウドソリューションを構築するのを支援しています。彼は好奇心に駆られ、公共交通機関、ウェブマッピング、IoT、航空、宇宙といった多くの分野にテクノロジーを応用しています。彼は、OpenStreetMap、Navitia、トランスポート API といった、いくつかの OpenSource プロジェクトと Opendata プロジェクトに貢献しました。

 

 

Anna Luo は AWS のアプライドサイエンティストです。彼女は、サプライチェーンやレコメンダーシステムなど、さまざまな分野で強化学習テクニックを活用しています。彼女の現在の個人的な目標は、スノーボードをマスターすることです。

 

 

Bharathan Balaji は AWS のアプライドサイエンティストで、彼の研究対象は強化学習システムとアプリケーションにあります。彼は Amazon SageMaker RL と AWS DeepRacer の立ち上げに貢献しました。余暇には、バドミントン、クリケット、ボードゲームを楽しんでいます。

 

 

Vishaal Kapoor は、AWS AI のシニアソフトウェア開発マネージャーです。彼は AI のすべてを愛し、SageMaker を使ってディープラーニングソリューションを構築することに取り組んでいます。余暇には、マウンテンバイク、スノーボードを楽しみ、家族との時間を大切にしています。