Amazon SageMaker BlazingText(推論編)

目次

Amazon SageMaker(以下SaSageMaker)の組み込みアルゴリズムであるBlazingTextで学習したモデルを使って、推論エンドポイントによる推論を行います。その際にインスタンスを立ち上げるエンドポイントタイプとともに、サーバレスエンドポイントタイプでも実行します。

SageMakerによる推論処理

前回学習したモデルに対して推論を行いたいと思います。

SageMakerには推論をするための機能がありますが、現時点で大きく分けて以下の4種類が存在します。

  1. インスタンスのスケーリングなどを自分で管理し、リアルタイム(同期的)に推論する従来タイプのエンドポイント
  2. リアルタイム(同期的)に推論するが、リクエストがあった時の推論の処理時間や処理したデータ量に応じてのみ課金が発生するサーバレスエンドポイント
  3. 大きなリクエストを非同期で処理するエンドポイント
  4. 大量のデータに対して推論を行うバッチ推論

1と2はリアルタイム(同期的)に推論結果を得るための機能であるのに対し、3と4は非同期的に推論を行う機能になります。今回は1(従来タイプ)と2(サーバレスタイプ)を扱います。

さて、従来タイプとサーバレスタイプとを比べた場合、

  • 自分でインスタンスタイプやそのスケーリングを管理する必要がある
  • リクエストが来ないアイドル状態でも課金が発生する

という点からサーバレスのほうが圧倒的に良いように思えるかもしれません。

では、常にサーバレスを使えばよいかというと、そうでもありません。

サーバレスタイプの推論エンドポイントには、いくつか制限があります。公式ドキュメントにその制限が書かれていますが、従来タイプのエンドポイントでは使えるいくつかの機能が使えないという制限があります。その中でももっと大きいのはGPUを使えないということです。

GPUを使えるかどうかは、推論のレイテンシーを大きく左右するので、ある程度規模の大きいモデルで推論を行う際にはネックになるかと思います。

とはいえ、リクエストがあるときのみ課金という点は非常に魅力的ではあるので、使えるところは積極的に使っていきたいものです。今回のようなモデルであればGPUを使わなくても十分なので、両方の利用法で推論エンドポイントを作成していきます。

既存の学習済みのモデルの取得

前回同様に、SageMaker Python SDKを使用するので、前準備としてインストールします。

pip install sagemaker

まず、前回学習した結果のモデルからModelオブジェクトを作ります。

import sagemaker
import boto3
from sagemaker.predictor import Predictor


sess = sagemaker.Session()
role = "role_arn"
region = boto3.Session().region_name
container = sagemaker.image_uris.retrieve("blazingtext", region)

model = sagemaker.model.Model(
    model_data="model_data_path",
    image_uri=container,
    sagemaker_session=sess,
    predictor_cls=Predictor,
    role=role)

role_arnとmodel_data_pathはそれぞれの環境ごとに違うので適宜変更します。model_data_pathは、前回の学習処理のoutput先に設定したS3バケットのパスになります。SageMakerのコンソールの「トレーニングジョブ」の詳細画面にある「出力」というところに書いてあるS3 モデルアーティファクトがそのパスになります。

image_uriは前回学習に使用したものと同じものを指定します。

predictor_clsには、推論エンドポイントに対してデータが投げられる時にモデルが処理できる形式に前処理(シリアライズ)したり結果を都合のいい語りに後処理(デシリアライズ)したりするためのクラスを指定します。今回は特に処理がいらないので、sagemaker.predictorモジュールからインポートしたPredictorクラスをそのまま指定しています。

従来タイプの推論エンドポイントのデプロイ

モデルのデプロイは以下の1行で実行できます。

instance_endpoint = model.deploy(initial_instance_count=1, instance_type="ml.t2.medium", endpoint_name="instance-endpoint")

初期起動インスタンスの数とインスタンスタイプを指定するのみです。コンソールなどで作る際にはエンドポイント設定を作って、それを元にエンドポイントを作成するなどの設定が必要ですが、SDKがよしなにやってくれるので楽ですね。

サーバレスタイプの推論エンドポイントのデプロイ

つついてサーバレスタイプの推論エンドポイントです。

from sagemaker.serverless import ServerlessInferenceConfig


serverless_config = ServerlessInferenceConfig(
    memory_size_in_mb=1024,
    max_concurrency=1
)

serverless_endpoint = model.deploy(serverless_inference_config=serverless_config, endpoint_name="serverless-endpoint")

ServerlessInferenceConfigにメモリサイズと同時実行数を指定して、それをdepoy時に渡してあげる形になります。

推論リクエストの実行\

最後にそれぞれのエンドポイントに推論リクエストを送ります。

import json


words = ["scipio"]
payload = {"instances": words}
# 従来タイプ
response = instance_endpoint.predict(
    json.dumps(payload),
    initial_args={"ContentType": "application/json", "Accept": "application/json"},
)
print(json.loads(response))

# サーバレスタイプ
response = serverless_endpoint.predict(
    json.dumps(payload),
    initial_args={"ContentType": "application/json", "Accept": "application/json"},
)
print(json.loads(response))

上記のコードを実行すると以下の様な出力がされます。ちゃんとwordのベクトル結果を取得できていますね。

[{'vector': [0.011563128791749477, (省略), -0.10662495344877243], 'word': 'scipio'}]
[{'vector': [0.011563128791749477, (省略), -0.10662495344877243], 'word': 'scipio'}]

前回の学習処理、今回の推論処理の一連の流れは、他の組み込みアルゴリズムや自身で用意したアルゴリズムを使用する場合でも基本的に同じです。SageMakerを使うことでやり方を標準化できるのも、SageMakerの魅力の一つだと思います。