scikit-learn を使ったカスタム予測ルーチンの作成

Colab のロゴ このチュートリアルを Colab のノートブックとして実行 GitHub ロゴ GitHub のノートブックを表示

概要

このチュートリアルでは、トレーニング済みの scikit-learn モデルを AI Platform Prediction にデプロイし、カスタム予測ルーチンを使用して予測を提供します。これにより、予測リクエストに対する AI Platform Prediction のレスポンスをカスタマイズできます。

この例では、カスタム予測ルーチンを使用して、前処理として予測入力をスケーリングし、後処理として予測出力のクラス番号をラベル文字列に変換します。

このチュートリアルでは次の操作を行います。

  • ローカル(このノートブック)で簡単な scikit-learn モデルをトレーニングする
  • カスタム予測ルーチンを作成して AI Platform Prediction にデプロイする
  • そのデプロイメントからの予測リクエストを処理する

データセット

このチュートリアルでは R.A. Fisher の Iris データセットを使用します。これは、機械学習技術を試す際によく利用される小さなデータセットです。各インスタンスには 4 つの数値特徴があり、花のさまざまな測定値を表します。ターゲット ラベルは Iris(アヤメ)の種類で、Iris setosa、Iris versicolour、Iris virginica のいずれかになります。

このチュートリアルでは、scikit-learn ライブラリに含まれている Iris データセットのコピーを使用します。

目的

ここでは、花の測定値を入力として、それがどのアヤメの種類かを予測するモデルをトレーニングすることを目的とします。

このチュートリアルでは、モデル自体の設計よりも、AI Platform Prediction でこのモデルを使用することに重点を置きます。

費用

このチュートリアルでは、Google Cloud の課金対象となるコンポーネントを使用します。

  • AI Platform Prediction
  • Cloud Storage

詳しくは、AI Platform Training の料金Cloud Storage の料金をご覧ください。また、料金計算ツールを使用すると、予想される使用量に基づいて費用の見積もりを作成できます。

始める前に

AI Platform Prediction でモデルをトレーニングしてデプロイする前に、次の準備作業が必要です。

  • ローカル開発環境を設定します。
  • 課金と必要な API が有効になっている Google Cloud プロジェクトを設定します。
  • トレーニング パッケージとトレーニングしたモデルを保存する Cloud Storage バケットを作成します。

ローカル開発環境の設定

このチュートリアルを完了するには、以下のリソースが必要です。

  • Python 3
  • virtualenv
  • Cloud SDK

Python 開発環境を設定するための Google Cloud ガイドでは、上記の要件を満たすための詳しい手順を説明しています。要約した手順を次に示します。

  1. Python 3 をインストールします

  2. virtualenv をインストールして、Python 3 を使用する仮想環境を作成します。

  3. その環境をアクティブにします。

  4. 次のセクションにある手順に従い、Cloud SDK をインストールします。

Google Cloud プロジェクトの設定

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. Cloud Console のプロジェクト セレクタページで、Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタのページに移動

  3. Google Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  4. AI Platform Training & Prediction and Compute Engine API を有効にします。

    API を有効にする

  5. Cloud SDK をインストールして初期化します。

GCP アカウントの認証

認証を設定するには、サービス アカウントキーを作成し、そのサービス アカウントキーへのファイルパスの環境変数を設定する必要があります。

  1. 認証に使用するサービス アカウント キーを作成します。
    1. Cloud Console で、[サービス アカウント キーの作成] ページに移動します。

      [サービス アカウント キーの作成] ページに移動
    2. [サービス アカウント] プルダウン リストから [新しいサービス アカウント] を選択します。
    3. [サービス アカウント名] フィールドに名前を入力します。
    4. [ロール] プルダウン リストから、[Machine Learning Engine] > [ML Engine 管理者]、および [ストレージ] > [ストレージ オブジェクト管理者] を選択します。

      : [ロール] フィールドによって、サービス アカウントによるリソースへのアクセスが承認されます。このフィールドは、後で Cloud Console を使用して表示および変更できます。本番環境のアプリを開発している場合は、[Machine Learning Engine] > [ML Engine 管理者][ストレージ] > [ストレージのオブジェクト管理者] よりも詳細な権限を指定する必要があります。詳しくは、AI Platform Prediction のアクセス制御をご覧ください。
    5. [作成] をクリックします。キーを含む JSON ファイルがパソコンにダウンロードされます。
  2. 環境変数 GOOGLE_APPLICATION_CREDENTIALS をサービス アカウント キーが格納された JSON ファイルのファイルパスに設定します。 この変数は現在の shell セッションにのみ適用されるため、新しいセッションを開く場合は、変数を再度設定します。

Cloud Storage バケットの作成

カスタム予測ルーチンをデプロイするには、トレーニング済みモデルのアーティファクトとカスタムコードを Cloud Storage にアップロードする必要があります。

Cloud Storage バケットの名前を環境変数として設定します。この名前は、すべての Cloud Storage バケットにわたって一意なものにする必要があります。

