0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【後編】機械学習って何をしてるの?SageMakerで流れをまるごと体験!

0
Posted at

機械学習って何をしてるの?SageMakerで流れをまるごと体験!_eyecatch.png

後編では、前編で準備した環境・データを使用してデータの前処理(クレンジング)、モデルの学習、学習させたモデルを使用して実際にテストデータとして用意した顧客が成約するかどうかを予測するといった機械学習のメイン部分を説明していきます。
また、最後には不要な料金を発生させないためのクリーンアップ手順も説明していますので忘れずに実施してください。

SageMakerの概要、ならびにハンズオンの概要については前編をご覧ください。
前編はこちら:【前編】機械学習って何をしてるの?SageMakerで流れをまるごと体験

前編の振り返り

前編ではSageMaker Unified Studioを立ち上げ、銀行のデータセットを準備しました。後編では、いよいよ「学習」と「予測」を行います。

fig-01_hands-on-architecture-1.png

後編では、以下のステップで進めていきます。

【後編】

  1. データの前処理・S3アップロード: データを学習できる形に変換し、S3に保存します。
  2. モデルの学習: XGBoostアルゴリズムを使って学習ジョブを実行します。
  3. 予測とデプロイ: エンドポイントを作成し、実際に予測を試します。
  4. リソースの削除: 課金を止めるため、作成したものをすべて削除します。

ハンズオンの手順

データの前処理・S3アップロード

まず、前編で取得したデータを前処理してS3に保存します。

このステップでは、具体的に以下を行います。

  1. 目的変数の数値化: 機械学習アルゴリズムは文字列をそのまま扱えないため、予測したい列 y(定期預金の成約有無)を 'yes' → 1、'no' → 0 の数値に変換します。
  2. カテゴリ変数のエンコード: 職業や婚姻状況など文字列のカラムを、One-hot encoding(0/1の数値列)に変換します。単純に番号を振ると、モデルが「管理職=2 > 技術者=1」のように数値の差を意味のある情報として学習してしまうため、予測精度に影響します。One-hot encodingで「管理職である(1 or 0)」「技術者である(1 or 0)」のようにカテゴリごとに独立した列として表現します。
  3. 学習用・テスト用データの分割: test_size=0.2 を指定してテストデータを20%確保し、残り80%を学習に使います。学習に使っていないデータで評価することで、モデルが「未知のデータ」にどれだけ対応できるかを正しく測ります。
  4. XGBoost形式への整形: SageMakerのXGBoostコンテナが「目的変数を先頭列に配置したCSV」を入力形式として要求するため、列を並び替えます。
  5. S3へのアップロード: Training Jobsはノートブックとは別のサーバーで動作するため、S3を経由してデータを渡す必要があります。アップロード用のS3バケットは自動作成されます。

では、前編の実施内容に続き、ノートブックにて ※ 新規セル を追加して以下のコードを実施してみましょう!

※新規セルの追加については前編の「4-2-2. 取得したデータの確認」の実施内容を参考にしてください。

import sagemaker
import pandas as pd
from sklearn.model_selection import train_test_split
from sagemaker import get_execution_role
# セッションとロールの取得
session = sagemaker.Session()
role = get_execution_role()
bucket = session.default_bucket()  # 自動作成されます
prefix = 'bank-marketing'
# 目的変数を 1/0 に変換('yes' → 1、'no' → 0)
df['y'] = (df['y'] == 'yes').astype(int)
# カテゴリ変数をOne-hot encodingで数値化
df_encoded = pd.get_dummies(df)
# 特徴量と目的変数を分割
X = df_encoded.drop('y', axis=1)
y = df_encoded['y']
# 学習用・テスト用データに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# XGBoostは目的変数を先頭列に要求するため、結合して並べ替え
train_data = pd.concat([y_train.reset_index(drop=True), X_train.reset_index(drop=True)], axis=1)
test_data_df = pd.concat([y_test.reset_index(drop=True), X_test.reset_index(drop=True)], axis=1)
# CSVとして保存(test.csvは確認用。予測時はメモリ上のX_testを直接使用)
train_data.to_csv('train.csv', index=False, header=False)
test_data_df.to_csv('test.csv', index=False, header=False)
# S3へアップロード
train_s3 = session.upload_data('train.csv', bucket=bucket, key_prefix=f'{prefix}/train')
print(f'学習データをアップロード: {train_s3}')

