search
LoginSignup
3

posted at

updated at

Organization

Amazon Sagemaker ~trainingからCompileまで~

概要

  • AWSのSagemakerを使ってモデルをトレーニングし、Compileまでやってみる!

はじめに

AWSのSagemakerを勉強した機会があったので、せっかくだからまとめたいなと記事に起こしました。
意外とCompileまで説明している人は少なかったので、AWS IoT GreenGrassを使う人とかの参考になればなと思います。

実験環境

  • Amazon SageMaker Notebooks
  • Tensorflow Keras

Sagemakerとは?

Sagemakerとは何なのかということは他のサイトで詳しく解説されていますので、具体的なことは割愛して、
簡単に言うと、機械学習の諸々の処理をクラウド上で行うためのツールみたいなものです。
例えば、アノテーション、モデルの学習推論、コンパイルなどをSagemaker上だけで行うことができます。
本記事では、モデルの学習~コンパイルまでをメインに扱っていきます。

Sagemakerについて

今回はSagemakerにあるGround Truthには触れないので参考記事の方を以下に載せておきます。

↓ Sagemakerのタブ
image.png

Sagemaker Notebook

今回使用していくのが、SagemakerのNotebookになります。このNotebookは、ほぼJupyter NotebookとLabみたいなものです。
Notebookインスタンスを起動するときに、NotebookかLabのどちらかで起動することができます。

インスタンスの作成方法はそんなに難しくないと思うので、参考までに以下の記事を載せておきます。

少し補足したいことがあったので補足すると、ロールを選択する箇所で「新しいロールを作成」であったり、「既存のロールを使用」という選択肢があります。
一人で、Sagemakerを使う場合は上記のサイトの通りにやるとすんなりできると思いますが、AWSのホストが自分以外のユーザーにある場合には、そのホストの人に

  1. AmazonSageMakerFullAccess
  2. AmazonS3FullAccess

の最低限2つはIAMのアクセス権限に追加してもらい、そのIAMを使用すると、うまくいくと思います。

ちょっとSagemaker Studioについて

Sagemaker Notebookとは別に、Notebookを拡張したSagemaker StudioがSagemakerにはあります。
Notebookインスタスでは一度起動してしまうと、Notebook自体のインスタンス(ml.p2.xlargeとか)を変更するためには、一度インスタンスを終了して変更し、再び起動しなければいけませんでした。
しかし、Studioであればインスタンスタイプを起動中も変更できるます。また、推論に使用するエンドポイントがNotebook上で見れたり、学習済みモデルのインポートが、ボタンをポチポチするだけでできたりします。
であれば、Studioを使えばいいのではと思われるかもしれませんが、「なんか動作が重かった」という理由故に、Notebookを使うことにしました笑。
今は、改善されているかもしれませんので、こっちの方が断然使いやすいじゃんという人は、Sagemaker Studioを使ってみてください。

Sagemaker Studioについて

Sagemakerのコンテナについて

Sagemakerはtrainingをするときには大きく分けて2つの方法があるのかなと思います。

  1. 裏でtensorflowやpytorchのコンテナが起動し、そのコンテナ上で学習。
  2. ノートブック上で学習

2の場合だと学習に使われるインスタンスが起動したノートブックのインスタンスに依存してしまうので、個人的には1の方がいいのかなと思います。
今回も1の方法で学習を行っているのですが、実はコンテナの中にはそんなにライブラリがインストールされてはいません。

tensorflowのコンテナの中にあるライブラリ

Dependencies Scipt Mode Legacy Mode
boto3 Latest Latest
botocore Latest Latest
CUDA (GPU image only) 9.0 9.0
numpy Latest Latest
Pillow Latest Latest
scipy Latest Latest
sklean Latest Latest
h5py Latest Latest
pip 18.1 18.1
curl Latest Latest
tensorflow 1.12 1.12
tensorflow-serving-api 1.12 None
sagemaker-containers >=2.3.5 >=2.3.5
sagemaker-tensorflow-container 1.0 1.0
Python 2.7 or 3.6 2.7

SageMaker TensorFlow Docker containers

