概要
- AWSのSagemakerを使ってモデルをトレーニングし、Compileまでやってみる!
はじめに
AWSのSagemakerを勉強した機会があったので、せっかくだからまとめたいなと記事に起こしました。
意外とCompileまで説明している人は少なかったので、AWS IoT GreenGrassを使う人とかの参考になればなと思います。
実験環境
- Amazon SageMaker Notebooks
- Tensorflow Keras
Sagemakerとは?
Sagemakerとは何なのかということは他のサイトで詳しく解説されていますので、具体的なことは割愛して、
簡単に言うと、機械学習の諸々の処理をクラウド上で行うためのツールみたいなものです。
例えば、アノテーション、モデルの学習推論、コンパイルなどをSagemaker上だけで行うことができます。
本記事では、モデルの学習~コンパイルまでをメインに扱っていきます。
Sagemakerについて
今回はSagemakerにあるGround Truthには触れないので参考記事の方を以下に載せておきます。
Sagemaker Notebook
今回使用していくのが、SagemakerのNotebookになります。このNotebookは、ほぼJupyter NotebookとLabみたいなものです。
Notebookインスタンスを起動するときに、NotebookかLabのどちらかで起動することができます。
インスタンスの作成方法はそんなに難しくないと思うので、参考までに以下の記事を載せておきます。
少し補足したいことがあったので補足すると、ロールを選択する箇所で「新しいロールを作成」であったり、「既存のロールを使用」という選択肢があります。
一人で、Sagemakerを使う場合は上記のサイトの通りにやるとすんなりできると思いますが、AWSのホストが自分以外のユーザーにある場合には、そのホストの人に
- AmazonSageMakerFullAccess
- 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つの方法があるのかなと思います。
- 裏でtensorflowやpytorchのコンテナが起動し、そのコンテナ上で学習。
- ノートブック上で学習
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 |
そのため、コンテナの中にインストールされていないライブラリをつかいたい場合は、随時インストールする必要があります。
インストール方法としてはこちらも2つあります。
- Trainingのパラメータの中にあるdependenciesにライブラリのフォルダを指定する
- Training用の.pyファイルの先頭にコードを書き込む
1の方はうまくいくときと行かないときがあったので、自分は2のほうがいいのかなと思います。また、1の方はノートブック内にインストールされるので、容量を食ってしまいます。
1の方法
ライブラリをインストールする用のディレクトリを作り、そこに使用したいライブラリをインストール
python3 -m pip install matplotlib --target ./module
その後、dependenciesにパスを設定
2の方法
学習用のpythonファイルの先頭にsubprocess
を使ってライブラリをインストールするためのコードを書き込む
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でモデルを保存するコードは
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を使っています。
まずは今回使用するライブラリのインポート
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のバケットの指定を行います。
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を使用するだけでいつも通りのコードの書き方で書くことができます。
パラメータの補足は後でします。
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であれば出力はされなくなります。
estimator.fit({'training':s3_train_data}, wait=False, logs=True)
トレーニングジョブのところから、確認したいトレーニングをクリックして、
「ログを表示」のところで確認することができます。
また、バケットからファイルをダウンロードしたい場合は、以下のようにしてダウンロードすることができます。
学習のヒストリーとかを見たい場合に使うのかなと思います。
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
で使うことができます。
使い方の例として、以下にコードを書いておきます。
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
にすることで、学習の時間は伸びてしまいますが、料金を節約することができます。
推論(Inference)
学習が終わったあとに、そのモデルで推論を行うことができます。
推論を行うためには、Sagemakerではエンドポイントというものを作成する必要があります。このへんはググればたくさんサイトが出てくると思うので、自分の記事か他のサイトの記事か好きなものを参考にしてみてください。
エンドポイントを作成する方法はSagemakerのメニューからGUIで作成するか、ノートブック上でスクリプトを書くかの2つの方法があります。
個人的には、スクリプトで書いたほうが流れで作業が出来かつわかりやすいので、スクリプトで書くことをおすすめします。
training後にそのモデルを使って推論をする場合
detector = estimator.deploy(initial_instance_count=1, instance_type="ml.m4.xlarge")
別のtraining結果のモデルで推論をする場合
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のモデルで予測
以下のコードを推論をするスクリプトの中に記載することで、推論ができます。
model = detector
results = model.predict(input)
推論をする必要がなくなったら、endpointの削除は絶対にする必要があります。
削除しない場合はお金がかかるので要注意です。
sagemaker.Session().delete_endpoint(detector.endpoint_name)
endpointが削除されたかどうか確認したい場合は、Sagemakerのメニューのエンドポイントのところで確認可能です。
コンパイル(Compile)
それでは最後に、Sagemakerで学習をしたモデルをコンパイルしていきます。
このコンパイルという過程は、AWSのGreengrassというIoTのサービスを使う上で必要になってくると思います。
ちなみにGreengrassとは
AWS IoT Greengrass は、クラウドの機能をローカルデバイスに拡張するソフトウェアです。これにより、デバイスは情報源に近いデータを収集および分析して、ローカルイベントに自律的に反応し、ローカルネットワークで互いに安全に通信することができます。ローカルデバイスもAWS IoT Coreにエクスポートし、IoT データをAWS クラウド。AWS IoT Greengrass開発者はAWS Lambda関数と事前ビルドコネクタを使用して、ローカルで実行するためにデバイスにデプロイされるサーバーレスアプリケーションを作成します。
簡単に言うと「jetsonなどのエッジデバイスとAWSを繋ぐ架け橋」みたいなものです。
と、Greengrassの話はここまでにして、コンパイルに入っていきましょう。
コンパイルもエンドポイント作成と同様に、Sagemakerのメニューあるいはスクリプトで行うことができます。
今回はスクリプトの紹介をしていこうと思います。というのも、メニューはスクリプトをそのまま入れればいいだけなので笑
ちなみに、このコンパイルはSagemaker Neoによるコンパイルというものになります。
Sagemaker Neoについて
コードは以下のようになります。
パラメータの設定方法はリファレンスに記載してあります。
training後にそのモデルを使って推論をする場合
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結果のモデルで推論をする場合
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を使ってデプロイしてみたいなと考えています。