Amazon SageMaker 入門: 組み込みアルゴリズムを使う

Amazon SageMaker 入門: 組み込みアルゴリズムを使う

SageMaker Studioと組み込みアルゴリズムを使って、Irisデータセットでk-NN分類器を学習・デプロイします。

Takahiro Iwasa
10 min read

機械学習向けの統合開発環境であるSageMaker Studioを使って、SageMakerの組み込みK近傍法(k-NN)アルゴリズムを、広く使われているIrisデータセットに適用する方法を説明します。

SageMakerのオンボーディング

まず、SageMaker Studioのオンボーディングプロセスを完了する必要があります。

Quick SetupCustom Setupからセットアップ方法を選択します。

VPCを選択します。

自動的に作成されたユーザーのメニューから、SageMaker Studioを起動します。

起動すると、SageMaker Studioが表示されます。

SageMaker Studio中央のNotebookボタンをクリックします。

前処理

データセットの準備

まず環境変数を設定します。

以下を実際の値に置き換えてください。

  • <YOUR_S3_BUCKET>
  • <YOUR_SAGEMAKER_ROLE>
Terminal window
%env S3_DATASET_BUCKET=<YOUR_S3_BUCKET>
%env S3_DATASET_TRAIN=knn/input/iris_train.csv
%env S3_DATASET_TEST=knn/input/iris_test.csv
%env S3_TRAIN_OUTPUT=knn/output
%env SAGEMAKER_ROLE=<YOUR_SAGEMAKER_ROLE>

次に、以下のPythonのimport文を含むセルを作成します。Python3 Data Scienceインスタンスには、これらのライブラリがあらかじめインストールされています。

import os
import random
import string
import boto3
import matplotlib.pyplot as plt
import pandas as pd
import sagemaker
from IPython.display import display
from sagemaker import image_uris
from sagemaker.deserializers import JSONDeserializer
from sagemaker.estimator import Estimator, Predictor
from sagemaker.inputs import TrainingInput
from sagemaker.serializers import CSVSerializer
from sklearn.model_selection import train_test_split

定数と変数を定義します。

# Define constants
CSV_PATH = './tmp/iris.csv'
S3_DATASET_BUCKET = os.getenv('S3_DATASET_BUCKET')
S3_DATASET_TRAIN = os.getenv('S3_DATASET_TRAIN')
S3_DATASET_TEST = os.getenv('S3_DATASET_TEST')
S3_TRAIN_OUTPUT = os.getenv('S3_TRAIN_OUTPUT')
SAGEMAKER_ROLE = os.getenv('SAGEMAKER_ROLE')
ESTIMATOR_INSTANCE_COUNT = 1
ESTIMATOR_INSTANCE_TYPE = 'ml.m5.large'
PREDICTOR_INSTANCE_TYPE = 'ml.t2.medium'
PREDICTOR_ENDPOINT_NAME = f'sagemaker-knn-{PREDICTOR_INSTANCE_TYPE}'.replace('.', '-')
# Define variables
bucket = boto3.resource('s3').Bucket(S3_DATASET_BUCKET)
train_df = None
test_df = None
train_object_path = None
test_object_path = None
knn = None
predictor = None

AWSのSageMaker ExamplesリポジトリからIrisデータセットをダウンロードします。このデータセットは、そのシンプルさと明確に定義された構造から、分類モデルのデモンストレーションに広く使われています。Irisデータセットの属性や用途など詳細については、公式ページを参照してください。

Terminal window
!mkdir -p tmp
!curl -o "$(pwd)/tmp/iris.csv" -L https://raw.githubusercontent.com/aws/amazon-sagemaker-examples/master/hyperparameter_tuning/r_bring_your_own/iris.csv

ダウンロード後、以下のコードでCSVを読み込み、前処理を行います。この関数は、Irisデータセットを組み込みアルゴリズムでの学習に使えるよう、SageMakerの要件に合わせて処理します。

詳細はSageMakerのドキュメントを参照してください。