そのため、コンテナの中にインストールされていないライブラリをつかいたい場合は、随時インストールする必要があります。
インストール方法としてはこちらも2つあります。

  1. Trainingのパラメータの中にあるdependenciesにライブラリのフォルダを指定する
  2. Training用の.pyファイルの先頭にコードを書き込む

1の方はうまくいくときと行かないときがあったので、自分は2のほうがいいのかなと思います。また、1の方はノートブック内にインストールされるので、容量を食ってしまいます。

1の方法
ライブラリをインストールする用のディレクトリを作り、そこに使用したいライブラリをインストール

.bash
python3 -m pip install matplotlib --target ./module

その後、dependenciesにパスを設定

参考サイト:SageMakerでTensorFlow+Kerasによる独自モデルをトレーニングする方法

2の方法
学習用のpythonファイルの先頭にsubprocessを使ってライブラリをインストールするためのコードを書き込む

.py
import subprocess
import sys
# 必要なmoduleをインストール
def install(package):
    subprocess.check_call([sys.executable, "-q", "-m", "pip", "install", package])
install('tables==3.5.2')
install('matplotlib')

Train.pyの注意点

モデルの学習に入る前に一つだけ注意点があります。
それは、モデルの保存方法に関することなのですが、trainの.pyファイルのモデル保存で適切に保存されるコードを書いてないと、エンドポイントの作成などは行うことができるが、Compileが行えないといった事態が発生してしまいます。

Kerasでモデルを保存するコードは

.py
model_save_path = os.path.join(args.model_dir, str(db_number))
os.makedirs(model_save_path)
model.save(model_save_path, save_format='tf')

# Freeze saved model
input_node_names = [inp.name.split(":")[0] for inp in model.inputs]
output_node_names = [output.name.split(":")[0] for output in model.outputs]
print("Input names: ", input_node_names)
with tf.Session() as sess:
    loaded = tf.saved_model.load(sess, export_dir=model_save_path, tags=["serve"]) 
    frozen_graph = tf.graph_util.convert_variables_to_constants(sess,
                                                                sess.graph.as_graph_def(),
                                                                output_node_names)
    tf.io.write_graph(graph_or_graph_def=frozen_graph, logdir=".", name="frozen_graph.pb", as_text=False)

のようにする必要があります。

学習(Training)

それではモデルの学習に入っていきましょう!
今回はkerasを使用しているので、tensorflow kerasを使っています。

まずは今回使用するライブラリのインポート

.py
import os
import keras
import numpy as np
import sagemaker
from sagemaker.tensorflow import TensorFlow
from sagemaker import get_execution_role

使用するロールとS3バケットの設定
Sagemakerでは基本的にトレーニングに使用するデータや、モデルの結果をS3から取り出したり保存したりするので、そのS3のバケットの指定を行います。

.py
role = get_execution_role()
print(role)
sess = sagemaker.Session(default_bucket="s3のバケット")
bucket = sess.default_bucket()
print(bucket)

トレーニングに使用するパラメータの設定
今回のトレーニングではSagemakerに元から用意されているTensorflowのコンテナと、Script modeというものを使用しています。
Script modeを使わない場合は、Sagemakerのお作法に沿って学習用のスクリプトを記述する必要があります。(お作法の紹介サイト)
しかし、Script modeを使用するだけでいつも通りのコードの書き方で書くことができます。
パラメータの補足は後でします。

.py
s3_train_data = "s3://path/to/train/file"
s3_output = "s3://path/to/output"
s3_output_checkpoint = "s3://path/to/checkpoint"
print("s3_train_data : ", s3_train_data)
print("s3_output : ", s3_output)
print("s3_output_checkpoint : ", s3_output_checkpoint)

epochs = 70
db = "test"

hyper_param = {
    "batch_size"       : 128,
    "nb_epochs"        : epochs,
    "db"               : db,
    "validation_split" : 0.2,
    "checkpoint"       : s3_output_checkpoint,
}

estimator = TensorFlow(entry_point='train.py',
                       source_dir='source',
                       role=role,
                       framework_version='1.15',
                       hyperparameters=hyper_param,
                       instance_count=1,
                       instance_type='ml.p2.xlarge',
                       script_mode=True,
                       checkpoint_s3_uri = s3_output_checkpoint,
                       base_job_name="job",
                       use_spot_instances=True,
                       max_run=30000,
                       max_wait=30000,
                       output_path=s3_output,
                       py_version='py3')

