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

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

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

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

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

  • ローカルで簡単な Keras モデルをトレーニングする
  • カスタム予測ルーチンを作成して 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
  • Google Cloud SDK

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

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

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

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

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

Google Cloud プロジェクトの設定

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the AI Platform Training & Prediction and Compute Engine APIs.

    Enable the APIs

  5. Install the Google Cloud CLI.
  6. To initialize the gcloud CLI, run the following command:

    gcloud init
  7. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  8. Make sure that billing is enabled for your Google Cloud project.

  9. Enable the AI Platform Training & Prediction and Compute Engine APIs.

    Enable the APIs

  10. Install the Google Cloud CLI.
  11. To initialize the gcloud CLI, run the following command:

    gcloud init

GCP アカウントの認証

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

  1. サービス アカウントを作成します。

    1. Google Cloud コンソールで [サービス アカウントの作成] ページに移動します。

      [サービス アカウントの作成] に移動

    2. [サービス アカウント名] フィールドに名前を入力します。
    3. 省略可: [サービス アカウントの説明] フィールドに説明を入力します。
    4. [作成] をクリックします。
    5. [ロールを選択] フィールドをクリックします。[すべてのロール] で、[AI Platform] > [AI Platform 管理者] の順に選択します。
    6. [別の役割を追加] をクリックします。
    7. [ロールを選択] フィールドをクリックします。[すべてのロール] で、[Cloud Storage] > [ストレージ オブジェクト管理者] を選択します。

    8. [完了] をクリックして、サービス アカウントを作成します。

      ブラウザ ウィンドウは閉じないでください。次のステップでこれを使用します。

  2. 認証に使用するサービス アカウント キーを作成します。

    1. Google Cloud コンソールで、作成したサービス アカウントのメールアドレスをクリックします。
    2. [キー] をクリックします。
    3. [鍵を追加]、[新しい鍵を作成] の順にクリックします。
    4. [作成] をクリックします。JSON キーファイルがパソコンにダウンロードされます。
    5. [閉じる] をクリックします。
  3. 環境変数 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 バケットを作成し、後のトレーニングと予測で同じリージョンを使用します。そのバケットが存在しない場合は、次のコマンドを実行して作成します。

gcloud storage buckets create gs://$BUCKET_NAME --location=$REGION

Keras モデルの構築とトレーニング

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

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

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

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

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

pip install numpy scikit-learn 'tensorflow=2.3'

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

各数値特徴列の平均値が 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 データを前処理し、Keras を使用して簡単なニューラル ネットワークをトレーニングします。

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

import pickle

from sklearn.datasets import load_iris
import tensorflow as tf

from preprocess import MySimpleScaler

iris = load_iris()
scaler = MySimpleScaler()
num_classes = len(iris.target_names)
X = scaler.preprocess(iris.data)
y = tf.keras.utils.to_categorical(iris.target, num_classes=num_classes)

model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(25, activation=tf.nn.relu))
model.add(tf.keras.layers.Dense(25, activation=tf.nn.relu))
model.add(tf.keras.layers.Dense(num_classes, activation=tf.nn.softmax))
model.compile(
  optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(X, y, epochs=10, batch_size=1)

model.save('model.h5')
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
import tensorflow as tf

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)
    outputs = self._model.predict(preprocessed_inputs)
    if kwargs.get('probabilities'):
      return outputs.tolist()
    else:
      return [self._class_names[index] for index in np.argmax(outputs, axis=1)]

  @classmethod
  def from_path(cls, model_dir):
    model_path = os.path.join(model_dir, 'model.h5')
    model = tf.keras.models.load_model(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)

この予測器は、トレーニング中に定義したプリプロセッサを使用するだけでなく、ニューラル ネットワークのソフトマックス出力(各ラベルが正しい確率を示す配列)を最も可能性の高いラベルで変換する後処理も行います。

ただし、予測器が値 True を含む probabilities キーワード引数を受け取った場合、代わりに確率配列を返します。このチュートリアルの最後の部分で、このキーワード引数を指定する方法を説明します。

カスタムコードをパッケージ化する

カスタムコードを使用して予測を提供できるように、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.h5(モデル アーティファクト)
  • preprocessor.pkl(モデル アーティファクト)
  • my_custom_code-0.1.tar.gz(カスタムコード)

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

gcloud storage cp ./dist/my_custom_code-0.1.tar.gz gs://$BUCKET_NAME/custom_prediction_routine_tutorial/my_custom_code-0.1.tar.gz
gcloud storage cp model.h5 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 2.3 \
  --python-version 3.7 \
  --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.0019204545533284545, 0.8623144626617432, 0.13576509058475494], [0.999488353729248, 0.000511515187099576, 1.293626752385535e-07]]

クリーンアップ

このプロジェクトで使用しているすべての 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
gcloud storage rm gs://$BUCKET_NAME/custom_prediction_routine_tutorial --recursive

次のステップ