モデルの学習

今回は、表形式データの解析に非常に強力な「XGBoost」というアルゴリズムを使用します。SageMakerの「Estimator」を定義して学習ジョブをノートブックの新規セルにて実行します。

ここから課金が本格化するので注意です! 学習が終わったらすぐに次のステップへ進みましょう。

【筆者のメモ】

Training Jobs(学習ジョブ)は、SageMakerが別途サーバーを起動して実行します。このサーバーには ml.m5.xlarge などのM/C系インスタンスが指定でき、ノートブック用の ml.t3.medium は使用できません。インスタンスはジョブ実行時にAWSが自動で起動・終了するため、事前の作成は不要です。なお、インスタンスタイプによって料金が異なり、ml.m5.xlarge はXGBoostの学習ジョブに使用できる最小クラスのインスタンスです。

from sagemaker.inputs import TrainingInput
# XGBoostコンテナイメージの取得
container = sagemaker.image_uris.retrieve('xgboost', session.boto_region_name, version='1.7-1')
# Estimatorの定義(Training Jobsにはm/c系インスタンスを使用)
estimator = sagemaker.estimator.Estimator(
    image_uri=container,
    role=role,
    instance_count=1,
    instance_type='ml.m5.xlarge',
    output_path=f's3://{bucket}/{prefix}/output',
    sagemaker_session=session
)
# ハイパーパラメータの設定
estimator.set_hyperparameters(
    max_depth=5,
    eta=0.2,
    gamma=4,
    min_child_weight=6,
    subsample=0.8,
    objective='binary:logistic',
    num_round=100
)
# 学習の実行 ※実行完了には数分かかります
train_input = TrainingInput(train_s3, content_type='text/csv')
estimator.fit({'train': train_input})
print('学習完了!')

実行すると、SageMakerが別途インスタンス(ml.m5.xlarge)を起動してXGBoostのコンテナイメージをダウンロードし、学習を開始します。ログには各ラウンドの損失関数(train-logloss)が表示されます。

今回は100ラウンド回した結果、loglossが 0.55 → 0.15 まで下がり、モデルがデータのパターンを学習できていることが確認できました。学習完了後、モデルのアーティファクトは自動的にS3へ保存されます。今回の課金対象時間は110秒でした。

【筆者のメモ】

logloss(対数損失)は予測の「外れ具合」を表す指標で、値が小さいほど精度が高いことを意味します。1ラウンド目は 0.55 でしたが、ラウンドを重ねるごとに減少し、100ラウンド目では 0.15 まで改善されました。

予測とデプロイ

前編の「3-3. 各サービスの役割」で紹介した通り、Training Jobsは「完了後、学習済みモデルのファイルをS3へ自動保存する」役割でした。つまりこの時点では、モデルはS3上のファイルとして存在しているだけで、予測リクエストを受け付けることはできません。

そこで必要になるのがデプロイです。デプロイを行うと Endpoint(推論サーバー) が起動し、「学習済みモデルをAPIとして公開し、新規データへの予測リクエストを受け付ける」状態になります。これでようやく実際にデータを渡して予測結果を受け取れるようになります。

【筆者のメモ】

エンドポイント(推論サーバー)のインスタンスは、Training Jobsとは異なり ml.t2.medium が使用できます。ただし起動したままにすると課金が続くため、予測確認が終わったらすぐに削除しましょう。

from sagemaker.serializers import CSVSerializer
# モデルをデプロイしてエンドポイントを作成(Endpointはt2.mediumでOK)
predictor = estimator.deploy(
    initial_instance_count=1,
    instance_type='ml.t2.medium',
    serializer=CSVSerializer()
)
# テストデータから特徴量のみ取り出して1件分を予測(bool列をfloatに変換しないとエラーになるので注意)
test_features = X_test.astype(float).values[:1]
test_csv = ','.join(map(str, test_features[0]))
result = predictor.predict(test_csv)
print(f'予測結果: {result}')
予測結果: b'0.011883473955094814\n'