BUCKET_NAME="your-bucket-name"

AI Platform Prediction を利用できるリージョンを選択して、別の環境変数を作成します。

REGION="us-central1"

このリージョンに Cloud Storage バケットを作成し、後のトレーニングと予測で同じリージョンを使用します。そのバケットが存在しない場合は、次のコマンドを実行して作成します。

gsutil mb -l $REGION gs://$BUCKET_NAME

scikit-learn モデルの構築とトレーニング

多くの場合、機械学習モデルをトレーニングするときに、データをそのままの形式で使用することはできません。そのまま使用できる場合でも、トレーニングの前にデータの前処理を行うと、モデルが改善されることがあります。

予測入力がトレーニング データと同じ形式になると予想される場合、モデルが一貫した予測を行うように、トレーニングと予測で同じ前処理を行う必要があります。

このセクションでは、前処理モジュールを作成し、そのモジュールをトレーニングで使用します。さらに、トレーニング中に学習した特徴を持つプリプロセッサをエクスポートし、後でカスタム予測ルーチンで使用します。

ローカル トレーニング用の依存関係をインストールする

ローカル トレーニングでは、いくつかの依存関係が必要です。

pip install numpy>=1.16.0 scikit-learn==0.20.2

プリプロセッサを作成する

各数値特徴列の平均値が 0、標準偏差が 1 になるようにトレーニング データをスケーリングすると、モデルを改善できます

このスケーリングを行うクラスを含む preprocess.py を作成します。

import numpy as np

class MySimpleScaler(object):
  def __init__(self):
    self._means = None
    self._stds = None

  def preprocess(self, data):
    if self._means is None: # during training only
      self._means = np.mean(data, axis=0)

    if self._stds is None: # during training only
      self._stds = np.std(data, axis=0)
      if not self._stds.all():
        raise ValueError('At least one column has standard deviation of 0.')

    return (data - self._means) / self._stds

MySimpleScaler のインスタンスは、最初の使用時に各特徴列の平均と標準偏差を保存します。その後、これらの要約統計を使用して、発生したデータをスケーリングします。

これにより、トレーニング分布の特徴を保存し、予測時に同じ前処理を行うことができます。

モデルのトレーニング

次に、preprocess.MySimpleScaler を使用して Iris データを前処理し、scikit-learn でモデルをトレーニングします。

最後に、トレーニング済みのモデルを joblib(.joblib)ファイルとしてエクスポートし、MySimpleScaler インスタンスを pickle(.pkl)ファイルとしてエクスポートします。

import pickle

from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.externals import joblib

from preprocess import MySimpleScaler

iris = load_iris()
scaler = MySimpleScaler()
X = scaler.preprocess(iris.data)
y = iris.target

model = RandomForestClassifier()
model.fit(X, y)

joblib.dump(model, 'model.joblib')
with open ('preprocessor.pkl', 'wb') as f:
  pickle.dump(scaler, f)

カスタム予測ルーチンのデプロイ

カスタム予測ルーチンをデプロイして、トレーニング済みモデルから予測を提供するには、次の作業を行います。

  • リクエストを処理するカスタム予測器を作成する
  • 予測器と前処理モジュールをパッケージ化する
  • モデル アーティファクトとカスタムコードを Cloud Storage にアップロードする
  • カスタム予測ルーチンを AI Platform Prediction にデプロイする

カスタム予測器を作成する

カスタム予測ルーチンをデプロイするには、予測器インターフェースを実装するクラスを作成する必要があります。これにより、AI Platform Prediction にモデルの読み込み方法と予測リクエストの処理方法を指示します。

次のコードを predictor.py に記述します。

import os
import pickle

import numpy as np
from sklearn.datasets import load_iris
from sklearn.externals import joblib

class MyPredictor(object):
  def __init__(self, model, preprocessor):
    self._model = model
    self._preprocessor = preprocessor
    self._class_names = load_iris().target_names

  def predict(self, instances, **kwargs):
    inputs = np.asarray(instances)
    preprocessed_inputs = self._preprocessor.preprocess(inputs)
    if kwargs.get('probabilities'):
      probabilities = self._model.predict_proba(preprocessed_inputs)
      return probabilities.tolist()
    else:
      outputs = self._model.predict(preprocessed_inputs)
      return [self._class_names[class_num] for class_num in outputs]

  @classmethod
  def from_path(cls, model_dir):
    model_path = os.path.join(model_dir, 'model.joblib')
    model = joblib.load(model_path)

    preprocessor_path = os.path.join(model_dir, 'preprocessor.pkl')
    with open(preprocessor_path, 'rb') as f:
      preprocessor = pickle.load(f)

    return cls(model, preprocessor)

この予測器は、トレーニング中に定義したプリプロセッサを使用するだけでなく、予測出力をクラス インデックス(01 または 2)からラベル文字列(花の種類の名前)に変換する後処理も行います。

