[アップデート] Amazon SageMaker Autopilot のモデル学習速度が最大40%, 正答率が最大200% 改善しました!

2020.10.04

先日のアップデートで Amazon SageMaker Autopilot の機能が改善しました。

アップデートでできるようになったことのまとめ

  • 小さい(500以上の)データセットでも使えるように! Amazon SageMaker Autopilot を利用できる機会が増えた
  • より早く、より良い結果が出せるようになった
  • 指標(AUC)が増えて適切な評価指標の選択肢が広がった

何ができるようになったか

データセットが小さく不均衡な場合でも対応可能に

以前は 1,000 以上の学習データセットが必須だったのに、半分の 500 になりました。そして不均衡のデータ(例えばデータセットの分類対象が 2:8 の割合など)でも使えるようになったと!

つまり、利用機会がさらに増えたということですね!

モデルの学習を最大40%高速で、正答率が最大200%改善

これは説明不要! より早く、より良い精度の結果を出せるになった、と!

良いことづくし!

AUC が利用できるように

分類問題のモデルのための客観的な指標が追加されて使えるようになった、と!

ビジネス上の関係者に、よりモデルの結果の妥当性をアピールすることができます!

(AUC is 何?って方は、本稿では最後に「オマケ」として AUC 他を説明しています。)

やってみる

  • 1 赤ワインデータの品質分類
  • 2 kaggle の Titanic コンペにノー作業で提出してみる

1 以前やってみた赤ワインデータの品質分類と比較してみる

やってみることは下記ブログと同じです。

SageMaker Studio で対応します。

SageMaker Studio のAutopilot で赤ワインデータの品質分類を試してみた

3ヶ月前に行ったテストデータの正解率は 0.6792 でした。

今回はどうでしょうか?

new_redwine_test_result

テストデータの正解率は 0.7 でした!!

約4%の改善 ですね!(誤差の範囲かもしれませんが、前回は数回やっても 0.68を超えることはなかったように記憶しています。)

ちなみに、学習データで最も高い正解率は、前回と完全に同じでした。

学習時間は約1時間で、前回と大きな差はなかったです。おそらくデータサイズが大きくなるほど差が出てくるのだと思われます。

redwine_varidation

うまく過学習を抑えているためなのか、(通常は逆の結果になるのですが) トレーニングの結果よりテストの結果の方が良くなるのは前回も今回も同じでした。

2 kaggleの Titanic を Amazon SageMaker Autopilot でやってみる

諸注意

Kaggleで勝つデータ分析の技術 では、Titanic のデータセットがあまり機械学習の初心者向きではなく、機械学習のモデルを作成する流れを理解できたら他のコンペに挑戦することを推奨しています。(実際、スコアはかなりぶれます。)

したがって、本稿はあくまで Autopilot を使った遊びに近いものであって、コンペのスコアの良し悪しによって、 Amazon SageMaker Autopilot 性能云々を議論できるような検証水準ではない、ということは前もってお伝えしておきます。

じゃ何で Titanic かというと、データセットが 1,000以下で少ないこと、kaggle にコンペがあったこと、色々と特徴量に手を施してあげないと良い結果は出ないことを思い出したためですが、単にやってみたかっただけです。

Titanic のデータでどんな手法を使うとどの程度のスコアが出るようになるかは、下記 kaggle の Notebooks にもまとまっています。

How am I doing with my score?

やってみる

それはさておき、 kaggle の Titanic の Compete から titanic.zip をダウンロードします。

kaggle_titanic

  • gender_submission.csv:提出するデータ形式
  • train.csv:このデータを使って学習させてモデルを作る
  • test.csv:このデータを使って結果を推定する

train.csv, test.csv を それぞれ titanic_train.csv, titanic_test.csv にして SageMaker Studio にアップロードします。

SageMaker Studio の使い方や分析は本稿の主旨ではないので、特に詳細は説明せず進めます。