先頭の b'...' はPythonのbytes型を表す表記で、実際の値は 0.011883... です。0.5より小さいので「定期預金を成約しない可能性が高い」と判断されたことになります!

実際に数字が返ってくると「AIが判断した!」という実感が湧きます。結果が0〜1の数値で返ってくる場合、一般的には0.5(= 50%)を基準(しきい値)にして「成約するかどうか」を判定させます。
では今回実際に予測した顧客を見てみましょう。

fig-05_test_data_1.png

年齢:57歳
職業:技術者
婚姻状況:既婚
学歴:高校卒
ローン:あり
前回キャンペーン結果:失敗

次にこの顧客の成約結果も見てみます。

fig-06_test_data_2.png

yの値が0のため「成約なし」の顧客データであり、モデルの予測結果(約1.2%、しきい値0.5未満のため「成約なし」と判定)と実際の結果が一致していました。

このテストデータは学習には使っておらずモデルにとって未知のデータです。見たことのないデータに対しても正しく判定できたということは、モデルが訓練データをただ丸暗記したのではなく、顧客属性から成約有無の傾向をきちんと汎化して学習できていたことの裏付けになります。

所感

今回のハンズオンを通じて、SageMakerを使った学習・予測の一連の流れを体験しました。 複数の属性を組み合わせて自動で予測結果を出してくれる点に、機械学習の有用性を確認できました!

本来の機械学習フローでは、モデル全体の精度検証(テストデータ全体での正解率の算出など)や、より踏み込んだデータの前処理・確認(EDA)も実施する必要がありますが、本ハンズオンの目的はあくまで機械学習のフローを簡易的に体験することだったため、そこまでは実施していません。
次に挑戦する際には精度検証などにも取り組み、モデルの精度をどこまで改善できるか試してみるのも面白そうと感じました。

また、予測結果についてノートブック上で確認するだけに留めましたが、実務では他のAWSサービスと連携させて使うケースが想定されます。ハンズオンでやったようなEndpointの仕組みは「リクエストを送るとモデルがその場で推論結果を返す」というシンプルなAPIですが、これを外部から使えるようにするにはAmazon API Gateway + AWS Lambda を組み合わせて「クライアント → API Gateway → Lambda → SageMakerエンドポイント」という構成にするのが定番のようです。

AWS公式ブログでも、Call an Amazon SageMaker model endpoint using Amazon API Gateway and AWS Lambda として、先ほど紹介したものと同様の構成が解説されていました。

fig-07_inference_api_diagram.png

SageMakerの活用例を調べてみても本当に多種多様な業種、業界で使われており、今後さらに機械学習の技術は波及していきそうなので、今の時点で少しでもこういった技術に触れておくことが大切だなと感じました。

リソースの削除

「2-3. 予測とデプロイ」までの内容でハンズオンとしては終了になります。

ハンズオンが終わったら、不要な料金が発生しないように以下のリソースを削除(クリーンアップ)してください。

1.エンドポイントの削除 ノートブック上で predictor.delete_endpoint() を実行して推論サーバーを停止します。エンドポイントをサポートするインスタンスも同時に削除されます。

fig-01_endpoint-delete.png

2.モデルの削除

AWSコンソールで「Amazon SageMaker」→「推論」→「モデル」を開き、作成したモデルを選択して「アクション」→「削除」をクリックします。

モデルオブジェクト自体に課金はありませんが、後の手順でS3バケットを削除するとモデルが参照する先のファイルがなくなり、このモデルでデプロイをしようとしてもエラーになるため、合わせて削除しておきましょう。