ただし、予測器が値 True を含む probabilities キーワード引数を受け取った場合、代わりに確率配列を返し、3 つのクラスが正しいラベルに変換される確率を示します(確率はモデルによって異なります)。このチュートリアルの最後の部分で、予測中にキーワード引数を指定する方法を説明します。

カスタムコードのパッケージ化

カスタムコードを使用して予測を提供できるように、predictor.pypreprocess.py.tar.gz ソース配布パッケージとしてパッケージ化して AI Platform Prediction に提供する必要があります。

以下の setup.py を記述してパッケージを定義します。

from setuptools import setup

setup(
    name='my_custom_code',
    version='0.1',
    scripts=['predictor.py', 'preprocess.py'])

次のコマンドを実行して dist/my_custom_code-0.1.tar.gz を作成します。

python setup.py sdist --formats=gztar

モデル アーティファクトとカスタムコードを Cloud Storage にアップロードする

提供するモデルをデプロイする前に、Cloud Storage 内の次のファイルを AI Platform Prediction からアクセスできるようにする必要があります。

  • model.joblib(モデル アーティファクト)
  • preprocessor.pkl(モデル アーティファクト)
  • my_custom_code-0.1.tar.gz(カスタムコード)

モデル アーティファクトは、モデル ディレクトリにまとめて保存する必要があります。予測器は、from_path クラスメソッドの model_dir 引数を使用してこのディレクトリにアクセスできます。カスタムコードは同じディレクトリに保存する必要はありません。次のコマンドを実行して、ファイルをアップロードします。

gsutil cp ./dist/my_custom_code-0.1.tar.gz gs://$BUCKET_NAME/custom_prediction_routine_tutorial/my_custom_code-0.1.tar.gz
gsutil cp model.joblib preprocessor.pkl gs://$BUCKET_NAME/custom_prediction_routine_tutorial/model/

カスタム予測ルーチンのデプロイ

モデルリソースとバージョン リソースを作成して、カスタム予測ルーチンをデプロイします。最初に自分のリソース名で環境変数を定義します。

MODEL_NAME='IrisPredictor'
VERSION_NAME='v1'

次にモデルを作成します。

gcloud ai-platform models create $MODEL_NAME \
  --regions $REGION

バージョンを作成します。Cloud Storage にアップロードしたアーティファクトとカスタムコードへのパスを指定します。

gcloud components install beta

gcloud beta ai-platform versions create $VERSION_NAME \
  --model $MODEL_NAME \
  --runtime-version 1.13 \
  --python-version 3.5 \
  --origin gs://$BUCKET_NAME/custom_prediction_routine_tutorial/model/ \
  --package-uris gs://$BUCKET_NAME/custom_prediction_routine_tutorial/my_custom_code-0.1.tar.gz \
  --prediction-class predictor.MyPredictor

カスタム予測ルーチンのデプロイで使用できるオプションについては、指定する必要があるオプションをご覧ください。

オンライン予測を提供する

オンライン予測リクエストを送信してデプロイメントを試してみましょう。まず、Python 用の Google API クライアント ライブラリをインストールします。

pip install --upgrade google-api-python-client

次に、デプロイしたバージョンに Iris データの 2 つのインスタンスを送信します。

import googleapiclient.discovery

instances = [
  [6.7, 3.1, 4.7, 1.5],
  [4.6, 3.1, 1.5, 0.2],
]

service = googleapiclient.discovery.build('ml', 'v1')
name = 'projects/{}/models/{}/versions/{}'.format(PROJECT_ID, MODEL_NAME, VERSION_NAME)

response = service.projects().predict(
    name=name,
    body={'instances': instances}
).execute()

if 'error' in response:
    raise RuntimeError(response['error'])
else:
  print(response['predictions'])
['versicolor', 'setosa']

キーワード引数の送信

カスタム予測ルーチンに予測リクエストを送信するときに、リクエスト本文に追加のフィールドを指定できます。予測器の predict メソッドが、これらを **kwargs ディクショナリのフィールドとして受け取ります。

次のコードは、以前と同じリクエストを送信しますが、今回はリクエスト本文に probabilities フィールドが追加されています。

response = service.projects().predict(
    name=name,
    body={'instances': instances, 'probabilities': True}
).execute()

if 'error' in response:
    raise RuntimeError(response['error'])
else:
  print(response['predictions'])
[[0.0, 1.0, 0.0], [1.0, 0.0, 0.0]]

クリーンアップ

このプロジェクトで使用しているすべての GCP リソースをクリーンアップするには、チュートリアルで使用した GCP プロジェクトを削除します。

また、以下のコマンドを実行して、個々のリソースを別々にクリーンアップすることもできます。

# Delete version resource
gcloud ai-platform versions delete $VERSION_NAME --quiet --model $MODEL_NAME

# Delete model resource
gcloud ai-platform models delete $MODEL_NAME --quiet

# Delete Cloud Storage objects that were created
gsutil -m rm -r gs://$BUCKET_NAME/custom_prediction_routine_tutorial

次のステップ