import pandas as pd
import numpy as np
import urllib.request
import csv
from sklearn.model_selection import train_test_split
# データを読み込む
train = pd.read_csv('./titanic_train.csv')
test = pd.read_csv('./titanic_test.csv')
# 意味のある変数だと学習されないように削除する
train = train.drop(['PassengerId'],axis=1)
test = test.drop(['PassengerId'],axis=1)
# S3バケット配置用に学習データを学習, 検証データのcsvに分ける
train_train_set, train_test_set = train_test_split(train, train_size=0.8, random_state=42)
train_train_set.to_csv('train.csv', index=False, header=True, sep=',')
train_test_set.to_csv('test.csv', index=False, header=True, sep=',')
# S3をセットする
%%time

import os
import boto3
import re
from sagemaker import get_execution_role

role = get_execution_role()
region = boto3.Session().region_name

bucket='YOUR_BUCKET_NAME'
prefix = 'autopilot/titanic'
bucket_path = 'https://s3-{}.amazonaws.com/{}'.format(region,bucket)
data_partitions = ['train', 'test']
# S3にデータをアップロードする
for data_partition_name in data_partitions:
    key = "{}/{}/data".format(prefix,data_partition_name)
    boto3.Session().resource('s3').Bucket(bucket).Object(key).upload_file(data_partition_name + '.csv')

実験を作成します。

学習させるデータがあるS3バケットの情報を入力します。

予測値は Survived です。

create_experiment1

続いて、学習させた結果を出力させたいバケットおよびオブジェクトを選びます。

2項分類なので、Binary classification を選択します。ここで AUC が増えていますね!

auc_criterion

実験が完了したら、トライアルの中から良い評価指標のモデルをデプロイしたいので、 Do you want to run a complete experiment? は Yes にして、実験を作成します。

実験が完了するまで待ちます。

続きは、1時間後くらいです。

どれが一番良いかソートしてみましょう。

1st_titanic_varidation

え、正答率が90%以上。。。何も特徴量をいじっていないのに??

やだ、なにこれ。

これは、もしかして、とんでもないことになるのか。

期待しかない。

評価の良いトライアルを選んで Deploy model からエンドポイントを作成します。

10分くらい待ったらエンドポイントができるので予測を出力させます。

# 推論の算出
runtime_client = boto3.client('runtime.sagemaker')
endpoint_name = 'ENDPOINT_NAME'

test.to_csv('titanic_test_predict.csv', index=False, header=True, sep=',')

results = []
with open('titanic_test_predict.csv', 'r') as f:
    for i in range(418):
        single_test = f.readline()
        response = runtime_client.invoke_endpoint(EndpointName = endpoint_name,
                                         ContentType = 'text/csv',
                                         Body = single_test)
        result = response['Body'].read().decode('ascii')
        results.append(int(result))
# 提出形式に整形してcsv出力
list = pd.read_csv('titanic_test.csv')
passenger_id = list['PassengerId']
submit_df = pd.DataFrame({'PassengerId': passenger_id,'Survived': results})
submit_df.to_csv('submission.csv', index=False)

kaggleに提出してみましょう!

ワクワク...

titanic_first_result

0.495

あらら、やっぱり過学習だったのでしょうか。さすがにそんなに世の中甘くはないですよね。

そしたら、以下ちょっとだけ特徴量に手を加えて再提出してみます。 *1

  • Name, Ticket, Cabin は色々とうまく処理を施すとスコアに大きな影響を与えるのですが、面倒なので削除します。
  • Sex, Embarked はラベルエンコーディングして変換する

機械学習の特徴量エンジニアリングのブログではないので説明は省きますが、簡単に補足しておくと、モデルの学習がうまくいくように(ちょっとだけ)データを修正しているだけです。

上記で変数を削除している箇所を修正します。

from sklearn.preprocessing import LabelEncoder

# 意味のある変数だと学習されないように削除する
train = train.drop(['PassengerId'],axis=1)
test = test.drop(['PassengerId'],axis=1)

# 変数Name, Ticket, Cabinを除外する
train = train.drop(['Name', 'Ticket', 'Cabin'], axis=1)
test = test.drop(['Name', 'Ticket', 'Cabin'], axis=1)

# それぞれのカテゴリ変数にlabel encodingを適用する
for c in ['Sex', 'Embarked']:
    # 学習データに基づいてどう変換するかを定める
    le = LabelEncoder()
    le.fit(train.fillna('NA'))

    # 学習データ、テストデータを変換する
    train = le.transform(train.fillna('NA'))
    test = le.transform(test.fillna('NA'))

