Amazon SageMaker 入門: 組み込みアルゴリズムを使う
SageMaker Studioと組み込みアルゴリズムを使って、Irisデータセットでk-NN分類器を学習・デプロイします。
機械学習向けの統合開発環境であるSageMaker Studioを使って、SageMakerの組み込みK近傍法(k-NN)アルゴリズムを、広く使われているIrisデータセットに適用する方法を説明します。
SageMakerのオンボーディング
まず、SageMaker Studioのオンボーディングプロセスを完了する必要があります。
Quick SetupとCustom Setupからセットアップ方法を選択します。

VPCを選択します。

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

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

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

前処理
データセットの準備
まず環境変数を設定します。
以下を実際の値に置き換えてください。
<YOUR_S3_BUCKET><YOUR_SAGEMAKER_ROLE>
%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 osimport randomimport string
import boto3import matplotlib.pyplot as pltimport pandas as pdimport sagemakerfrom IPython.display import displayfrom sagemaker import image_urisfrom sagemaker.deserializers import JSONDeserializerfrom sagemaker.estimator import Estimator, Predictorfrom sagemaker.inputs import TrainingInputfrom sagemaker.serializers import CSVSerializerfrom sklearn.model_selection import train_test_split定数と変数を定義します。
# Define constantsCSV_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 = 1ESTIMATOR_INSTANCE_TYPE = 'ml.m5.large'PREDICTOR_INSTANCE_TYPE = 'ml.t2.medium'PREDICTOR_ENDPOINT_NAME = f'sagemaker-knn-{PREDICTOR_INSTANCE_TYPE}'.replace('.', '-')
# Define variablesbucket = boto3.resource('s3').Bucket(S3_DATASET_BUCKET)train_df = Nonetest_df = Nonetrain_object_path = Nonetest_object_path = Noneknn = Nonepredictor = NoneAWSのSageMaker ExamplesリポジトリからIrisデータセットをダウンロードします。このデータセットは、そのシンプルさと明確に定義された構造から、分類モデルのデモンストレーションに広く使われています。Irisデータセットの属性や用途など詳細については、公式ページを参照してください。
!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- SageMakerではCSVの最初の列がターゲットラベル(クラス)である必要があるため、
Species列を先頭に移動する必要があります。 - ターゲットラベル(品種名)も、互換性のために整数へ変換する必要があります。
データセットの可視化
データセットの特徴量と分布を把握するため、散布図を作成します。
def plot(df: pd.DataFrame) -> None: pd.plotting.scatter_matrix(df, figsize=(15, 15), c=df['Species']) plt.show()
生成された散布図の軸は次のように対応しています。
- X軸
- 左から右に向かって
Species、Sepal.Length、Sepal.Width、Petal.Length、Petal.Widthを表します。
- 左から右に向かって
- Y軸
- 下から上に向かって
Petal.Width、Petal.Length、Sepal.Width、Sepal.Length、Speciesを表します。
- 下から上に向かって
プロットを見ると、データポイントがはっきりとしたグループに分かれて分類されていることから、特徴量から品種を予測できることが読み取れます。
データセットの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といった指標が含まれており、テストデータセットに対するモデルの性能を把握できます。
- 学習時に
trainとtestの両方のチャンネルを活用することで、組み込みアルゴリズムが自動的にモデルの汎化性能を評価します。
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のserializerとdeserializerは、デプロイされた推論エンドポイントとやり取りする際の、入出力データの形式を指定するために使われます。
- 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()にtrainとtestの両方のチャンネルを渡すことで、SageMakerによる自動評価がトリガーされ、追加の検証コードなしに学習ログに現れるaccuracyやmacro_f_1.000といった指標が得られます。ここで得られた97%という精度は、Irisの各品種がすでに特徴量空間の中できれいに分離されていることを反映したものです。データセットの難易度に関わらず、デプロイしたエンドポイントは稼働している間ずっと時間単位で課金され続けるため、使い終わったら忘れずに削除しておく価値があります。
Related posts
SageMakerの物体検出によるオブジェクトカウント
Ground Truthで画像にラベルを付け、SageMakerの物体検出モデルを学習させ、推論結果からオブジェクトをカウントする。
LambdaなしでAPI GatewayからSageMakerを呼び出す
API Gatewayの統合リクエストをSageMaker推論エンドポイントに直接接続し、リクエストパスからLambda関数を完全に排除する。
Cognito User PoolsとOIDCでSlackサインインを実装する
Cognito user poolをOIDC経由でSlackと連携させ、"Sign in with Slack"をAmplifyでNext.jsアプリに組み込みます。
Lambda Web AdapterでFastAPIをAWS Lambdaにデプロイする
Lambda Web Adapterを使うと、FastAPIで書いたAPIバックエンドをコンテナのまま単一のLambda関数にデプロイできます。
API Gateway WebSocket:モック統合の実装
バックエンドのLambdaを一切使わず、モック統合のみでAPI Gateway WebSocket APIを構築し、あらかじめ用意されたレスポンスを返します。
