Last active
January 13, 2021 15:46
-
-
Save harusametime/ac3050d25c47b23534784ce8fb09da6b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# GluonCV のモデルを SageMaker のエンドポイントにホストする\n", | |
"\n", | |
"\n", | |
"## 1. SageMaker のエンドポイントにモデルを配置して推論を実行するスクリプトを作成する\n", | |
"\n", | |
"以下のコードブロックを実行すると、以下のコードが記載された deploy.py ファイルができます。ファイルの中には、モデルを配置する model_fn と推論を実行する transform_fn が必要です。\n", | |
"- model_fn \n", | |
" ここでは gluoncv を使ってモデルを読み込むコードのみを書きます。そのモデルは net に保存され、transform_fn に渡されます。\n", | |
" \n", | |
"- transform_fn \n", | |
" model_fn から net を受け取り、また推論のリクエスト data に対して予測を実行します。data は base64 形式で届くので、まずdecode してから PIL で画像として読み込みます。gluon での予測は mxnet の array 形式である必要があるため、mx.nd.array への変換などを行い、predict で予測します。エンドポイントから結果を返すのも json である必要があるので、json.dumps した結果を返します。" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"%%writefile deploy.py\n", | |
"\n", | |
"import gluoncv\n", | |
"from gluoncv.data.transforms.presets.segmentation import test_transform\n", | |
"\n", | |
"import json\n", | |
"import logging\n", | |
"import mxnet as mx\n", | |
"from mxnet import gluon\n", | |
"import os\n", | |
"from io import BytesIO\n", | |
"import base64\n", | |
"from PIL import Image\n", | |
"import numpy as np\n", | |
"\n", | |
"logging.basicConfig(level=logging.DEBUG)\n", | |
"\n", | |
"def model_fn(model_dir):\n", | |
" net = gluoncv.model_zoo.get_deeplab_resnet50_ade(pretrained=True, ctx=mx.gpu())\n", | |
" return net\n", | |
"\n", | |
"def transform_fn(net, data, input_content_type, output_content_type):\n", | |
" \n", | |
" data = base64.b64decode(data)\n", | |
" data = Image.open(BytesIO(data))\n", | |
" data = np.array(data)\n", | |
" data = mx.nd.array(data,ctx=mx.gpu())\n", | |
" data = test_transform(data,ctx=mx.gpu())\n", | |
" output = net.predict(data)\n", | |
" predict = mx.nd.squeeze(mx.nd.argmax(output, 1)).asnumpy().tolist()\n", | |
" response_body = json.dumps(predict)\n", | |
" return response_body, output_content_type" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## 2. スクリプトを使って推論用のエンドポイントを作成する\n", | |
"\n", | |
"基本的には1のスクリプトのみで完結しますが、SageMaker の仕様上、スクリプトだけでなく、そこで読み込むモデルも渡す必要があります (SageMaker APIの仕様)。ここでは中身のない0バイトの tar.gz ファイルを作って S3 にアップロードしておき、それを使うように API を実行します。\n", | |
"\n", | |
"\n", | |
"touchで空のファイルを作成して tar.gzに固め、これをダミーのモデルとします。" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"!mkdir ./model\n", | |
"!touch ./model/dummy_model\n", | |
"!tar -zcvf model.tar.gz model" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"次にそれをアップロードします。実行するとアップロード先が表示されます。" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import sagemaker\n", | |
"sagemaker_sess = sagemaker.Session()\n", | |
"\n", | |
"dummy_path = sagemaker_sess.upload_data('model.tar.gz', key_prefix='dummy_model')\n", | |
"print('Dummy model has been uploaded to {}'.format(dummy_path))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"上記のスクリプトとダミーのモデルをセットしてデプロイの準備をします。MXNetModel の関数を読み込むことで、GluonCVがインストールされた環境を使ってデプロイすることができるので、ユーザ側で環境を用意する必要はなく、モデルとスクリプトを用意するだけです。" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from sagemaker.mxnet.model import MXNetModel\n", | |
"\n", | |
"deeplab_model = MXNetModel(model_data = dummy_path,\n", | |
" role = sagemaker.get_execution_role(),\n", | |
" entry_point = 'deploy.py',\n", | |
" framework_version='1.6.0',\n", | |
" py_version='py3',\n", | |
" env={'MXNET_CUDNN_AUTOTUNE_DEFAULT': '0'})" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"上記は設定を作成しただけですので、以下のコードを実行してデプロイします。以下を実行するとインスタンスが新規起動されるので料金がかかります。\n", | |
"\n", | |
"-----!\n", | |
"\n", | |
"と最後に`!`がでると完了です。" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"scrolled": true | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"-" | |
] | |
} | |
], | |
"source": [ | |
"predictor = deeplab_model.deploy(initial_instance_count=1, instance_type='ml.g4dn.xlarge')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "conda_mxnet_p36", | |
"language": "python", | |
"name": "conda_mxnet_p36" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.6.10" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 4 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment