0
0

【AWS SageMaker】Notebookインスタンスにてバッチ変換で組み込みアルゴリズムXGBoostの推論を行ってみた

Posted at

背景

SageMakerで学習済みモデルを使って推論を行う際、その学習済みモデルのエンドポイントを作成していましたが、バッチ変換を用いる事で、わざわざエンドポイントを作成しなくても推論を行えそうなため(※)、バッチ変換を試してみる事にしました。

(※おそらく、内部的にはエンドポイントは作成されていて、推論完了後に自動でエンドポイントが削除されていると思います。)

環境

sagemaker 2.219.0

試した事(概要)

こちらの記事で作成した学習済みXGBoostモデルを使って、バッチ変換で、Nishikaのテスト(test)データを推論してみます。

試した事(詳細)

こちらの記事の5.7.まで行っていて、学習済みXGBoostモデルのmodel.tar.gzファイルは作成済みの所から始めていきます。

1. Notebookインスタンスの.ipynbファイルでコードを記載

1.1. 必要なライブラリーをインポート
hogehoge.ipynb
from datetime import datetime
import os

import numpy as np
import pandas as pd

import boto3
import sagemaker
1.2. 初期変数を設定
hogehoge.ipynb
ROLE = sagemaker.get_execution_role()
SAGEMAKER_SESSION = sagemaker.Session()
S3_BUCKET = SAGEMAKER_SESSION.default_bucket()
S3_PREFIX = "data-for-machine-learning/for_sagemaker_algorithm_XGBoost"
TEST_DATA_PATH = "test/input_test_data.csv"
1.3. テスト(test)ファイルを取得

Nishikaのコンペサイトからダウンロードして、Notebookインスタンスのローカルにアップロードしていたtest.csvファイルを、DataFrameとして変数test_dfに保存します。

hogehoge.ipynb
test_df = pd.read_csv(filepath_or_buffer="data/Nishika_ApartmentPrice/test.csv",
                      converters={"面積(㎡)": str},
                      encoding="utf-8")
1.4. テスト(test)データを前処理

こちらの記事の5.10.と同様の形で、テスト(test)データを前処理します。

hogehoge.ipynb
test_feature_df = test_df[["市区町村コード", "最寄駅:距離(分)", "面積(㎡)", "建ぺい率(%)", "容積率(%)"]].dropna(how="any").copy()
test_feature_df["面積(㎡)"] = test_feature_df["面積(㎡)"].apply(lambda x: "2000" if x == "2000㎡以上" else x)
test_feature_df["面積(㎡)"] = test_feature_df["面積(㎡)"].astype("int")
test_feature_df["最寄駅:距離(分)"] = test_feature_df["最寄駅:距離(分)"].apply(lambda x: "45" if x == "30分?60分" else "75" if x == "1H?1H30" else "105" if x == "1H30?2H" else "120" if x == "2H?" else x)
test_feature_df["最寄駅:距離(分)"] = test_feature_df["最寄駅:距離(分)"].astype("int")
test_feature_df["建ぺい率(%)"] = test_feature_df["建ぺい率(%)"].astype("int")
test_feature_df["容積率(%)"] = test_feature_df["容積率(%)"].astype("int")
print(test_feature_df)
       市区町村コード  最寄駅:距離(分)  面積(㎡)  建ぺい率(%)  容積率(%)
0         1101         26     75       40      60
1         1101          1     55       80     600
2         1101          2     15       80     400
3         1101          2     45       80     400
4         1101          3     20       80     400
...        ...        ...    ...      ...     ...
19453    47201         16     75       60     200
19454    47201         16     15       60     200
19456    47201         11     65       60     200
19457    47208         45     60       60     200
19458    47208          6     55       60     150

[19032 rows x 5 columns]
1.5. 前処理したテスト(test)データをCSVファイルにしてS3へアップロード

まずは、前処理したDataFrameの変数test_feature_dfを、NotebookインスタンスのローカルにCSVファイルとして保存します。
その際に、組み込みアルゴリズムXGBoostはヘッダー(カラム名)を不要なので、このタイミングで外します。

hogehoge.ipynb
test_feature_df.to_csv("./data/Nishika_ApartmentPrice/input_test_data.csv",
                       header=False,
                       index=False)

続いて、Notebookインスタンスのローカルに保存したCSVファイルを、S3にアップロードします。

hogehoge.ipynb
test_data_file_path = os.path.join(S3_PREFIX, TEST_DATA_PATH)
boto3.Session().resource("s3").Bucket(S3_BUCKET).Object(test_data_file_path).upload_file("./data/Nishika_ApartmentPrice/input_test_data.csv")

マネジメントコンソールで確認すると、キチンとS3にアップロードされています。
キャプチャ1.PNG

1.6. 学習後XGBoostモデルのオブジェクトを作成

まずは、AWS側で用意している、組み込みアルゴリズムXGBoostモデルのDockerコンテナのURIを取得します。

hogehoge.ipynb
xgboost_container = sagemaker.image_uris.retrieve(framework="xgboost",
                                                  region="ap-northeast-1",
                                                  version="1.5-1")
print(xgboost_container)
354813040037.dkr.ecr.ap-northeast-1.amazonaws.com/sagemaker-xgboost:1.5-1

続いて、作成済みの学習後XGBoostモデルのファイルであるmodel.tar.gzファイルを使って、学習後XGBoostモデルのオブジェクトを作成します。

