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 = NoneAmazon SageMaker Examples リポジトリから 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 を読み込み、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 の AWS サービス統合から 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 にデプロイする
FastAPI で書いた API バックエンドをコンテナ化し、Lambda Web Adapter と AWS CDK を使って単一の Lambda 関数へデプロイします。
API Gateway WebSocket:モック統合の実装
バックエンドの Lambda を使わず、モック統合のみで API Gateway WebSocket API を構築し、あらかじめ用意したレスポンスを返します。
