Amazonの新しい機械学習プラットフォーム「Amazon SageMaker(アマゾン・セージメーカー)」ですが、早速、機械学習初心者向けのハンズオンチュートリアル第一弾をまとめました!オンラインで公開されている銀行顧客のデータを利用して、Amazon SageMaker+XGBoostを使って、データの前処理からモデルホスティング、さらに評価確認までを一緒に行ってみましょう。
SageMaker入門チュートリアル概要
所要時間目安
1時間〜3時間
実行する内容
- SageMakerノートブックインスタンスの立ち上げ
- データの処理
- SageMaker XGBoostのモデル訓練
- モデルのホスティング
- テストデータをホスティングされたモデルで予測計算
- モデルの評価
参考
https://bank-tutorial.notebook.us-east-1.sagemaker.aws/notebooks/bank-tutorial-1.ipynb
この記事の目次
Amazon SageMakerの登録
まずはAmazon SageMakerへの登録を行いましょう。SageMakerの発表記事でも記載をしましたが、現段階で使えるリージョンはまだ4つのみとなっています。残念ながら東京リージョンは現時点で未対応です。本記事では、「米国東部(バージニア北部)」のリージョンを使っています。
Amazon SageMakerへのサインアップが完了するとダッシュボードへ遷移します。早速、ノートブックインスタンスの作成を行ってみましょう。
ノートブックインスタンスの作成をクリックすると、次画面でインスタンス作成画面へ遷移します。インスタンスの名前はとりあえず「 bank-tutorial 」として、またノートブックのインスタンスタイプも最小の「 ml.t2.medium 」を選びました。無料枠が使える方は、おそらくこちらで無料枠用のインスタンスが出てくるかと思いますので、ご希望の方はそちらを選んだ方が良いかと思います。
IAMロール(AWS内の権限を管理する機能)ですが、「 任意のS3バケット 」を選択しています。チュートリアルですので、セキュリティ面は深く考えていませんが、重要なデータを扱う場合は、IAMロールの設定を必ずしっかりと確認しましょう。
他のVPCや暗号化キーはオプションとなっていますので、今回は特に指定せずノートブックインスタンスを作成します。
ノートブックインスタンスの作成が完了したら、ノートブックを立ち上げてみましょう。ノートブックインスタンス(下記キャプチャ)のページから、「オープン」をクリックするとJupyter Notebookのトップへ遷移します。
Jupyter Notebookページ(下記キャプチャ)の「New」からconda_python3を選択して、新しいノートブックを立ち上げましょう。
ノートブックの画面(下記キャプチャ)へ遷移しますので、解りやすいように名前の変更をしましょう。Jupyterのロゴのすぐ横の「 Untitled 」をクリックするとノートブックの名前の変更が可能です。「bank-tutorial-1」と名前を変更しておきましょう。
最後のステップとして、AWS S3のバケットネームの確認を行います。
本チュートリアルでは、後ほどSageMakerのノートブックとS3の連携を行いますので、S3の登録をまだ行っていない方は、こちらからどうぞ。またS3をすでに使っている方でも、リージョンが異なる場合は「米国東部(バージニア北部)」にて、新しいバケットの作成をお願いします。SageMakerとS3の連携ですが、リージョンが異なると行えないようです。
さて、これでアカウント周りの準備は完了です。次のステップでは、機械学習モデル構築の大まかな手順をみていきましょう。
データセットとモデル構築の概要
本チュートリアルでは、カルフォルニア大学アーバイン校が公開している「
Bank Marketing Data Set (銀行マーケティング・データセット)」を利用します。機械学習エンジニアなら、一度は耳にする初心者向けの非常に有名なデータセットです。
こちらのデータセットですが、ポルトガルのとある銀行が実際に行った、電話による定期貯金のダイレクトマーケティングの結果となります。各ユーザーの年齢や職業、さらには学歴などのデータがあり、ダイレクトマーケティングを行った結果、定期預金へお申し込みをした(ラベル=1)、お申し込みをしなかった(ラベル=0)が付与されています。
SageMakerを使ってこのデータセットの前処理を行い、XGBoostを使って予測を行います。本チュートリアルですが、SageMakerノートブックインスタンスを「ml.t2.medium」を使用しています。特に問題はありませんでしたが、ところどころ10分程度、時間がかかる処理がありました。ml.t2.mediumですが、vCPUが2、メモリーが4GBとなっています。もっと大規模な処理を行う場合には、上級インスタンスへ簡単に変更が可能なのは大きなメリットですね。(当然、料金も高くなりますが)
では、早速、Amazon SageMakerのノートブックを使ってデータセットを紐解いていきましょう。
ノートブックの立ち上げと準備
すでに前項目でSageMakerのノートブックインスタンスの立ち上げと、S3の設定(または新規登録)を行いましたので、早速ノートブックで下準備をしていきましょう。SageMakerの「ノートブックインスタンス」のページへアクセスしていただき、先ほど作った「bank-tutorial」を立ち上げましょう。
本チュートリアルの通りに設定をした方であればSageMakerのノートブックを立ち上げて、Jupyter Notebookのトップ画面で「bank-tutorial-1.ipynb」が作られているかと思います。こちらをクリックして、ノートブックを開きましょう。
準備編として、必要な設定変数とライブラリのインポートを行いましょう。下記のbucketの「XXXXXXXXXXX」ですが、各自のS3のバケット名へ変更をしましょう。またSageMakerとS3のリージョンが異なると動きませんので、リージョンが同じかどうか注意が必要です。
prefix で指定したフォルダがS3へ新しく作られます。特に変更は必要ありませんが、適宜変更しても問題ありません。最後にboto3とIAMのroleの宣言です。boto3ですすが、AWSが開発したPythonとAWSの各種サービスを統合するライブラリとなっています。(詳しくはこちらから)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# S3のバケット名を下記に設定してください # S3のプレフィックスを設定(変更は不要です) bucket = 'XXXXXXXXXXX' prefix = 'sagemaker/xgboost-dm' # IAMのroleの宣言 import boto3 import re from sagemaker import get_execution_role role = get_execution_role() |
こちらを最初のセルへ入力して、 Shift + Enter でセルの実行を行いましょう。
次は今回のモデル構築に使う必要なライブラリ各種を一気にインポートしちゃいましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import numpy as np import pandas as pd import matplotlib.pyplot as plt from IPython.display import Image from IPython.display import display from sklearn.datasets import dump_svmlight_file from time import gmtime, strftime import sys import math import json import os import sagemaker from sagemaker.predictor import csv_serializer |
機械学習の定番(?)となるNumpy、Pandas、Matplotlibに加えて、ipython(Jupyter Notebook)で表などをプロッティングするモジュール、さらにsagemakerのPython SDKもインポートします。各ライブラリの詳細の説明は行いませんが、見たことのないライブラリがある方は、軽く調べてみると良いかと思います。
SageMakerノートブックでみると、下記キャプチャの様になっているかと思います。正しく処理が行えてれば、各セルの左上の [ ] に番号が表示されます。何かしらの理由で処理が終わらなかったりすると、こちらに[*]と処理中のマークが出ます。
さて、次はデータをUCIからデータをダウロードして紐解いていきましょう!
データセットの取得と確認
カルフォルニア大学アーバイン校のサイトにてデータセットが公開されていますので、そちらから直接取得しましょう。特に会員登録などは必要ありません。 wget でURLから直接ダウロードして、 unizip (解答)してあげましょう。
1 2 3 4 5 6 |
# カルフォルニア大学アーバイン校の公開URLからデータセットをダウロード !wget https://archive.ics.uci.edu/ml/machine-learning-databases/00222/bank-additional.zip !unzip -o bank-additional.zip |
Jupyter Notebookのtreeページを確認すると、ダウロードした bank-additional.zip と解凍された bank-additional というフォルダーが作成されているのが確認できます。
ではこちらのcsvファイルのデータセットを、Pandasのデータフレームとして読み込みましょう。
1 2 3 4 5 6 7 8 9 10 11 12 |
# bank-additional-full.csvをdataへ格納 data = pd.read_csv('./bank-additional/bank-additional-full.csv', sep=';') # Pandasの最大表示カラム数と行数の設定を変更 pd.set_option('display.max_columns', 500) pd.set_option('display.max_rows', 30) # 最初の10行を表示 data.head(10) |
こちら記事内表示の便宜上、二段に分けて掲載しています。ご覧の通り、「age(年齢)」や「marital(結婚ステータス)」など各ユーザーの情報が格納されています。今後、機械学習を勉強されてる方にも解りやすいよう、簡単に各項目の概要をまとめました。
- age – 顧客の年齢
- job – 仕事のカテゴリ
- marital – 結婚ステータス
- education – 学歴
- default – クレジットの支払遅延のステータス
- housing – 不動産ローンの有無
- loan – パーソナルローンの有無
- contact – 銀行と顧客の連絡方法
- month – 最後に連絡をとった月
- day_of_week – 最後に連絡をとった曜日
- duration – 最後の連絡長さ(秒数)
- campaign – このキャンペーン中に銀行が連絡した回数
- pdays – 最後のキャンペーンの連絡から経過した日にち
- previous – このキャンペーン以前に銀行が連絡した回数
- poutcome – 前回のキャンペーンの結果
- emp.var.rate – Employment Variation Rate(詳細説明なし)*
- cons.price.idx – 消費者物価指数 *
- cons.conf.idx – 消費者信頼感指数 *
- euribor3m – 3ヶ月スパンユーリボー指標金利 *
- nr.employed – 四半期の従業員数 *
- y – 顧客が定期預金を申し込みしたかどうか(予測ターゲット)
データセットの各項目の意味が理解できたところで、少し掘り下げてデータセットを紐解いていきましょう。まずは、お決まりの欠損データの確認をしておましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# データフレームの欠損データをまとめるテーブルの関数 def missing_values_table(df): mis_val = df.isnull().sum() mis_val_percent = 100 * df.isnull().sum()/len(df) mis_val_table = pd.concat([mis_val, mis_val_percent], axis=1) mis_val_table_ren_columns = mis_val_table.rename( columns = {0 : 'Missing Values', 1 : '% of Total Values'}) return mis_val_table_ren_columns # dataに欠損があるかどうか確認 missing_values_table(data) |
こちら実はデータセットダウロードページでも説明があるのですが、なんと欠損データが一つもありません(感動)!欠損データで頭を悩ます必要がないなんて、嬉しい限りです。
次は各項目のデータの分散を確認してみましょう。
1 2 3 4 5 6 7 8 9 10 11 |
# 各項目の度数分布の表を作成 for column in data.select_dtypes(include=['object']).columns: display(pd.crosstab(index=data[column], columns='% observations', normalize='columns')) # 数値を値として持っている項目のヒストグラム display(data.describe()) %matplotlib inline hist = data.hist(bins=30, sharey=True, figsize=(10, 10)) |
バーっと各項目の度数分布が出てくるのですが、いくつか気になる部分のデータをまとめてみてみましょう。下記画像ですが、左から「job(職業)」「education(学歴)」「martital(結婚ステータス)」の度数分布となっています。
さすが銀行のデータです。職業の項目の「unknown(不明)」の0.8%を筆頭に、他のデータでも不明の項目の割合が比較的小さいです。本記事では細かく触れませんが、他の項目のデータも紐解いていくと、このデータセットの特徴などが見えてきます。
また今回の予測ターゲットとなる「 y 」の項目も確認してみましょう。ご覧の通り、「 no 」が約88.7%とデータの大半を占めているのが解ります。こちらはキャンペーンで顧客が定期預金を申し込みしたかどうかのフラグとなっているので、「 no 」が多いのも納得できますね。
さて、次もお決まりですが、各項目が予測ターゲットとどのような関係となっているかを確認していきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 各項目が予測ターゲット「y」にどのように関係してるか確認 for column in data.select_dtypes(include=['object']).columns: if column != 'y': display(pd.crosstab(index=data[column], columns=data['y'], normalize='columns')) for column in data.select_dtypes(exclude=['object']).columns: print(column) hist = data[[column, 'y']].hist(by='y', bins=30) plt.show() |
1 2 3 4 5 6 7 8 9 |
# 相関係数とScatter Matrixの確認 # 処理完了まで少し時間がかかります display(data.corr()) pd.plotting.scatter_matrix(data, figsize=(12, 12)) plt.show() |
バーっと表やテーブルが出てきますので、深く理解されたい方は、各項目のテーブルを紐解いてみてください。下記の図は、各項目の相関係数(data.corr())となっています。
いくつかの項目で高い正の相関と負の相関が見受けられますね。当然といえば当然ですが、外部環境要因の指標同士は高い相関があるようです。
ざっくりではありますが、データセットを簡単に紐解いてみました。次のステップでは、データセットの前処理、いわゆる「データクレンジング」をやっていきましょう。
データクレンジング(データセット前処理)
ほぼ全ての機械学習のプロセスで、データセットのクレンジングは必須の工程となっています。何が正しいのか、悪いのかという正解は無く、手探りでトライ&エラーを繰り返しながら進めていくのが通常です。
ただ、いくつか基本となる「前処理の前処理」とでも言いますか、一般的に広く使われている方法・テクニックがあります。
- 欠損データを処理
- カテゴリカルデータを処理
- 特異な分散をしているデータを処理
すでに確認した通りで欠損データは含まれませんので今回は対応をしなくて大丈夫ですね。実際に行うデータの前処理ですが、下記の4つの処理を行いましょう。各処理の説明も記載しています。
[1] pdaysから連絡の取っていない顧客を抽出する
pdays ですが、「最後のキャンペーンの連絡から経過した日にち」となります。すでにデータ確認のステップで見ましたが、 pdays は「 999 」のデータが非常に多かったです。つまり前回から連絡を取っていない顧客が大半と言えます。 pdays を少し処理して、999日(つまり連絡を取っていなかった顧客)を「 1 」としてそれ以外を「 0 」とするデータ処理をします。
jobから現在職についてない顧客を抽出する
job (職業)の項目ですが、 unknown (不明)を含む12種類あります。よくこの項目をみて見ると、「 student (学生)」や「 unemployed (失業中)」など現時点で職についてない顧客が含まれています。そこで、現在働いているか、働いていないかを切り分けて新しく「 not_working 」(働いていない)という項目を追加する処理を行います。
カテゴリカルデータをダミー変数化する
ダミー変数とは、数字てはないデータを数字に変換する手法を指します。例えば、今回のデータで言うと、予測ターゲットの「 y 」ですが、持っている値が「 yes 」「 no 」となっています。これをダミー変数化すると、もともと一つの項目「 y 」が二つの項目「 y_yes 」と「 y_no 」に分裂して、各値に応じて「0」「1」が付与されます。機械学習では、かなり頻繁に行う処理です。Pandasではダミー変数化をするのはとても簡単で、pd.get_dummiesを使うことで、ほぼ自動的にダミー変数化してくれます。(get_dummies以外にも、カテゴリカルデータを数値に変換してくれるpd.cat.codeという便利な関数もあります)
予測モデルに組み込まない項目の削除
さて、最後に外部環境要因の指標( emp.var.rate )など、今回のトレーニングで使わない項目をpd.dropでデータフレームから削除を行います。
下記が、コードとなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 以前にコンタクトがなかった人を判別する新しい項目の追加 data['no_previous_contact'] = np.where(data['pdays'] == 999, 1, 0) # 職業から「職についていない人」(学生など)のフラグを追加 data['not_working'] = np.where(np.in1d(data['job'], ['student', 'retired', 'unemployed']), 1, 0) # カテゴリカルデータをダミー変数化 model_data = pd.get_dummies(data) # 今回のモデルで使用しない項目を削除 model_data = model_data.drop(['duration', 'emp.var.rate', 'cons.price.idx', 'cons.conf.idx', 'euribor3m', 'nr.employed'], axis=1) # データを確認しよう mode_data.head(10) |
ご覧の通り、ダミー変数化してますので、列数が多くなっているのが確認できます。また今回のモデルで使用しない項目が削除されていることも確認しておきましょう。
前処理が完了したので、次はデータを訓練データ、確認用データ、テストデータの3つに分けましょう。その前に機械学習では避けて通れない「Overfitting(オーバーフィッティング)(過学習)」について簡単に触れておきましょう。
教師あり学習モデル(Supervised Learning Models)は、与えられたデータで、「予測した値と実際の値の誤差をどれだけ最小にするか」を目的としてデザインされています。つまりモデルは、いかに予測値と実際の値の誤差を小さくするための計算を行うわけなんですが、そのプロセスの中で、モデルが、特異点までもを組み込んで偏った予測をしてしまうことが多々あります。これが過学習です。
特異点が新しいデータでも見られるパターンであれば、それを組み込んだモデルの予測は正確なものになるのですが、そうでないケースは、そのモデルの正確性は落ちてしまいます。
この過学習を避けるテクニックは多数ありますが、一般的な方法として、モデルのトレーニングを一つのデータセットで行うのではなく、新しいデータセットでもトレーニングを行う手法です。
一先ず今回は「データを一回だけ訓練させると、そのデータには正確性が高い予測が出るけど・・新しいデータでの予測はそうとは限らないよね。だから元データを複数に分けて、複数回のトレーニングをした方が、今後の新しいデータへの予測に汎用性が高そうじゃない?」というくらいのニュアンスで理解しておきましょう!
ということで、今回のデータセットですが3つに分けることにします。
1 2 3 4 5 6 7 8 9 |
# 前処理したmodel_dataをランダムにソートして3つのデータフレームに分けましょう train_data, validation_data, test_data = np.split(model_data.sample(frac=1, random_state=1729), [int(0.7 * len(model_data)), int(0.9 * len(model_data))]) # Randomly sort the data then split out first 70%, second 20%, and last 10% # 念のため各データフレームのサイズを確認 # 全ての合計がmodel_dataのサイズと一致してます model_data.shape, train_data.shape, validation_data.shape, test_data.shape |
さて、とうとうデータ前処理の最終ステップとなります。Amazon SageMaker XGBoostのコンテナのデータフォーマットですが、libSVMとなります。libSVMフォーマットですが、feature(特徴量)と予測ターゲット(目的変数)を別々のアーギュメントにしなくてはいけませんので、その処理を行いましょう。
最後に、boto3経由でAWS S3へ、この訓練データセット(libSVM形式)を送っておきます。
1 2 3 4 5 6 7 8 9 10 11 |
# libSVMファイルの書き出し dump_svmlight_file(X=train_data.drop(['y_no', 'y_yes'], axis=1), y=train_data['y_yes'], f='train.libsvm') dump_svmlight_file(X=validation_data.drop(['y_no', 'y_yes'], axis=1), y=validation_data['y_yes'], f='validation.libsvm') dump_svmlight_file(X=test_data.drop(['y_no', 'y_yes'], axis=1), y=test_data['y_yes'], f='test.libsvm') # Boto3を使ってS3へファイルをコピーする boto3.Session().resource('s3').Bucket(bucket).Object(os.path.join(prefix, 'train/train.libsvm')).upload_file('train.libsvm') boto3.Session().resource('s3').Bucket(bucket).Object(os.path.join(prefix, 'validation/validation.libsvm')).upload_file('validation.libsvm') |
最初の準備編で指定したAWS S3のバケットに新しく「 sagemaker 」というフォルダーが作成されているかと思います。繰り返しになりますが、SageMakerのリージョンとS3のリージョンが異なると、処理が行われませんので気をつけてください。
下記のキャプチャのように、 S3 > バケット名 > sagemaker > xgboost-dm > train のディレクトリーにtrain.libsvmが新規作成されているばオッケーです。
訓練(トレーニング)の実行
データセットの確認と前処理が完了しましたので、次はいよいよXGBoostを使ってモデルの構築を行いましょう。その前に、今回使うアルゴリズムとXGBoostの概要を簡単に説明します。
今回の予測モデルのアルゴリズムは「勾配ブースティング(Gradient Boosting)(グラディアント・ブースティング)」を使います。
勾配ブースティングの大まかなステップ
- 多数の小さいシンプルな予測モデルを構築
- この最小限予測モデルの「誤差」と「重み」を算出
- 最小限予測モデルを最適化して一つの予測モデルとして構築
いまいち意味が解らなくても心配不要です!機械学習と一言で言っても、その内実は多数のアルゴリズム&予測モデルで溢れています。アルゴリズムを理解することで、より深く最適なモデル構築&予測を行うことができますが、そうでなくても、トライ&エラーを繰り返すことで予測はできます。
この「勾配ブースティング(Gradient Boosting)」を、より効率的に使いやすしたのが「XGBoost」です。XGBoostですがオープンソースで、世界中の機械学習エンジニアの間で人気が非常に高いフレームワークです。(XGBoostを使って、Kaggle(機械学習コンペ)の上位になることも可能ですので、初心者用のフレームワークという訳ではありません)
それでは、Amazon SageMakerでXGBoostを使って予測モデルの構築をしてみましょう!やり方は・・驚くくらい単純です。大まかなステップは以下の通り。
- Amazon SageMakerのXGBoostのためのECRコンテナの場所を指定
- 訓練データ(libSVM)とS3の連携してあげる
- sagemaker.estimator.Estimatorに必要な情報を指定
- ハイパーパラメーターの指定
- フィッティングと出力データのS3の格納先の指定
では、実際にSageMakerノートブックで上記の流れを行ってみましょう。
1 2 3 4 5 6 7 8 |
# SageMaker XGBoostのためのECRコンテナを指定 containers = {'us-west-2': '433757028032.dkr.ecr.us-west-2.amazonaws.com/xgboost:latest', 'us-east-1': '811284229777.dkr.ecr.us-east-1.amazonaws.com/xgboost:latest', 'us-east-2': '825641698319.dkr.ecr.us-east-2.amazonaws.com/xgboost:latest', 'eu-west-1': '685385470294.dkr.ecr.eu-west-1.amazonaws.com/xgboost:latest'} |
1 2 3 4 5 6 |
# 訓練データとS3を連携してあげる s3_input_train = sagemaker.s3_input(s3_data='s3://{}/{}/train'.format(bucket, prefix), content_type='libsvm') s3_input_validation = sagemaker.s3_input(s3_data='s3://{}/{}/validation/'.format(bucket, prefix), content_type='libsvm') |
さて、次はSageMakerのEstimatorへ必要なパラメーターとハイパーパラメーターの指定をしてあげて、フィッティングを行います!下記コードですが、訓練用のインスタンスとして、 ml.m4.xlarge を使用しています。処理ですがおおよそ10分程度で完了します。参考までにですが、本チュートリアル全体(ノートブック、モデルトレーニング、モデルホスティングの全ての合計)で、約3〜4ドルくらいで行えました。
さて、いよいよモデルフィッティングとなります!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# SageMakerのセッション sess = sagemaker.Session() # sagemakerのestimatorへ必要項目を指定 xgb = sagemaker.estimator.Estimator(containers[boto3.Session().region_name], role, train_instance_count=1, train_instance_type='ml.m4.xlarge', output_path='s3://{}/{}/output'.format(bucket, prefix), sagemaker_session=sess) # ハイパーパラメーターの指定 xgb.set_hyperparameters(max_depth=5, eta=0.2, gamma=4, min_child_weight=6, subsample=0.8, silent=0, objective='binary:logistic', num_class=1, num_round=100) # モデルフィッティングと出力先の指定(S3) xgb.fit({'train': s3_input_train, 'validation': s3_input_validation}) |
下記が出力されていれば、問題なくフィッティングが完了しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# こちらは入力コードではありません。出力結果です。 [95]#011train-error:0.093961#011validation-error:0.10488 [04:47:33] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 12 extra nodes, 20 pruned nodes, max_depth=5 [96]#011train-error:0.094204#011validation-error:0.10488 [04:47:33] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 20 extra nodes, 24 pruned nodes, max_depth=5 [97]#011train-error:0.094239#011validation-error:0.105244 [98]#011train-error:0.094274#011validation-error:0.105123 [04:47:34] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 4 extra nodes, 24 pruned nodes, max_depth=2 [04:47:34] src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 20 extra nodes, 26 pruned nodes, max_depth=5 [99]#011train-error:0.094308#011validation-error:0.105365 ===== Job Complete ===== |
ハイパーパラメーターで設定した通り100ラウンドで完了していますね。ここまでのステップで、前処理を行ったデータを使って、XGBoostアルゴリズムの訓練(トレーニング)が完了できました。次は、この訓練したモデルをデプロイしましょう。
それでは、モデルホスティングを行いましょう。下記ですが、 ml.c4.xlarge のインスタンスを利用しています。(
処理完了まで約10分程度かかります)
1 2 3 4 5 6 |
# ml.c4.xlargeのインスタンスでデプロイ xgb_predictor = xgb.deploy(initial_instance_count=1, instance_type='ml.c4.xlarge') |
いよいよ、最後のステップ「評価(Evaluation)」となります。次のステップでは、今回、訓練したXGBoostの予測精度を確認してみましょう。
予測の精度確認(評価 / Evaluation)
機械学習モデルの評価方法ですが、多数の手法がありますが、本チュートリアルでは一番単純かつ簡単な「実データとの比較」を行いましょう。復習となりますが、今回の予測ターゲットは銀行のキャンペーンの定期預金のお申し込み状況(Yes or No)でしたね。
訓練したXGBoostアルゴリズムが予測した結果と実際のラベルを照らし合わせて、どれくらいの精度で予測したかを確認してみましょう。
最初のステップとして、評価で使うデータの渡し方と受け取り方を指定してあげます。テストデータですが、現在はSageMakerノートブックのインスタンス上にNumpy配列として置かれています。これをHTTP POSTリクエストで予測モデルに送るために、SageMakerの「 serializer 」を使ってシリアライズ化して、さらに content_type も指定しておきましょう。
1 2 3 4 5 6 |
# データの受け渡しのための設定を行っておく xgb_predictor.content_type = 'text/csv' xgb_predictor.serializer = csv_serializer |
次に前のステップで作成した test_data を500行ずつの小さいバッチに小分けして、XGBoostのエンドポイントで予測を行い、Numpyの配列として出力します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 500行ごとの小バッチに区切ってxgb_predictorで予測算出する def predict(data, rows=500): split_array = np.array_split(data, int(data.shape[0] / float(rows) + 1)) predictions = '' for array in split_array: predictions = ','.join([predictions, xgb_predictor.predict(array).decode('utf-8')]) return np.fromstring(predictions[1:], sep=',') # 前項目で作成したtest_dataからターゲット項目を削除して予測を出力 predictions = predict(test_data.drop(['y_no', 'y_yes'], axis=1).as_matrix()) # 予測と正解データの比較テーブル pd.crosstab(index=test_data['y_yes'], columns=np.round(predictions), rownames=['actuals'], colnames=['predictions']) |
これで、予測した値が predictions としてNumpy配列に格納されました!さぁ、いよいよ結果確認です。Pandasを使って、実際の正解データと予測した「 predictions 」の結果をテーブルにしてあげましょう。
*追記 3月13日*
下記、正解 x 予測比較のテーブルのコードが抜け落ちていましたので追記致しました。
(ドラムロール)(ドラムロール)
う〜〜〜ん・・・なんとも微妙な感じの予測ですね(苦笑) 。テストデータ全4119件中、約4000人の顧客を「見込み顧客」として考えて、その中の480名が実際に定期預金へお申し込みをしたと言えます。これを土台に、特徴量の調整やハイパーパラメーターの調整など、予測精度を改善してみると、より深い理解&学習になるかと思います!
最後に重要な作業です!!
本チュートリアルが終わったら、余計な料金が発生しないように、今回作成したエンドポイントを削除しましょう。不安な方は、SageMakerの管理画面で「モデル」「エンドポイント」「ノートブック」の状況が確認できますので、不必要なものは適宜、削除または停止をしておいた方が良いかと思います。
1 2 3 4 5 |
# 作成したエンドポイントの削除 sagemaker.Session().delete_endpoint(xgb_predictor.endpoint) |
まとめとSageMakerの所感
少々長いチュートリアルになってしまいましたが、Amazon SageMakerは如何でしたでしょうか?個人的な所感ではありますが、機械学習エンジニアにとっては「孫の手」のようなツールだと感じました。
膨大なデータを処理する機械学習ですが、今までクラウド上で処理をされる方も多かったと思いますが、使いたいフレームワークやツールなど、その都度、設定やインストールを行い、全体の管理をするのに、それなりの労力があったかと思います。
また、作成したモデルをホスティングするのに、膨大な作業が必要だったのも事実です。SageMakerを利用することで、機械学習の0から100まで、ほぼ全てのステップが一括して行えるプラットフォームというのは非常に魅力的だと感じました!
他にも似たような機械学習初心者向けチュートリアルをやってみたいという方は、こちらも挑戦してみてください。
- Kaggle リクルートレストラン客数予想チャレンジをやってみた – Kaggle初心者ハンズオンチュートリアル
- Kaggle メルカリ価格予想チャレンジの初心者チュートリアル
- 【Kaggle初心者入門編】タイタニック号で生き残るのは誰?
機械学習ではありませんが、ここ最近日本語解禁となったAmazon Alexa Skill Kit(ASK)の初心者入門チュートリアルも個人的にはおすすめです!(話題のスマートスピーカーAmazon Echoのスキル開発ができます)
以上、速報バージョンのAmazon SageMakerハンズオンチュートリアルとなります!随時、わかりやすいように改善をしていきますので、ご指摘やご意見はコメントにてお願いできればと思います!
追記 2017年12月21日
Amazon SageMakerチュートリアル第二段目を公開しました!ゲームソフトの売行きをXGBoostで予測してみた【Amazon SageMaker ノートブック+モデル訓練+モデルホスティングまで】。