学習用のパラメータ設定が終わったので学習を回していきます。

  • trainingはデータセットがあるバケットのパス
  • waitはTrueにすればノートブック上にもログが出力され、Falseにすればログが出力されなくなります。
  • logsはAWSにあるCloudWatchにログを出力するか否かを設定します。Trueであれば出力され、Falseであれば出力はされなくなります。
.py
estimator.fit({'training':s3_train_data}, wait=False, logs=True)

ログの確認は
  aws1.PNG

トレーニングジョブのところから、確認したいトレーニングをクリックして、
aws3.PNG

「ログを表示」のところで確認することができます。

また、バケットからファイルをダウンロードしたい場合は、以下のようにしてダウンロードすることができます。
学習のヒストリーとかを見たい場合に使うのかなと思います。

.py
import boto3

job_name = estimator_age.latest_training_job.name
s3 = boto3.resource('s3')
bucket=s3.Bucket('test')

bucket.download_file(os.path.join("output/"+job_name,"output/output.tar.gz"),"output.tar.gz")

学習のパラメータについて

学習のパラメータについて少し補足をしていきます。

entry_pointとsource_dir

entry_pointは学習用のコードが書かれているファイルのパス、source_dirは学習用のコードと、その他使用するコードがあるフォルダを指定します。
train.pyの中に別ファイルの関数をimportしたい場合は、source_dirで指定したフォルダの中に忘れずにファイルを入れておくようにしましょう。

hyperparameters

学習用のファイル、今回であればtrain.pyで使うことができる変数を定義することができます。
ここで定義した変数はコマンドラインのライブラリであるargparseで使うことができます。
使い方の例として、以下にコードを書いておきます。

