Amazon SageMakerで複数モデルを紐づけたエンドポイントを構築する

はじめに

好物はインフラとフロントエンドのかじわらゆたかです。 SagemakerのEndpoint構築はdeployメソッド実行するだけで可能ですが、
SagemakerのEndpoint configを用いることで、deployではできない細かいな設定を記載することが可能です。

今回はちょっと複雑なEndpoint を構築してみたいと思います。

A / Bテストを行うEndpointの構築

Sagemakerのエンドポイントの特徴として以下が挙げられます。

自動 A/B テスト Amazon SageMaker はまたモデルの A/B テストも行えます。エンドポイントの設定で最大 5 つのモデルに渡ってトラフィックを分散し、各々が処理するインファレンスコールのパーセンテージを設定できます。これらはすべて操作しながら変更できます。柔軟に実験することにより、どのモデルが実際の世界で最も正確な結果を生み出すかを決定できます。

複数のモデルを含めたendpointの構築をしていきたいと思います。

演習に用いたJupyterNotebookはこちらにあります。

上記の演習を進めていき、現在以下のような2つのモデルが存在しているとします。

  • xgboost-2018-12-22-18-12-18-044
  • xgboost-2018-12-20-21-27-59-069

これらのモデルを含んだEndpointを構築していきます。

エンドポイント設定の作成

from time import gmtime, strftime
sagemarker_client = boto3.client('sagemaker')

endpoint_config_name = 'XGBoost-MultiModel-' + strftime("%Y-%m-%d-%H-%M-%S", gmtime())
model_name_test_a = 'xgboost-2018-12-22-18-12-18-044'
model_name_test_b = 'xgboost-2018-12-20-21-27-59-069'

print(endpoint_config_name)
create_endpoint_config_response = sagemarker_client.create_endpoint_config(
    EndpointConfigName = endpoint_config_name,
    ProductionVariants=[{
        'InstanceType':'ml.m4.xlarge',
        'InitialInstanceCount':1,
        'ModelName':model_name_test_a,
        'VariantName':'TEST-A'},{
        'InstanceType':'ml.m4.xlarge',
        'InitialInstanceCount':1,
        'ModelName':model_name_test_b,
        'VariantName':'TEST-B'}])

endpoint configを作成するメソッドcreate_endpoint_configは SageMaker Python SDKではなくboto3に存在するメソッドのため、注意が必要です。

エンドポイントの作成

endpoint_name = 'XGBoostMultiModelEndpoint-' + strftime("%Y-%m-%d-%H-%M-%S", gmtime())
print(endpoint_name)
create_endpoint_response = sagemaker.create_endpoint(
    EndpointName=endpoint_name,
    EndpointConfigName=endpoint_config_name)
print(create_endpoint_response['EndpointArn'])

resp = sagemaker.describe_endpoint(EndpointName=endpoint_name)
status = resp['EndpointStatus']
print("Status: " + status)

try:
    sagemaker.get_waiter('endpoint_in_service').wait(EndpointName=endpoint_name)
finally:
    resp = sagemaker.describe_endpoint(EndpointName=endpoint_name)
    status = resp['EndpointStatus']
    print("Arn: " + resp['EndpointArn'])
    print("Create endpoint ended with status: " + status)

    if status != 'InService':
        message = sagemaker.describe_endpoint(EndpointName=endpoint_name)['FailureReason']
        print('Training failed with the following error: {}'.format(message))
        raise Exception('Endpoint creation did not succeed')

こちらも用いるのはboto3側のメソッドになるので注意が必要です。

エンドポイントの検証

from sagemaker.predictor import RealTimePredictor
from sagemaker.predictor import csv_serializer
xgboost_multimodel_predictor = RealTimePredictor(endpoint_name,content_type='text/csv',serializer=csv_serializer)
def predict(data, rows=500):
    split_array = np.array_split(data, int(data.shape[0] / float(rows) + 1))
    predictions = ''
    for array in split_array:
        predictions = ','.join([predictions, xgboost_multimodel_predictor.predict(array).decode('utf-8')])

    return np.fromstring(predictions[1:], sep=',')

predictions = predict(test_data.as_matrix()[:, 1:])

deployメソッドを使わずにエンドポイントを構築したため、推論を行うオブジェクトをRealTimePredictorから作り、推論を行いました。 複数のModelが含まれているからといって、そのためになにか意識をする必要等はありません。

参考

ステップ 3.4: Amazon SageMaker ホスティングサービスにモデルをデプロイする

まとめ

Sagemakerのエンドポイントに複数のモデルを紐付けるのは、そんなに難しくないことがわかったかと思います。