3.アプリケーションの停止 AWSコンソールで「Amazon SageMaker」→「ドメイン」→ 対象ドメインを選択 →「リソース」タブ →「アプリケーション」セクションから起動中のアプリケーションを選択して「停止」します。画面上部に「〇件のアプリケーションが正常に停止されました」と表示され、一覧が「現在リソースはありません。」となれば完了です。

fig-02_app-stop.png

4.SageMakerドメインの削除(他の演習を続けない場合のみ) 同じ「ドメインの詳細」画面の「ドメインの設定」タブを開き、「ドメインを削除」ボタンをクリックします。確認ダイアログが表示されるので「はい、ドメインを削除します」をクリックし、テキストボックスに 削除 と入力して「削除」ボタンを押します。

fig-03_domain-delete-1.png

fig-04_domain-delete-2.png

5.S3バケットの削除

Amazon S3コンソールを開き、モデルアーティファクトとトレーニングデータセットを保存するために作成したバケットを削除します(他のSageMaker演習を引き続き試す予定がある場合は、コストもそこまでかからないので保管しておいても良いでしょう)。

6.CloudWatchログの削除

Amazon CloudWatchコンソールを開き、名前が /aws/sagemaker/ で始まるロググループをすべて削除します。

課金対象ではないが環境に残るもの

上記の手順を完了しても、以下のリソースはAWS環境に残り続けます。課金は発生しませんが、気になる場合は手動で対応してください。

リソース 残る理由 対応
学習ジョブの実行記録 SageMakerの仕様上、完了済みジョブは削除不可 対応不要(記録のみ。データはS3削除で消える)
IAMロール 前編で作成した SageMakerExecutionRole がそのまま残る IAMコンソールから手動削除可能
Glue Data Catalogのデータベース Unified Studio(DataZone)がカタログ連携用に自動作成 AWS Glueコンソール →「データベース」から手動削除可能

【筆者のメモ】

「ブラウザを閉じれば終わり」と勘違いしがちですが、AWS側ではインスタンスが動き続けています!ノートブックの画面にあるごみ箱アイコンはファイルの削除のみで、インスタンスは止まりません。 ドメイン詳細の「リソース」タブでアプリケーションが消えたことを必ず確認しましょう。
なお、SageMakerのドメイン一覧画面には「IAMベースのドメインを使用する」という別のアクセス方法が表示されますが、こちらからノートブックを起動してしまうと課金が発生します。今後使わない場合は「Actions」ボタンから削除するか、誤って開かないよう注意しましょう。

おわりに

お疲れ様でした!
今回はコンソールとノートブックを併用しましたが、これを自動化(IaC:Infrastructure as Code)したり、さらに精度を高めるチューニングをしたりと、工夫していくことでさらに活用の幅が広がっていきそうです。 また、今回はコードを書く方法を紹介しましたが、前編の機能紹介で軽く触れた「SageMaker Canvas」というノーコードツールを使えば、さらに手軽に予測を試すことも可能です。

私自身もSageMakerに今回初めて触れてみましたが、とても可能性を秘めたサービスだがまだまだ全貌は見えないな、、というのが正直な感想です。 今後も機械学習・AI関連のサービスをキャッチアップしてブログで発信していきますので、ぜひ一緒に学んでいきましょう!

この記事が、あなたの機械学習活用の第一歩になれば幸いです!

We Are Hiring!

今回、私は自身の知的好奇心からSageMakerを使った機械学習ハンズオンに取り組んでみましたが、データの前処理・モデルの学習・予測まで一連のステップを体験してみると、「もっとこの領域を深掘りしてスキルを積み上げていきたい」と感じた方もいるのではないでしょうか。

FindConsultingでは、入社後も継続的に学べる充実した研修制度を整えています。 座学・ハンズオン形式の技術研修から、研修の中でAWS最難関資格までの資格取得支援まで、成長をしっかりバックアップする環境があります。 「技術を学び続けたい」「仕事を通じてスキルアップしたい」と感じているエンジニアの方、ぜひ一緒に成長しませんか?

現在、FindConsultingでは学ぶ意欲のある仲間を募集しています。 まずはカジュアル面談からでも、ぜひお気軽にお声がけください!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?