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

Amazon SageMaker Examples リポジトリから 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 を読み込み、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.