機械学習初心者がVertex AIでモデルを構築してみた(AutoML)

記事タイトルとURLをコピーする

G-gen の佐々木です。今回は Google Cloud (旧称 GCP) の機械学習サービスである Vertex AI で、表形式データを用いた予測モデルの作成を試してみました。

私は機械学習についてはまだまだ勉強を始めたばかりなのですが、 Google の助けを借りて、高精度なモデル作りに挑戦してみようと思います。

Vertex AIとは

Vertex AI とは、 Google Cloud 上で機械学習モデルを開発・運用するための統合プラットフォームサービスです。

機械学習の学習用データセットを管理する DataSets 、学習用データの正解ラベル付けを自動で行う Data Labeling Service 、特徴量ストアを提供する Feature Store 、統合開発環境を提供する Workbench など、機械学習に関するサービスが統合されています。

今回はその統合されたサービス群から AutoML を使用していきます。

AutoML

AutoML は、高度なデータサイエンスの知識を持っていなくても トレーニングデータをアップロードするだけで自動的に機械学習モデルを構築することができる サービスです。

Googleが目指している AIの民主化 を象徴するサービスの1つと言ってもよいでしょう。

AutoMLが自動化する範囲

現在 AutoML のトレーニングデータとしては、以下の 4 つがサポートされています (参考) 。

  • 画像データ
  • 表形式データ
  • テキストデータ
  • 動画データ

モデル構築に使用するデータ

今回は表形式のデータ(CSVファイル)を使用してモデルをトレーニングしていきます。

モデルの作成に使用するトレーニングデータとして、パブリックドメインとなっている Adult Census Income を使用します。

このデータは米国の国勢調査局のデータベースから抽出されたものであり、ある個人に関する様々な情報(年齢、職業、結婚歴など)と「年収(income)が$50,000よりも高いか、$50,000以下か」が記録されています。

今回は AutoML を用いることで「各種パーソナリティ情報から年収($50,000よりも高いかどうか)を予測する分類モデル」を作成していきます。

Adult Census Incomeのデータ

前処理

本データにNull値は含まれていないのですが、代わりに '?' が入力されているところがあるので、今回は '?' が含まれる行を欠損値ありとして全て取り除きました。

また、モデル学習後に予測精度を確認するため、予測に使うデータを一部を切り出して別々にCSVファイルに出力しています (pred_data.csvpred_answer.csv) 。

以下のコードは、今回行った前処理の抜粋です。これ以外の前処理やモデルのトレーニングは出来る限り AutoML に任せていく方針です。

import pandas as pd
from sklearn.model_selection import train_test_split
 
 
# データ読み込み
df = pd.read_csv('/home/sasashun/notebook/blog/data/adult.csv') 
 
 
# ?を含む行を削除
drop_index = []
 
for column in ['workclass', 'occupation', 'native.country']:
    drop_index.extend(df.loc[df[column] == '?'].index.values)
 
drop_index = sorted(set(drop_index))
df2 = df.drop(index=drop_index)
 
 
# 学習に使用するデータ(train)とモデルに予測させるデータ(test)に分ける
train, test = train_test_split(df2, test_size=0.01, random_state=0)
 
 
# testを使ってincomeを予測したときの正解率を見たいので、incomeは分離しておく
pred_data = test.drop('income', axis=1)
pred_answer = test['income']
 
 
# それぞれCSVファイルに出力
train.to_csv('/home/sasashun/notebook/blog/train.csv', index=False)  # トレーニング用のデータ
pred_data.to_csv('/home/sasashun/notebook/blog/pred_data.csv', index=False)  # テストの際にモデルに与えるデータ
pred_answer.to_csv('/home/sasashun/notebook/blog/pred_answer.csv', index=False)  # テストの正解データ(※後で不要になる)

モデルのトレーニング

モデルのトレーニング前に、トレーニングデータとなるデータセットを作成します。

今回はデータを「年収が$50,000より上」もしくは「年収が$50,000以下」のどちらかに分ける 分類 モデルを作成していきます。

データセットの作成①

データソースとして、以下の3つの選択肢があります。

  • ローカルPCからアップロードしたCSVファイル
  • GCSにあるCSVファイル
  • BigQueryのテーブル/ビュー

データセットの作成②

作成したデータセットについて、欠損値の数やユニークな値の数などをここで確認できます。

読み込んだデータセットの情報

データセットを作成したら、それをトレーニングデータとしてモデルの構築を行っていきます。

トレーニング方法として AutoML による Classification (分類) を選択します。

モデルのトレーニング①

Target columnには予測対象となる income を設定します。

トレーニングで使用される訓練データとテストデータの割合などもここで設定できます。

モデルのトレーニング②