.py
import argparse
def get_args():
    parser = argparse.ArgumentParser(description="This script trains the CNN model for age and gender estimation.",
                                     formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("--input", "-i", type=str, default=os.environ.get('SM_CHANNEL_TRAINING'),
                        help="path to input database npz file")
    parser.add_argument("--db", type=str, default="imdb",
                        help="database name(megaage, imdb, wiki)")
    parser.add_argument("--batch_size", type=int, default=128,
                        help="batch size")
    parser.add_argument("--nb_epochs", type=int, default=90,
                        help="number of epochs")
    parser.add_argument("--validation_split", type=float, default=0.2,
                        help="validation split ratio")
    parser.add_argument("--checkpoint", type=str, required=True, 
                        help="model checkpoint dir path")
    parser.add_argument("--model-dir", type=str, default=os.environ.get('SM_MODEL_DIR'),
                        help="model save dir")

    args, _ = parser.parse_known_args()
    return args

def main():
    
    args = get_args()
    input_path = args.input
    db_name = args.db
    batch_size = args.batch_size
    nb_epochs = args.nb_epochs
    validation_split = args.validation_split
    checkpoint_dir = args.checkpoint

# 学習用のスクリプト
instance_type

学習を実行するインスタンスのタイプを選択します。
予算に合ったGPU or CPUのインスタンスを選ぶようにしましょう。

use_spot_instances

これをTrueにすることで、学習の時間は伸びてしまいますが、料金を節約することができます。

参考サイト:【備忘録】Sagemakerの学習にスポットインスタンスを使う【超カンタン】

推論(Inference)

学習が終わったあとに、そのモデルで推論を行うことができます。
推論を行うためには、Sagemakerではエンドポイントというものを作成する必要があります。このへんはググればたくさんサイトが出てくると思うので、自分の記事か他のサイトの記事か好きなものを参考にしてみてください。

エンドポイントを作成する方法はSagemakerのメニューからGUIで作成するか、ノートブック上でスクリプトを書くかの2つの方法があります。

メニューの場合はここから↓
aws4.PNG

個人的には、スクリプトで書いたほうが流れで作業が出来かつわかりやすいので、スクリプトで書くことをおすすめします。

training後にそのモデルを使って推論をする場合

.py
detector = estimator.deploy(initial_instance_count=1, instance_type="ml.m4.xlarge")

別のtraining結果のモデルで推論をする場合

.py
from sagemaker.tensorflow.model import TensorFlowModel

input_model_path = "s3://path/to/own/output.tar.gz"

# Create a TensorFlow SageMaker model
tensorflow_model = TensorFlowModel(model_data = input_model_path, role = role, framework_version='1.15', source_dir='source', entry_point = 'train.py')

detector = tensorflow_model.deploy(initial_instance_count=1, instance_type="ml.m4.xlarge")

endopointのモデルで予測
以下のコードを推論をするスクリプトの中に記載することで、推論ができます。

.py
model = detector
results = model.predict(input)

推論をする必要がなくなったら、endpointの削除は絶対にする必要があります。
削除しない場合はお金がかかるので要注意です。

.py
sagemaker.Session().delete_endpoint(detector.endpoint_name)

endpointが削除されたかどうか確認したい場合は、Sagemakerのメニューのエンドポイントのところで確認可能です。
aws5.PNG

コンパイル(Compile)

それでは最後に、Sagemakerで学習をしたモデルをコンパイルしていきます。
このコンパイルという過程は、AWSのGreengrassというIoTのサービスを使う上で必要になってくると思います。
ちなみにGreengrassとは

AWS IoT Greengrass は、クラウドの機能をローカルデバイスに拡張するソフトウェアです。これにより、デバイスは情報源に近いデータを収集および分析して、ローカルイベントに自律的に反応し、ローカルネットワークで互いに安全に通信することができます。ローカルデバイスもAWS IoT Coreにエクスポートし、IoT データをAWS クラウド。AWS IoT Greengrass開発者はAWS Lambda関数と事前ビルドコネクタを使用して、ローカルで実行するためにデバイスにデプロイされるサーバーレスアプリケーションを作成します。

引用:AWS IoT Greengrass とは

簡単に言うと「jetsonなどのエッジデバイスとAWSを繋ぐ架け橋」みたいなものです。
と、Greengrassの話はここまでにして、コンパイルに入っていきましょう。

コンパイルもエンドポイント作成と同様に、Sagemakerのメニューあるいはスクリプトで行うことができます。
今回はスクリプトの紹介をしていこうと思います。というのも、メニューはスクリプトをそのまま入れればいいだけなので笑
ちなみに、このコンパイルはSagemaker Neoによるコンパイルというものになります。

Sagemaker Neoについて

コードは以下のようになります。
パラメータの設定方法はリファレンスに記載してあります。

training後にそのモデルを使って推論をする場合

.py
compile_output = "s3://{}/{}".format(bucket, "output_compile")
print(compile_output)

compile_mode = estimator.compile_model(
    target_instance_family="jetson_nano",
    input_shape={"input_1": [1, 64, 64, 3]},
    output_path=compile_output,
    role=role,
    framework="tensorflow",
    compile_max_run=5000,
    framework_version='1.15'
)

別のtraining結果のモデルで推論をする場合

.py
from sagemaker.tensorflow.model import TensorFlowModel

input_model_path = "s3://path/to/own/output.tar.gz"

# Create a TensorFlow SageMaker model
tensorflow_model = TensorFlowModel(model_data = input_model_path,role = role, framework_version='1.15', source_dir='source', entry_point = 'train.py')

job_name = "compile"
compile_output = "s3://{}/{}".format(bucket, "output_compile")

tensorflow_model.compile(
    target_instance_family="jetson_nano",
    input_shape={"input_1": [1, 64, 64, 3]},
    output_path=compile_output,
    role=role,
    job_name=job_name,
    compile_max_run=5000,
    framework="tensorflow"
)

コンパイルの成功・失敗はSagemakerの推論メニューで確認できます。

コンパイルが終わったら、あとは煮るなり焼くなり好きにしてもらえればと思います。

終わりに

今回は、AWSのSagemakerを使ってTrainingからCompileまでの手順を紹介させていただきました。
学習用のファイルのスクリプトなどは省きましたが、普段どおりの学習のスクリプトを書いてもらえれば大丈夫です。(というのも、学習用のファイルのスクリプトを書いてくれてる人はネットにたくさんいるので笑)
今後、時間があればjetsonなどでGreengrassを使ってデプロイしてみたいなと考えています。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
3