【AWS】Amazon SageMaker ~ 基本編 ~

■ はじめに

https://dk521123.hatenablog.com/entry/2020/03/18/223033

で、Amazon SageMaker の AWS本家のチュートリアルを行った。

 しかし、Amazon SageMaker の全体像や便利さはおおよそ掴めたが、
コピペ&実行で機械的行ったので、
実際に自分でもモデル作れって言われても作れそうにない。

で、データセットの説明などが詳しく、違うデータセットを扱った
別のチュートリアルがあったので、やってみる。

■ サンプル

チュートリアル – クレジットカード債務不履行予測
https://aws.amazon.com/jp/blogs/news/simplify-machine-learning-with-xgboost-and-amazon-sagemaker/

をやってみる。

* 最初のIAMロールなどの設定は、前回行っているのですっとばす
* 「conda_python2 を選択」⇒「conda_python3 を選択」に変更して行う
 => これのせいなのか、サイトのコピペで実行できなくなったので、
  プログラム言語は前回のチュートリアルの経験を活かして改変していく

目的

* クレジットカード保有者のうち、どの顧客が債務不履行になるかどうかを予測し、
 顧客の信用度を知る。
 => これにより、信用の発行を改善し、将来の支払いを予測し、業務改善材料にする

使用するデータ について

* カリフォルニア大学アーバイン校
 (UCI; University of California, Irvine)機械学習リポジトリにある
 「default of credit card clients」データセット を使用

https://archive.ics.uci.edu/ml/datasets/default+of+credit+card+clients

* 実データは以下のURLから取得できる

https://archive.ics.uci.edu/ml/machine-learning-databases/00350/default%20of%20credit%20card%20clients.xls

* クレジットカード顧客に関する 23 の関連属性がある(30,000 レコード)

X1 : 与えられたクレジットの金額
X2 : 性別 (1 = 男性 ; 2 = 女性 )
X3 : 教育 (1 = 大学院、2 = 大学、3 = 高校、4 = その他 )
X4 : 婚姻状況 (1 = 既婚 ; 2 = 単身 ; 3 = その他 )
X5 : 年齢 ( 年 )
X6 - X11 : 過去の支払履歴追跡した過去の月々の支払記録 (2005 年 4 月〜 9 月 )
X12-X17 : 請求書の金額 (※1)
X18-X23 : 前回の支払い額 (※2)
Y (default payment next month) : その人は債務不履行になりましたか?( はい = 1 , いいえ = 0) (※3)

※1:X12 = 2005 年 9 月の請求書の金額、X13 = 2005 年 8 月の請求書の金額 ... X17 = 2005 年 4 月の請求書の金額
※2:X18 = 2005 年 9 月に支払った金額、X19 = 2005 年 8 月に支払った金額 ... X23 = 2005 年 4 月に支払った金額
※3:“Y” 属性はターゲット属性(つまり、XGBoost に予測させたい属性)

詳細は、チュートリアルにもあるのでそちらで。。。

データの準備

準備

# ★ここを対象S3バケットを指定する★
# S3バケット名
bucket = 'your-s3-bucket-name'
# S3キー
prefix = 'sagemaker/xgboost_credit_risk'

# import libraries
import boto3
import re
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
import sagemaker
from sagemaker import get_execution_role
from sagemaker.predictor import csv_serializer
# ここはオリジナル
import urllib.request

# 指定した Role の読み込み
role = get_execution_role()

データロード

# ここもオリジナル
# データダウンロード
target_dataset = https://archive.ics.uci.edu/ml/machine-learning-databases/00350/default%20of%20credit%20card%20clients.xls
try:
  urllib.request.urlretrieve (target_dataset, "credit_card_clients.xls")
  print('Success: downloaded credit_card_clients.xls.')
except Exception as e:
  print('Data load error: ',e)