オプションではカラムごとのデータ型などが指定できますが、今回はデフォルトのまま Auto ML に全て任せます。

モデルのトレーニング③

課金に影響する要素として、トレーニングに使用するノード時間を指定します (参考) 。

過学習が起きる前にトレーニングを終了させる Early Stopping もここで設定できます。

以上の設定のみで、機械学習モデルの構築は AutoML が自動で行ってくれます。

モデルのトレーニング④

トレーニングが完了するとメールで通知されるようになっています。今回、トレーニングには2時間ほどかかりました。およそ 3,000 円の課金がされています (15 列×約 30,000 行のデータ、 1 ノード時間での学習) 。

トレーニング結果①

トレーニングが終了すると、トレーニングによるモデルの予測精度の推移を確認することができます。

トレーニング結果②

構築されたモデルを確認すると、モデルの評価を一覧で確認することができます。0~1の値を取り、1に近ければ精度が高いとされる AUC や、0~∞の値を取り、0に近ければ精度が高いとされる LogLoss などの評価値を見ると、なかなか高精度なモデルになっているのではないかと思います。

構築したモデルの評価①

構築したモデルの評価②

また、年収を予測する際に、各カラムがどれほど影響を及ぼしているのかが可視化されています。どうやら、以下のカラムの影響が特に大きいようです。

  • marital.status(結婚歴:独身・既婚・別居・離婚・死別など)
  • education.num(教育年数)
  • occupation(職業)
  • age(年齢)

各カラムの重要度

予測

リアルタイムな予測が必要であればモデルをデプロイする必要がありますが、デプロイ後は削除するまで時間料金がかかってしまいます。

今回は数百行の予測用データ (pred_data.csv) で一度だけ予測を行いたいので、モデルをデプロイせずに バッチ予測ジョブ を作成して income を予測してみます。

バッチ予測に使用するデータのソースや、処理結果のエクスポート先には BigQuery と Cloud Storage が選択できます。

バッチ予測の作成

予測結果

今回、バッチ予測の結果を GCS に出力したのですが、予想に反して複数の CSV ファイルが出力されました。

それぞれのデータを繋ぎ合わせ、正解データと比較してみます。

予測結果のCSVファイル

バッチ予測の出力は以下のようになっているので、前処理のときに用意した、正解のカラム (income) を含むデータフレームにマージします。

バッチ予測の結果

# 予測結果CSVファイルの読み込み
pred_result = pd.read_csv('/home/sasashun/notebook/blog/data/pred_result.csv')
 
# 正解データが含まれるデータフレームにマージ
test_result = pd.merge(test, pred_result)

データフレームの income_>50K_scores カラムは予測によって出力されたものであり、年収が $50,000 を超える確率が入っています。

income_>50K_scoresカラムとincomeカラム

閾値を0.5として、値が0.5より大きければ '>50K' 、そうでなければ '<=50K' に変換し、新たなカラム pred_income として追加します。

sc_income['pred_income'] = sc_income['income_>50K_scores'].apply(lambda x: '>50K' if x > 0.5 else '<=50K')

予測結果であるpred_income列の追加

最後に、予測結果である pred_income と、正解である income がどれくらい一致しているかを確認します。

# pred_incomeとincomeの一致数
match_count = (sc_income['pred_income'] == sc_income['income']).sum()
 
# 一致した割合(一致数をデータ数で割る)
print(match_count / sc_income.shape[0])

今回構築したモデルでは、87%の確率で対象の年収が$50,000を超えているかどうかを予測できることがわかりました。

トレーニングデータに対する手動の処理をほぼ行っていない状態であっても、ここまでの精度を実現できるようです。

予測結果と正解データの一致割合

過去にKaggleで行われたコンペティションでは、 AutoML によって自動で構築されたモデルが2位にまで上り詰めた実績もあるようです (記事) 。

機械学習のモデルは、いかなる職人技によって構築されたものであっても、予測対象となる現実世界が時間の経過によって変化し、トレーニング時の状況から乖離してしまうことで、モデルの予測精度が下がってしまう問題があります。

そういった問題に対して、これからはAutoMLのようなサービスによる自動化を用いたMLOpsの実践が極めて重要になってくるのではないかと思います。

私のように、これから機械学習のスキルを習得していくエンジニアは、このような自動化の仕組みと上手く付き合っていけるように、意識して学んでいく必要があるのかもしれません。

佐々木 駿太(記事一覧)

クラウドソリューション部

2022年6月にG-genにジョイン。北海道在住。
Google Cloud認定4冠、AWS 5冠、Azure 3冠、Salesforce 1冠のクラウドネイティブなエンジニア。
Professional Cloud Architect、Professional Cloud Network Engineerなどを所持。
現在はコンテナと機械学習を中心に勉強中。