AWS EC2 で Numerai Compute

3 min読了の目安(約3400字TECH技術記事

この記事は、Numerai Advent Calendar 2020の10日目の記事です。

Numerai Compute とは?

Numerai Compute とは、Numeraiトーナメントの予測提出を自動化する仕組みです。

自分の予測プログラムをDockerイメージにしておけば、日曜日にNumerai ComputeサーバーがWebHookからコンテナを起動してくれます。

Numerai Computeを設定しているモデルには素敵なCOMPUTEバッジが付きます。

Numerai Computeバッジ

Numerai Compute(numerai-cli)の問題点

Numerai Compute(numerai-cli)では、DockerコンテナをAWS ECSのFargateで実行します。
現状、FargateではGPUを使えません。ニューラルネットワークでモデルを作成すると、GPUなしに予測を実行するにはとても時間がかかってしまいます。

というわけで、Numerai ComputeをEC2のGPUインスタンスを使って実行する方法を簡単にご紹介します。

構成

Numerai Compute構成

Numerai Compute WebHook から EC2 を起動

AWSは不慣れなので、参考になる資料をご紹介します。

ざっくり流れを追うと、

  1. IAMを設定
  2. Lambda関数を設定
  3. API Gatewayを設定

という感じです。
EC2の起動スクリプトは次のような簡単なものです。

import json
import boto3
region = 'ap-northeast-1'
instances = ['i-YOUR-INSTANCE-ID']
ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
    ec2.start_instances(InstanceIds=instances)
    print('started your instances: ' + str(instances))
    return {
        'statusCode': 200,
        'body': json.dumps('OK')
    }

あとは、API Gatewayで作成したURLをNumeraiの設定すれば完成。

Numerai Compute Webhook Setting

EC2インスタンス起動時にpredict.pyを実行する

EC2インスタンスは g4dn.xlarge を使用しています。GPU は NVIDIA T4 で RAMは 16GiB となっており、Google Colabと同等のスペックになっています。Google Colabから移植するにはもってこいですね!

AMIはDeep Learning AMIを使用すれば、最初からTensorFlowやPyTorchがインストールされていて便利です。

さて、EC2インスタンスの起動時にスクリプトを起動するように設定します。

cronで起動時に実行するスクリプトを設定しましょう。

crontab -e
@reboot /home/ubuntu/numerai/on_start.sh

実行するスクリプトはこんな感じです。

/home/ubuntu/numerai/on_start.sh
#!/bin/bash

cd `dirname $0`

SHELL=/bin/bash
# パスを通す
source /home/ubuntu/.bashrc
# 好きなPython環境を設定
source activate tensorflow2_latest_p37

sudo shutdown +45

python3 predict.py

predict.pyの起動前に、45分後にシャットダウンするように指示しています。
predict.py実行後に即シャットダウンだと、predict.pyがバグってる時にメンテで起動しようとしても、すぐシャットダウンしてしまうので要注意です。

predict.pyではDiscordに通知するようにしておくと便利です。
スクリプト全体をtryで囲って、エラーを全部Discordに流すようにしています。

predict.py
import requests
import traceback

def discord_post(message, filename=None, url='https://discord.com/api/webhooks/YOUR_DISCORD_URL'):
    payload = {"content": " " + message + " "}
    try:
        if filename is None:
            requests.post(url, data=payload)
        else:
            files = {"imageFile": open(filename, "rb")}
            requests.post(url, data=payload, files=files)
    except:
        pass

discord_post("Start predict.py")

try:
    import pandas as pd
    import numerapi

    (中略)

except:
    discord_post(traceback.format_exc() + "\nBAD END...")

ひととおり出来上がったら、NumeraiのSetting画面からWebHookをテスト起動してみて、動作確認をしましょう。

おわりに

最初の設定は面倒ですが、一度やってしまえば寝てる間に予測が提出されていて安心です。
土日の自由時間が増えますよ!ぜひやってみてください!