# Pandasによるデータの読み込み
try:
  dataset = pd.read_excel('./credit_card_clients.xls', header=1)
  print('Success: Data loaded into dataframe.')
except Exception as e:
    print('Data load error: ',e)

# Pandasの最大表示カラム数と行数の設定を変更
pd.set_option('display.max_rows', 8)
pd.set_option('display.max_columns', 15)

# データ確認
dataset

データ整形

# ID列を削除
dataset = dataset.drop('ID', axis=1)

# 最初の列に予測変数を設定する
dataset = pd.concat(
 [dataset['default payment next month'], dataset.drop(['default payment next month'], axis=1)],
 axis=1) 

データ分割(トレーニング/検証/テスト)

# トレーニング/検証/テストデータに分割
#  +トレーニング:学習用
#  + バリデーション:ハイパーパラメータチューニング用
#  + テスト:推論テスト用
#
# [補足]
# なぜ教師あり学習でバリデーションセットとテストセットを分ける必要があるのか?
# https://qiita.com/QUANON/items/ae569961ea02b4468e23  
train_data, validation_data, test_data = np.split(
  dataset.sample(frac=1, random_state=1729), [int(0.7 * len(dataset)), int(0.9 * len(dataset))])

# CSVファイル出力(ヘッダー除去)
#  トレーニング
train_data.to_csv('train.csv', header=False, index=False)
#  検証
validation_data.to_csv('validation.csv', header=False, index=False)

入力データ抽出(トレーニング/検証)

# S3 にアップロード
#  トレーニング
boto3.Session().resource('s3').Bucket(bucket_name).Object(
  os.path.join(prefix, 'train/train.csv')).upload_file('train.csv')
#  検証
boto3.Session().resource('s3').Bucket(bucket_name).Object(
  os.path.join(prefix, 'validation/validation.csv')).upload_file('validation.csv')

# 入力データを抽出
#  トレーニング
s3_input_train = sagemaker.s3_input(
  s3_data='s3://{}/{}/train'.format(bucket_name, prefix),
  content_type='csv')
#  検証
s3_input_validation = sagemaker.s3_input(
  s3_data='s3://{}/{}/validation'.format(bucket_name, prefix),
  content_type='csv')

XGBoost のトレーニン

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'
}

# Amazon SageMaker セッションをセットアップ
sess = sagemaker.Session()

# XGBoost モデル (estimator) のインスタンスを作成
# (train_instance_count と train_instance_typeで、
#  トレーニングをスケールアウトし分散できる)
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(
  eta=0.1,
  # XGBoost にどのような問題 ( 分類、回帰、ランク付けなど )
  # を解決するかを指示
  # クレジットカード債務不履行になる
  # 可能性がある人物かどうかを予測することで
  # バイナリ分類の問題を解決
  objective='binary:logistic',
  num_round=25)

# トレーニング
xgb.fit({'train': s3_input_train, 'validation': s3_input_validation})

モデルのデプロイ

xgb_predictor = xgb.deploy(
  initial_instance_count=1, instance_type='ml.m4.xlarge'

予測

xgb_predictor.content_type = 'text/csv'
xgb_predictor.serializer = csv_serializer
xgb_predictor.deserializer = None

# テストデータに入力として取り込み、データの予測を実行する予測関数
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=',')

predictions = predict(test_data.values()[:, 1:])
predictions

■ 補足

ハイパーパラメータの自動モデルチューニング

以下のサイトを参照。

https://aws.amazon.com/jp/blogs/news/sagemaker-automatic-model-tuning/

参考文献

https://qiita.com/suzukihi724/items/3792f395fb22cf7fb311

関連記事

Amazon SageMaker ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/03/18/223033
Amazon SageMaker ~ 組み込みアルゴリズム
https://dk521123.hatenablog.com/entry/2020/03/20/221553
Pandas ~ データ解析支援ライブラリ ~
https://dk521123.hatenablog.com/entry/2019/10/22/014957