def load_csv(path: str) -> pd.DataFrame:
# Load the CSV into a Pandas DataFrame
df = pd.read_csv(path)
# Move the label column ('Species') to the first position
df = df[['Species', 'Sepal.Length', 'Sepal.Width', 'Petal.Length', 'Petal.Width']]
# Convert target labels ('Species') to integers
df['Species'] = df['Species'].map({'setosa': 0, 'versicolor': 1, 'virginica': 2})
return df
🔥 Caution

  • SageMakerではCSVの最初の列がターゲットラベル(クラス)である必要があるため、Species列を先頭に移動する必要があります。
  • ターゲットラベル(品種名)も、互換性のために整数へ変換する必要があります。

データセットの可視化

データセットの特徴量と分布を把握するため、散布図を作成します。

def plot(df: pd.DataFrame) -> None:
pd.plotting.scatter_matrix(df, figsize=(15, 15), c=df['Species'])
plt.show()

生成された散布図の軸は次のように対応しています。

  • X軸
    • 左から右に向かってSpeciesSepal.LengthSepal.WidthPetal.LengthPetal.Widthを表します。
  • Y軸
    • 下から上に向かってPetal.WidthPetal.LengthSepal.WidthSepal.LengthSpeciesを表します。

プロットを見ると、データポイントがはっきりとしたグループに分かれて分類されていることから、特徴量から品種を予測できることが読み取れます。

データセットのS3へのアップロード

前処理済みのデータセットをS3にアップロードします。

def upload_csv_to_s3(df: pd.DataFrame, object_path: str) -> str:
filename = ''.join([random.choice(string.digits + string.ascii_lowercase) for i in range(10)])
path = os.path.abspath(os.path.join('./tmp', filename))
df.to_csv(path, header=False, index=False)
# Change content-type because the default is binary/octet-stream
bucket.upload_file(path, object_path, ExtraArgs={'ContentType': 'text/csv'})
return f's3://{bucket.name}/{object_path}'

前処理の実行

上記の前処理を完了するには、以下を実行します。

if __name__ == '__main__':
df = load_csv(CSV_PATH)
display(df)
plot(df)
train_df, test_df = train_test_split(df, shuffle=True, random_state=0)
train_object_path = upload_csv_to_s3(train_df, S3_DATASET_TRAIN)
test_object_path = upload_csv_to_s3(test_df, S3_DATASET_TEST)

学習

k-NN推定器を設定し、学習プロセスを開始します。

def get_estimator(**hyperparams) -> Estimator:
estimator = Estimator(
image_uri=image_uris.retrieve('knn', boto3.Session().region_name),
role=SAGEMAKER_ROLE,
instance_count=ESTIMATOR_INSTANCE_COUNT,
instance_type=ESTIMATOR_INSTANCE_TYPE,
input_mode='Pipe',
output_path=f's3://{S3_DATASET_BUCKET}/{S3_TRAIN_OUTPUT}',
sagemaker_session=sagemaker.Session(),
)
hyperparams.update({'predictor_type': 'classifier'})
estimator.set_hyperparameters(**hyperparams)
return estimator
def train(estimator: Estimator, train_object_path: str, test_object_path: str) -> None:
train_input = TrainingInput(train_object_path, content_type='text/csv', input_mode='Pipe')
test_input = TrainingInput(test_object_path, content_type='text/csv', input_mode='Pipe')
estimator.fit({'train': train_input, 'test': test_input})
if __name__ == '__main__':
knn = get_estimator(k=1, sample_size=1000)
train(knn, train_object_path, test_object_path)

学習ジョブを開始すると、以下のようなログが表示されます。

2022-01-08 13:38:34 Starting - Starting the training job...
2022-01-08 13:38:57 Starting - Launching requested ML instancesProfilerReport-1641649113: InProgress
......
[01/08/2022 13:43:00 INFO 140667182901056] #test_score (algo-1) : ('accuracy', 0.9736842105263158)
[01/08/2022 13:43:00 INFO 140667182901056] #test_score (algo-1) : ('macro_f_1.000', 0.97170347)
  • ログにはaccuracy(精度)macro F1 scoreといった指標が含まれており、テストデータセットに対するモデルの性能を把握できます。
  • 学習時にtraintestの両方のチャンネルを活用することで、組み込みアルゴリズムが自動的にモデルの汎化性能を評価します。

ECR URI

image_uri(3行目)は、AWSが提供するk-NN学習アルゴリズムのECRコンテナURIを指定しています。

組み込みアルゴリズムのコンテナURIに関する詳細情報は、公式ドキュメントを参照してください。

チャンネル名