hogehoge.ipynb
s3_xgboost_folder_path = "s3://" + os.path.join(S3_BUCKET, S3_PREFIX)
best_training_job_name = "test-20246274039-008-ab936e1f"
trained_xgboost_model = sagemaker.model.Model(image_uri=xgboost_container,
                                              model_data="{a}/{b}/output/model.tar.gz".format(a=s3_xgboost_folder_path,
                                                                                              b=best_training_job_name),
                                              role=ROLE,
                                              predictor_cls=sagemaker.predictor.RealTimePredictor)
print(type(trained_xgboost_model))
<class 'sagemaker.model.Model'>

設定している引数に関しては、こちらの記事に記載しました。

1.7. バッチ変換のオブジェクトを作成

学習済みXGBoostモデルのオブジェクトで、transformerクラスを使って、バッチ変換のオブジェクトを作成します。
transformerクラスの引数の一覧はこちらになります。

hogehoge.ipynb
trained_xgboost_batch_transform = trained_xgboost_model.transformer(instance_count=1,
                                                                    instance_type="ml.m5.large",
                                                                    strategy="MultiRecord",
                                                                    assemble_with="Line",
                                                                    output_path="{a}/test/result".format(a=s3_xgboost_folder_path),
                                                                    max_payload=1)
print(type(trained_xgboost_batch_transform))
<class 'sagemaker.transformer.Transformer'>

今回は下記の引数を設定しました。
instance_count
 バッチ変換のジョブを走らせるインスタンスの個数
instance_type
 バッチ変換のジョブを走らせるインスタンスの種類
 インスタンス毎の価格は

strategy
 バッチ変換のジョブへの入力データを、1レコードずつ投げるか、複数レコードずつ投げるか
 SingleRecordかMultiRecordを設定
assemble_with
 バッチ変換のジョブからの出力データで、レコードを1行ずつ分けるか、分けないか
 LineかNoneを設定
output_path
 バッチ変換のジョブからの出力データを、S3のどこに保存するか
 フォルダ名を設定
max_payload
 バッチ変換のジョブへ入力データとしてレコードを投げる際のリクエストサイズを、何MBにするか
 0~100の整数型で設定

1.8. バッチ変換のジョブを実施して、アパート価格を予測(推論)

作成したバッチ変換のオブジェクトで、transformメソッドを行って、バッチ変換のジョブを実施します。
transformメソッドの引数の一覧はこちらになります。

hogehoge.ipynb
now = datetime.now()
year = str(now.year)
month = str(now.month)
day = str(now.day)
hour = str(now.hour)
minute = str(now.minute)
second = str(now.second)
job_timestamp = year + month + day + hour + minute + second
batch_transform_job_name = "test-{a}".format(a=job_timestamp)
trained_xgboost_batch_transform.transform(data="{a}/test/input_test_data.csv".format(a=s3_xgboost_folder_path),
                                          data_type="S3Prefix",
                                          content_type="text/csv",
                                          split_type="Line",
                                          job_name=batch_transform_job_name,
                                          wait=True,
                                          logs=True)
.................................../miniconda3/lib/python3.8/site-packages/xgboost/compat.py:36: FutureWarning: pandas.Int64Index is deprecated and will be removed from pandas in a future version. Use pandas.Index with the appropriate dtype instead.

今回は下記の引数を設定しました。
data
 バッチ変換のジョブへの入力データとなるファイルのS3パス
data_type
 バッチ変換のジョブへの入力データとなるファイルがS3にあるならばS3Prefixを設定
 おそらく、S3以外の場合はManifestFileを設定
content_type
 バッチ変換のジョブへの入力データとなるファイルのタイプ
 今回はCSVファイルなので、text/csvを設定
split_type
 バッチ変換のジョブへの入力データとなるファイルは、1レコード毎をどのように区切っているか
 今回は1行毎に1レコードなので、Lineを設定
job_name
 バッチ変換のジョブの名前を設定
wait
 バッチ変換のジョブが完了するまで待つかどうか
logs
 バッチ変換のジョブに関するメッセージを表示するかどうか

様々なメッセージが表示された後、バッチ変換のジョブが実施されて、無事に完了しました。
マネジメントコンソールのSageMakerの「推論 > バッチ変換ジョブ」でも完了を確認出来ました。
キャプチャ2.PNG

2. 予測(推論)結果を確認

学習済みXGBoostモデルのオブジェクトで、transformerクラスを使って、バッチ変換のオブジェクトを作る際に、引数output_pathで指定したS3のフォルダに、バッチ変換のジョブでの出力ファイルが保存されています。
(ファイル名は、入力データのファイル名に.outを付与したものになります。)

キャプチャ3.PNG

このファイルをダウンロードして、Notebookインスタンスのローカルにアップロードして、中身を確認してみると、

hogehoge.ipynb
test_result_df = pd.read_csv(filepath_or_buffer="./data/Nishika_ApartmentPrice/input_test_data.csv.out",
                             header=None,
                             names=["result"],
                             encoding="utf-8")
print(test_result_df)
         result
0      7.107569
1      7.272198
2      6.398515
3      6.810840
4      6.300151
...         ...
19027  7.279865
19028  6.331160
19029  7.168963
19030  7.256274
19031  7.215110

[19032 rows x 1 columns]

テスト(test)データに対する、19032個のアパート価格の予測(推論)結果になります。

以上になります。

まとめ

学習済みXGBoostモデルをデプロイしてエンドポイントを作成せず、バッチ変換のジョブを行う事で、学習済みXGBoostモデルでの推論を行う事が出来ました。
個人的には、こちらの形で推論を行う方が好きかもです(笑)

参考

0
0
0

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
  3. You can use dark theme
What you can do with signing up
0
0