Python
AWS
MachineLearning
Jupyter
SageMaker

【完結編】AWS Amazon SageMaker つかってみた4 〜GPU利用でサンプルの実行〜

はじめに

Amazon SageMaker を利用する上で自分が気になったところ、詰まったところを中心にまとめていきます。
この記事では前回の記事で失敗したサンプルの実行について再度まとめます。
前回の記事はこちら
次回の記事は作成中

サンプルの場所

Jupyterの導入については前回の記事を参照

  1. Jupyterのホーム画面を開きます。
  2. sample-notebooks ディレクトリを開きます。
  3. sagemaker-python-sdk ディレクトリを開きます。
  4. mxnet_gluon_cifar10 ディレクトリを開きます。
  5. cifar10.ipynb ファイルを開きます。

サンプルの実行

Jupyter NotebookにはPythonのコードと説明が含まれます。
右に In [ ]: と書かれているのがコードで、それ以外は説明です。

サンプルについて

  • 用いるデータセット: CIFAR-10という6万枚の画像データのデータセット
  • 学習内容: 34層の深層学習により画像を10種類にクラスタリングする。

セットアップ

scikit-image のライブラリが必要なのでcondaのページから入れてください。

  1. conda tab のリンクをクリックするか、Jupyterのホームから Conda のタブをクリックします。
  2. Available packages のところのSearchで scikit-image を検索します。
  3. scikit-image を選択します。
  4. 右矢印を押下してインストールします。

はじめのpythonコードを実行してみましょう。
以下のコードを選択して、画面上部の Cell から Run Cells を選択します。

import os
import boto3
import sagemaker
from sagemaker.mxnet import MXNet
from mxnet import gluon
from sagemaker import get_execution_role

sagemaker_session = sagemaker.Session()

role = get_execution_role()

右の表示が In [*]: に変わります。
* は実行中であることを表します。
実行が終わると In [1]: のような表示になります。
数字は実行された順番を表します。

初めて実行すると以下のWarningが表示されます。
こちらの原因と解消方法を知っている人がいれば教えてください。

/home/ec2-user/anaconda3/envs/mxnet_p27/lib/python2.7/site-packages/urllib3/contrib/pyopenssl.py:46: DeprecationWarning: OpenSSL.rand is deprecated - you should use os.urandom instead
  import OpenSSL.SSL

もう一度実行するとWarningが消えます。

データのダウンロード

CIFAR10をダウンロードします。

from cifar10_utils import download_training_data
download_training_data()

少し時間がかかります。

データのアップロード

Amazon SageMakerで学習させるにはまずS3に学習データをアップロードする必要があります。
S3へデータをアップロードするには sagemaker.Session.upload_data の関数を使います。
戻り値の inputs にはアップロード先のIDが入っており、後ほど学習の際に利用します。

inputs = sagemaker_session.upload_data(path='data', key_prefix='data/gluon-cifar10')
print('input spec (in this case, just an S3 path): {}'.format(inputs))

train 関数の確認

SageMakerで利用可能な学習スクリプトを用意する必要があります。
学習スクリプトは train 関数として実装されている必要があります。
学習環境の情報が train 関数の引数として渡されます。

!cat 'cifar10.py'

学習スクリプトの実行

MXNet クラスを用いると分散環境での学習が可能です。
以下の設定をします。

  • 学習スクリプト
  • IAMロール
  • インスタンス数
  • インスタンスタイプ

デフォルトでは2個の ml.p2.xlarge インスタンスで学習ができるように設定されています。
3行目の train_instance_count の値を 1 に変更して1個のインスタンスで学習するように変更してください。(理由は考察の項目を参照)
※GPUインスタンスはデフォルトで使用制限があります。制限解除方法についてはこちらの記事にまとめています。

m = MXNet("cifar10.py", 
          role=role, 
          train_instance_count=1, 
          train_instance_type="ml.p2.xlarge",
          hyperparameters={'batch_size': 128, 
                           'epochs': 50, 
                           'learning_rate': 0.1, 
                           'momentum': 0.9})

MXNet クラスができましたので、アップロードしたデータを使って学習を開始します。

m.fit(inputs)

学習がスタートしました。
現在実行中の学習はAmazon SageMakerのジョブの画面で確認できます。
学習時間は44分でした。 ml.p2.xlarge が1時間\$1.26ですので学習にかかった費用は\$1ほどです。

予測

学習が終わりましたので学習結果を使ってエンドポイントを作成します。
学習ではGPUインスタンスを利用しましたが、エンドポイントではCPUのインスタンスも利用できます。

deployの戻り値のpredictorオブジェクトでエンドポイントを呼び出してサンプル画像の予測ができます。

predictor = m.deploy(initial_instance_count=1, instance_type='ml.m4.xlarge')

CIFAR10のサンプル画像

サンプル画像でCIFAR10のテストをします。

# load the CIFAR10 samples, and convert them into format we can use with the prediction endpoint
from cifar10_utils import read_images

filenames = ['images/airplane1.png',
             'images/automobile1.png',
             'images/bird1.png',
             'images/cat1.png',
             'images/deer1.png',
             'images/dog1.png',
             'images/frog1.png',
             'images/horse1.png',
             'images/ship1.png',
             'images/truck1.png']

image_data = read_images(filenames)

predictorは入力された画像を予測して結果のラベルを返します。
ラベルはfloat値で返ってくるのでintに変換してから表示しています。

for i, img in enumerate(image_data):
    response = predictor.predict(img)
    print('image {}: class: {}'.format(i, int(response)))

リソースの開放

このサンプルの実行が終わったらインスタンスを開放してエンドポイントを削除するのをお忘れなく。

sagemaker.Session().delete_endpoint(predictor.endpoint)

結果

正解率80%

image 0: class: 0
image 1: class: 9
image 2: class: 2
image 3: class: 3
image 4: class: 4
image 5: class: 5
image 6: class: 2
image 7: class: 7
image 8: class: 8
image 9: class: 9

考察

GPUの圧倒的な処理速度

GPUが得意な画像処理ということもあり60倍程度の処理速度が出ていた。

インスタンスタイプ 1秒間に処理できるサンプル数
ml.m4.xlarge 約 22 サンプル/秒
ml.p2.xlarge 約 1400 サンプル/秒

単位時間あたりはCPUよりGPUの方が高いが、処理速度が段違いなので結果的にGPUを使うほうが安上がりになる。

並列処理の同期のオーバヘッドが大きい

MXNetでは1回の学習ごとに各インスタンス間で同期を取っているようです。
単体のインスタンスで学習をさせたところ1秒間に11回の学習ができたのに対し、2並列で学習させた場合は毎秒各インスタンス1回ずつの合計2回しか学習ができませんでした。
分散学習をさせると性能が1/5に低下してしまいます。

インスタンスタイプ 1秒間に学習できる回数
単体(同期なし) 約 11 回/秒
2並列(毎回同期) 約 2 回/秒

今回の学習では1回の学習に要する時間が0.1秒以下の学習であったために毎回同期を取らないといけない並列処理のほうが遅くなる結果となってしまった。

SageMakerのいいと感じたところ

ワンストップで実行可能

ノートブックの作成、リソースの確保、学習、エンドポイントの作成までワンストップで行える。

リソースの最適化

ノートブック、学習、エンドポイントでそれぞれでインスタンスを選択できる。
学習は学習している間だけ料金が発生する。