あとは同様です。

トライアルで最も良い結果は前回と同じでした。エンドポイントを作成して再提出してみます。

どうか?!

titanic_2nd_result

うーん。 0.507 か。

あまり結果は変わらなかったですね。残念。

とりあえずデータセットが 500 以上なら扱えることとAUCの指標を確認できました!

最後に

機械学習の知識やプログラミング経験が十分でなくとも、精度の高いモデルを生成して予測分類することがさらに身近になりました!

今後もさらなる精度向上、そしてユーザーフレンドリーで使いやすい Amazon SageMaker Autopilot になっていくことは間違いないでしょう。引き続き使っていきたいです。

以上です。

どなたかのお役に立てば幸いです。

オマケの話

そもそもAUC ROCとは

2項分類でよく出てくるのが PR曲線とROC曲線(ROCとセットで出てくるのがAUC)です。

だいたいどっちが何だったっけ?と混乱します。 せっかくなので整理する機会とします。

なお、この手の話題は危ない(トマホークが四方八方から飛んできそう)と思ってるのであくまでオマケです。誤解を恐れずに読みたい人だけが読んで下さい。

そもそもこのややこしい指標がなぜ出てきたか、という背景としては、不均衡なデータを対象に分類するモデルの指標はどうすればいいんだ、がありました。

例えば、あるデータセットの内訳が9:1になっているとき、正しい予測の割合 accuracy(正答率)を指標とした場合、多い割合の方を必ず予測するモデルの正答率は90%になりますが、実際にはそんなモデルの予測が使えるとは思えないですよね。

そこで出てくるのが、あの適合率と再現率です。

毎回どっちがどっちの定義だっけ?となります。(なりませんか?)

適合率と再現率は、 Precision と Recall の英語で覚えてしまう方が個人的には記憶しやすかったです。

名称 言い換え イメージ例 トレードオフイメージ
Precision (適合率) TP /TP + FP 「正と判断したものの中」で実際に正だったもの 誤検知を避けたい 誤検知を減らすように曖昧なものは抽出しなければ見逃しは発生する可能性は上がる
Recall (再現率) TP / TP + FN 「実際に正だったものの中」で正と判断したもの 見逃しを減らしたい 見逃しを減らせるようにちょっとでも怪しいのを検出しようとすれば誤検知の可能性は上がる

ここまでくれば、PR曲線にピン!ときます。

PR曲線は Presicion と Recall のトレードオフの曲線です。 どちらの値を重視するかは使う状況や目的、価値判断になってきます。 どちらの指標に優劣あるか、の話ではありません。

こいつの話をしていると、ついでに顔を出してくるのが F値(F1-score) です。Precision と Recall の調和平均で算出される値で、それぞれの値がバランス良く高くならないとF値は高くなりません。

そして、PR 曲線の近縁?となる ROC(Receiver Operating Characteristic Curve) 曲線の登場です。 TPR(trure positive rate) = Recall とFPR(false positive ratio)とのトレードオフの曲線です。 PR曲線とROC曲線はそれぞれ焦点の対象が異なっている、という認識です。

こちらのブログでは、デモデータを使って視覚的に PR曲線と ROC曲線の違いを丁寧に説明してくれています。

インバランスデータにおけるPR曲線とROC曲線の振る舞いの違い

ROC曲線とセットで出てくるのが、AUC(area under the curve)です。ようやく出てきました。

その名の通り、ROC曲線下の面積です。1に近ければ近いほどすぐれた分類器というわけです。

なお、PR曲線とROC曲線の使い分けとしては

  • 陽性クラスが著しく少ない場合, 偽陰性よりも偽陽性が気になる場合にはPR曲線
  • それ以外の場合ではROC曲線を使う

ということです。 *2

特に意味もないですが、関係図を作ってみました。

criteria_image

再びどれが何だっけ?にならないことを願って。

参考

脚注

  1. 先述の「Kaggleで勝つデータ分析の技術」と同様の簡単な特徴量の処理を行っています。
  2. scikit-learn と TensorFlow による実践機械学習のp.94を参照