SageMakerの組み込みアルゴリズムでは、チャンネル名(18行目)はtrainに固定されています。学習ジョブの作成時にtestチャンネルを含めると、学習後に自動的にテストデータでMLモデルが評価されます。

Pipeモードの使用

データストリーミングの効率を高めるには、TrainingInput定義のinput_mode(7行目)パラメータを"Pipe"に設定することで、Pipeモードを有効化できます。Pipeモードは、S3からSageMakerインスタンスへデータを直接ストリーミングするため、データセット全体をダウンロードする場合と比べてレイテンシとメモリ要件を削減できます。

k-NNのハイパーパラメータ

k-NNアルゴリズムには、設定可能なハイパーパラメータがいくつか用意されています。使い方や効果の詳細については、公式ドキュメントを参照してください。

推論

学習済みモデルをエンドポイントにデプロイし、予測結果を検証します。

SageMakerのserializerdeserializerは、デプロイされた推論エンドポイントとやり取りする際の、入出力データの形式を指定するために使われます。

  • Serializer
    • CSVSerializer: データをCSV形式に変換します。
    • JSONSerializer: データをJSON形式に変換します。
    • NumpySerializer: NumPy配列をバイナリ形式に変換します。
  • Deserializer
    • JSONDeserializer: JSONレスポンスをPythonの辞書やリストに変換します。
    • BytesDeserializer: 生のバイト列をそのまま返します。
def deploy(estimator: Estimator) -> Predictor:
return estimator.deploy(
initial_instance_count=1,
instance_type=PREDICTOR_INSTANCE_TYPE,
serializer=CSVSerializer(),
deserializer=JSONDeserializer(),
endpoint_name=PREDICTOR_ENDPOINT_NAME,
)
def validate(predictor: Predictor, test_df: pd.DataFrame) -> pd.DataFrame:
rows = []
for _, data in test_df.iterrows():
predict = predictor.predict(
pd.DataFrame([data.drop('Species')]).to_csv(header=False, index=False),
initial_args={'ContentType': 'text/csv'},
)
predicted_label = predict['predictions'][0]['predicted_label']
row = data.tolist()
row.append(predicted_label)
row.append(data['Species'] == predicted_label)
rows.append(row)
return pd.DataFrame(rows, columns=('Species', 'Sepal.Length', 'Sepal.Width', 'Petal.Length', 'Petal.Width', 'Prediction', 'Result'))
if __name__ == '__main__':
predictor = deploy(knn)
predictions = validate(predictor, test_df)
display(predictions)

推論結果には、Prediction列とResult列が含まれます。

  • Prediction: モデルに与えられた各サンプルに対する予測ラベルです。
  • Result: 予測結果が実際のラベルと一致するかどうかを示すブール値(TrueまたはFalse)です。

後片付け

学習済みモデルとそのエンドポイントは、以下で削除できます。

def delete_model(predictor: Predictor) -> None:
predictor.delete_model()
def delete_endpoint(predictor: Predictor) -> None:
predictor.delete_endpoint(delete_endpoint_config=True)
if __name__ == '__main__':
delete_model(predictor)
delete_endpoint(predictor)

まとめ

SageMaker StudioでIrisデータセットを使ってk-NN分類器を学習・デプロイしたところ、学習スクリプトやコンテナを自作することなく、動作する推論エンドポイントを構築できました。ここで役立っているのは、image_uris.retrieve('knn', ...)による学習用イメージの取得と、input_mode='Pipe'の設定です。Pipeモードにより、データセット全体を先にダウンロードするのではなく、S3のCSVデータをインスタンスへ直接ストリーミングできます。estimator.fit()traintestの両方のチャンネルを渡すことで、SageMakerによる自動評価がトリガーされ、追加の検証コードなしに学習ログに現れるaccuracymacro_f_1.000といった指標が得られます。ここで得られた97%という精度は、Irisの各品種がすでに特徴量空間の中できれいに分離されていることを反映したものです。データセットの難易度に関わらず、デプロイしたエンドポイントは稼働している間ずっと時間単位で課金され続けるため、使い終わったら忘れずに削除しておく価値があります。

About the author

Takahiro Iwasa

Takahiro Iwasa

Software Developer

This blog shares technical notes from hands-on projects—architecture, implementation, and AWS service integrations.