スタートガイド: Keras によるトレーニングと予測

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

このチュートリアルでは、Keras シーケンシャル API を使用して AI Platform でニューラル ネットワークをトレーニングする方法と、そのモデルから予測を提供する方法について説明します。

Keras は、ディープ ラーニング モデルを構築してトレーニングするための高レベル API です。tf.keras は TensorFlow によるこの API の実装です。

チュートリアルの最初の 2 つの部分では、事前に作成した Keras コードを使用して AI Platform 上でモデルをトレーニングし、そのトレーニング済みモデルを AI Platform にデプロイします。さらに、デプロイしたモデルからオンライン予測を提供します。

チュートリアルの最後の部分では、このモデルで使用しているトレーニング コードの詳細を示し、AI Platform との互換性を確認します。より汎用性がある方法で Keras による機械学習モデルを構築するには、Keras に関する TensorFlow のチュートリアルをご覧ください。

データセット

このチュートリアルでは、UC Irvine Machine Learning Repository が提供する米国国勢調査の所得データセットを使用します。このデータセットには、1994 年の国勢調査データベースから得られた情報が収録されています。年齢、学歴、配偶者の有無、職種、年収が $50,000 以上あるかどうかなどの情報が含まれます。

目標

ここでの目的は、Keras を使用してディープ ニューラル ネットワーク(DNN)をトレーニングすることにあります。この場合、対象者に関して国勢調査情報にある年収以外の情報(特徴)に基づき、その人の年収(ターゲット ラベル)が $50,000 以上になるかどうかを予測します。

このチュートリアルでは、モデル自体の設計よりも、AI Platform でこのモデルを使用することに重点を置きます。ただし、機械学習システムの構築では、問題や意図しない結果が生じる可能性があることを常に意識する必要があります。国勢調査のデータセットに偏りが生じる原因や、機械学習の公平性に関する一般的な説明については、公平性に関する機械学習集中講座をご覧ください。

費用

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

  • AI Platform Training
  • AI Platform Prediction
  • Cloud Storage

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

始める前に

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

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

ローカル開発環境の設定

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

  • Git
  • Python 3
  • virtualenv
  • Google Cloud SDK

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

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

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

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

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

Google Cloud プロジェクトの設定

  1. Google Cloud アカウントにログインします。Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

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

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

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

    API を有効にする

  5. Google Cloud CLI をインストールします。
  6. gcloud CLI を初期化するには:

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

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

  8. Google Cloud プロジェクトで課金が有効になっていることを確認します

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

    API を有効にする

  10. Google Cloud CLI をインストールします。
  11. gcloud CLI を初期化するには:

    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 SDK を使用してトレーニング ジョブを送信するときは、トレーニング コードを収めた Python パッケージを Cloud Storage バケットにアップロードします。AI Platform では、このパッケージからコードが実行されます。このチュートリアルでは、ジョブで得られたトレーニング済みモデルも、AI Platform によって同じバケットに保存されます。オンライン予測で使用できるように、この出力に基づいて AI Platform バージョンのモデルを作成できます。

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

BUCKET_NAME="your-bucket-name"

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

REGION="us-central1"

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

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

AI Platform でのトレーニングのクイックスタート

チュートリアルのこのセクションでは、AI Platform にトレーニング ジョブを送信する方法について説明します。このジョブでは、Keras を使用して米国の国勢調査データに関するディープ ニューラル ネットワークをトレーニングするサンプルコードを実行します。このコードでは、トレーニング済みモデルが TensorFlow の SavedModel ディレクトリとして Cloud Storage バケットに出力されます。

トレーニング コードと依存関係の入手

まず、次のように、トレーニング コードをダウンロードして作業ディレクトリを変更します。

# Clone the repository of AI Platform samples
git clone --depth 1 https://github.com/GoogleCloudPlatform/cloudml-samples

# Set the working directory to the sample code directory
cd cloudml-samples/census/tf-keras

トレーニング コードは、次のように、trainer/ サブディレクトリで Python パッケージとして構造化されています。

# `ls` shows the working directory's contents. The `p` flag adds trailing
# slashes to subdirectory names. The `R` flag lists subdirectories recursively.
ls -pR
.:
README.md  requirements.txt  trainer/

./trainer:
__init__.py  model.py  task.py  util.py

次に、モデルをローカルでトレーニングするために必要な Python の依存関係をインストールします。

pip install -r requirements.txt

AI Platform でトレーニング ジョブを実施する場合は、選択したランタイム バージョンに基づいて依存関係がプリインストールされます。

ローカルでのモデルのトレーニング

AI Platform 上でトレーニングする前に、ジョブをローカルでトレーニングして、ファイル構造とパッケージングが正しいことを確認します。

複雑なジョブやリソースを大量に消費するジョブでは、データセットの小規模なサンプルのトレーニングをローカルで実施して、コードの動作を検証することをおすすめします。その検証でコードに問題がないことを確認すれば、AI Platform 上でジョブを実行して、データセット全体をトレーニングできます。

このサンプルでは、小型のデータセットに対して比較的短時間で終了する作業を実行します。したがって、ローカルでのトレーニングと AI Platform によるジョブでは、同じデータに対して同じコードを実行します。

次のコマンドを実行して、モデルをローカルでトレーニングします。

# This is similar to `python -m trainer.task --job-dir local-training-output`
# but it better replicates the AI Platform environment, especially
# for distributed training (not applicable here).
gcloud ai-platform local train \
  --package-path trainer \
  --module-name trainer.task \
  --job-dir local-training-output

トレーニングの進行をシェルで確認します。最後に、トレーニング アプリケーションからトレーニング済みモデルがエクスポートされ、次のようなメッセージが出力されます。

Model exported to:  local-training-output/keras_export/1553709223

AI Platform によるモデルのトレーニング

次に、AI Platform にトレーニング ジョブを送信します。これにより、クラウドでトレーニング モジュールが実行され、トレーニング済みモデルが Cloud Storage にエクスポートされます。

まず、トレーニング ジョブに名前を付け、中間ファイルと出力ファイルを保存するディレクトリを Cloud Storage バケットの中で選択します。これらを環境変数として設定します。例:

JOB_NAME="my_first_keras_job"
JOB_DIR="gs://$BUCKET_NAME/keras-job-dir"

次のコマンドを実行し、trainer/ ディレクトリをパッケージにして、指定した --job-dir にアップロードします。そして、AI Platform にそのパッケージから trainer.task モジュールを実行させます。

--stream-logs フラグを使用すると、シェルにトレーニング ログを表示できます。Google Cloud Console で、ログやその他のジョブの詳細を確認することもできます。

gcloud ai-platform jobs submit training $JOB_NAME \
  --package-path trainer/ \
  --module-name trainer.task \
  --region $REGION \
  --python-version 3.7 \
  --runtime-version 1.15 \
  --job-dir $JOB_DIR \
  --stream-logs

この作業は、ローカルでのトレーニングよりも時間を要する可能性がありますが、トレーニングの進捗状況をローカル同様にシェルで確認できます。最後に、トレーニング ジョブによって、トレーニング済みモデルが Cloud Storage バケットにエクスポートされ、次のようなメッセージが表示されます。

INFO    2019-03-27 17:57:11 +0000   master-replica-0        Model exported to:  gs://your-bucket-name/keras-job-dir/keras_export/1553709421
INFO    2019-03-27 17:57:11 +0000   master-replica-0        Module completed; cleaning up.
INFO    2019-03-27 17:57:11 +0000   master-replica-0        Clean up finished.
INFO    2019-03-27 17:57:11 +0000   master-replica-0        Task completed successfully.

ハイパーパラメータ調整

付属の hptuning_config.yaml 構成ファイルを使用して、ハイパーパラメータを調整することもできます。AI Platform は、この構成ファイルの指示に従ってバッチサイズと学習率を調整して、複数回にわたるトレーニングのトライアルで最大限の正確性を実現できるようにします。

この例で、トレーニング コードが使用する TensorBoard コールバックは、トレーニング中に TensorFlow Summary Event を作成します。AI Platform はこれらのイベントを使用して、最適化する指標を追跡します。詳しくは、AI Platform トレーニングでのハイパーパラメータ調整をご覧ください。

gcloud ai-platform jobs submit training ${JOB_NAME}_hpt \
  --config hptuning_config.yaml \
  --package-path trainer/ \
  --module-name trainer.task \
  --region $REGION \
  --python-version 3.7 \
  --runtime-version 1.15 \
  --job-dir $JOB_DIR \
  --stream-logs

AI Platform でのオンライン予測のクイックスタート

このセクションでは、AI Platform および前のセクションでトレーニングしたモデルを使用し、収入以外の国勢調査情報に基づいて個人の収入の範囲を予測する方法を示します。

AI Platform でのモデルとバージョンのリソースの作成

トレーニングのクイックスタートでトレーニングしてエクスポートしたモデルを使用してオンライン予測を提供するには、AI Platform でモデルリソースを作成し、そこにバージョンのリソースを作成します。バージョンのリソースとは、トレーニング済みのモデルを使用して実際に予測を提供するリソースです。この構造により、モデルの調整と再トレーニングを何回も実施でき、すべてのバージョンをまとめて API Platform で整理できます。詳細については、モデルとバージョンをご覧ください。

まず、名前を付けてモデルリソースを作成します。

MODEL_NAME="my_first_keras_model"

gcloud ai-platform models create $MODEL_NAME \
  --regions $REGION
Created ml engine model [projects/your-project-id/models/my_first_keras_model].

次に、モデルのバージョンを作成します。トレーニングのクイックスタートで実行したトレーニング ジョブでは、TensorFlow の SavedModel ディレクトリがタイムスタンプ付きで Cloud Storage バケットにエクスポートされました。API Platform では、このディレクトリを使用してモデルのバージョンが作成されます。詳細については、SavedModel と AI Platform をご覧ください。

トレーニング ジョグのログに、このディレクトリへのパスが記述されています。この記述は次のような行です。

Model exported to:  gs://your-bucket-name/keras-job-dir/keras_export/1545439782

次のコマンドを実行して SavedModel ディレクトリを特定し、そのディレクトリを使用してモデルのバージョンのリソースを作成します。

MODEL_VERSION="v1"

# Get a list of directories in the `keras_export` parent directory. Then pick
# the directory with the latest timestamp, in case you've trained multiple
# times.
SAVED_MODEL_PATH=$(gsutil ls $JOB_DIR/keras_export | head -n 1)

# Create model version based on that SavedModel directory
gcloud ai-platform versions create $MODEL_VERSION \
  --model $MODEL_NAME \
  --region $REGION \
  --runtime-version 1.15 \
  --python-version 3.7 \
  --framework tensorflow \
  --origin $SAVED_MODEL_PATH

予測に使用する入力の準備

有効で有用な予測を受け取るには、トレーニング データの前処理と同様の方法で、予測に使用する入力を前処理する必要があります。本番環境のシステムでは、トレーニング時と予測時とで同じように使用できる前処理パイプラインを作成できます。

この演習では、評価パッケージからサンプルを無作為に選択するために、トレーニング パッケージのデータ読み込みコードを使用します。このデータの形式は、トレーニングのエポックが終了するたびに実施された精度評価における形式と同じなので、それ以上の前処理を適用しなくても、テスト予測の送信に使用できます。

Python インタプリタ(python)を現在の作業ディレクトリから開き、コードの次のいくつかのスニペットを実行します。

from trainer import util

_, _, eval_x, eval_y = util.load_data()

prediction_input = eval_x.sample(20)
prediction_targets = eval_y[prediction_input.index]

prediction_input
age workclass education_num marital_status occupation relationship race capital_gain capital_loss hours_per_week native_country
1979 0.901213 1 1.525542 2 9 0 4 -0.144792 -0.217132 -0.437544 38
2430 -0.922154 3 -0.419265 4 2 3 4 -0.144792 -0.217132 -0.034039 38
4214 -1.213893 3 -0.030304 4 10 1 4 -0.144792 -0.217132 1.579979 38
10389 -0.630415 3 0.358658 4 0 3 4 -0.144792 -0.217132 -0.679647 38
14525 -1.505632 3 -1.586149 4 7 3 0 -0.144792 -0.217132 -0.034039 38
15040 -0.119873 5 0.358658 2 2 0 4 -0.144792 -0.217132 -0.841048 38
8409 0.244801 3 1.525542 2 9 0 4 -0.144792 -0.217132 1.176475 6
10628 0.098931 1 1.525542 2 9 0 4 0.886847 -0.217132 -0.034039 38
10942 0.390670 5 -0.030304 2 4 0 4 -0.144792 -0.217132 4.727315 38
5129 1.120017 3 1.136580 2 12 0 4 -0.144792 -0.217132 -0.034039 38
2096 -1.286827 3 -0.030304 4 11 3 4 -0.144792 -0.217132 -1.648058 38
12463 -0.703350 3 -0.419265 2 7 5 4 -0.144792 4.502280 -0.437544 38
8528 0.536539 3 1.525542 4 3 4 4 -0.144792 -0.217132 -0.034039 38
7093 -1.359762 3 -0.419265 4 6 3 2 -0.144792 -0.217132 -0.034039 38
12565 0.536539 3 1.136580 0 11 2 2 -0.144792 -0.217132 -0.034039 38
5655 1.338821 3 -0.419265 2 2 0 4 -0.144792 -0.217132 -0.034039 38
2322 0.682409 3 1.136580 0 12 3 4 -0.144792 -0.217132 -0.034039 38
12652 0.025997 3 1.136580 2 11 0 4 -0.144792 -0.217132 0.369465 38
4755 -0.411611 3 -0.419265 2 11 0 4 -0.144792 -0.217132 1.176475 38
4413 0.390670 6 1.136580 4 4 1 4 -0.144792 -0.217132 -0.034039 38

occupation などのカテゴリ フィールドは、(トレーニングで使用されたものと同じマッピングを使用して)すでに整数に変換されています。age などの数値フィールドは、Z スコアにスケーリングされています。フィールドによっては、元のデータから削除されているものがあります。上記と同じ例で、次のように予測入力を生データと比較します。

import pandas as pd

_, eval_file_path = util.download(util.DATA_DIR)
raw_eval_data = pd.read_csv(eval_file_path,
                            names=util._CSV_COLUMNS,
                            na_values='?')

raw_eval_data.iloc[prediction_input.index]
age workclass fnlwgt education education_num marital_status occupation relationship race gender capital_gain capital_loss hours_per_week native_country income_bracket
1979 51 Local-gov 99064 Masters 14 Married-civ-spouse Prof-specialty Husband White Male 0 0 35 United-States <=50K
2430 26 Private 197967 HS-grad 9 Never-married Craft-repair Own-child White Male 0 0 40 United-States <=50K
4214 22 Private 221694 Some-college 10 Never-married Protective-serv Not-in-family White Male 0 0 60 United-States <=50K
10389 30 Private 96480 Assoc-voc 11 Never-married Adm-clerical Own-child White Female 0 0 32 United-States <=50K
14525 18 Private 146225 10th 6 Never-married Other-service Own-child Amer-Indian-Eskimo Female 0 0 40 United-States <=50K
15040 37 Self-emp-not-inc 50096 Assoc-voc 11 Married-civ-spouse Craft-repair Husband White Male 0 0 30 United-States <=50K
8409 42 Private 102988 Masters 14 Married-civ-spouse Prof-specialty Husband White Male 0 0 55 Ecuador >50K
10628 40 Local-gov 284086 Masters 14 Married-civ-spouse Prof-specialty Husband White Male 7688 0 40 United-States >50K
10942 44 Self-emp-not-inc 52505 Some-college 10 Married-civ-spouse Farming-fishing Husband White Male 0 0 99 United-States <=50K
5129 54 Private 106728 Bachelors 13 Married-civ-spouse Tech-support Husband White Male 0 0 40 United-States <=50K
2096 21 Private 190916 Some-college 10 Never-married Sales Own-child White Female 0 0 20 United-States <=50K
12463 29 Private 197565 HS-grad 9 Married-civ-spouse Other-service Wife White Female 0 1902 35 United-States >50K
8528 46 Private 193188 Masters 14 Never-married Exec-managerial Unmarried White Male 0 0 40 United-States <=50K
7093 20 Private 273147 HS-grad 9 Never-married Machine-op-inspct Own-child Black Male 0 0 40 United-States <=50K
12565 46 Private 203653 Bachelors 13 Divorced Sales Other-relative Black Male 0 0 40 United-States <=50K
5655 57 Private 174662 HS-grad 9 Married-civ-spouse Craft-repair Husband White Male 0 0 40 United-States <=50K
2322 48 Private 232149 Bachelors 13 Divorced Tech-support Own-child White Female 0 0 40 United-States <=50K
12652 39 Private 82521 Bachelors 13 Married-civ-spouse Sales Husband White Male 0 0 45 United-States >50K
4755 33 Private 330715 HS-grad 9 Married-civ-spouse Sales Husband White Male 0 0 55 United-States <=50K
4413 44 State-gov 128586 Bachelors 13 Never-married Farming-fishing Not-in-family White Male 0 0 40 United-States <=50K

改行区切りの JSON ファイルに予測入力をエクスポートします。

import json

with open('prediction_input.json', 'w') as json_file:
  for row in prediction_input.values.tolist():
    json.dump(row, json_file)
    json_file.write('\n')

Python インタプリタを終了します(exit())。シェルから、prediction_input.json を調べます。

cat prediction_input.json
[0.9012127751273994, 1.0, 1.525541514460902, 2.0, 9.0, 0.0, 4.0, -0.14479173735784842, -0.21713186390175285, -0.43754385253479555, 38.0]
[-0.9221541171760282, 3.0, -0.4192650914017433, 4.0, 2.0, 3.0, 4.0, -0.14479173735784842, -0.21713186390175285, -0.03403923708700391, 38.0]
[-1.2138928199445767, 3.0, -0.030303770229214273, 4.0, 10.0, 1.0, 4.0, -0.14479173735784842, -0.21713186390175285, 1.5799792247041626, 38.0]
[-0.6304154144074798, 3.0, 0.35865755094331475, 4.0, 0.0, 3.0, 4.0, -0.14479173735784842, -0.21713186390175285, -0.6796466218034705, 38.0]
[-1.5056315227131252, 3.0, -1.5861490549193304, 4.0, 7.0, 3.0, 0.0, -0.14479173735784842, -0.21713186390175285, -0.03403923708700391, 38.0]
[-0.11987268456252011, 5.0, 0.35865755094331475, 2.0, 2.0, 0.0, 4.0, -0.14479173735784842, -0.21713186390175285, -0.8410484679825871, 38.0]
[0.24480069389816542, 3.0, 1.525541514460902, 2.0, 9.0, 0.0, 4.0, -0.14479173735784842, -0.21713186390175285, 1.176474609256371, 6.0]
[0.0989313425138912, 1.0, 1.525541514460902, 2.0, 9.0, 0.0, 4.0, 0.8868473744801746, -0.21713186390175285, -0.03403923708700391, 38.0]
[0.39067004528243965, 5.0, -0.030303770229214273, 2.0, 4.0, 0.0, 4.0, -0.14479173735784842, -0.21713186390175285, 4.7273152251969375, 38.0]
[1.1200168022038106, 3.0, 1.1365801932883728, 2.0, 12.0, 0.0, 4.0, -0.14479173735784842, -0.21713186390175285, -0.03403923708700391, 38.0]
[-1.2868274956367138, 3.0, -0.030303770229214273, 4.0, 11.0, 3.0, 4.0, -0.14479173735784842, -0.21713186390175285, -1.6480576988781703, 38.0]
[-0.7033500900996169, 3.0, -0.4192650914017433, 2.0, 7.0, 5.0, 4.0, -0.14479173735784842, 4.5022796885373735, -0.43754385253479555, 38.0]
[0.5365393966667138, 3.0, 1.525541514460902, 4.0, 3.0, 4.0, 4.0, -0.14479173735784842, -0.21713186390175285, -0.03403923708700391, 38.0]
[-1.3597621713288508, 3.0, -0.4192650914017433, 4.0, 6.0, 3.0, 2.0, -0.14479173735784842, -0.21713186390175285, -0.03403923708700391, 38.0]
[0.5365393966667138, 3.0, 1.1365801932883728, 0.0, 11.0, 2.0, 2.0, -0.14479173735784842, -0.21713186390175285, -0.03403923708700391, 38.0]
[1.338820829280222, 3.0, -0.4192650914017433, 2.0, 2.0, 0.0, 4.0, -0.14479173735784842, -0.21713186390175285, -0.03403923708700391, 38.0]
[0.6824087480509881, 3.0, 1.1365801932883728, 0.0, 12.0, 3.0, 4.0, -0.14479173735784842, -0.21713186390175285, -0.03403923708700391, 38.0]
[0.0259966668217541, 3.0, 1.1365801932883728, 2.0, 11.0, 0.0, 4.0, -0.14479173735784842, -0.21713186390175285, 0.3694653783607877, 38.0]
[-0.4116113873310685, 3.0, -0.4192650914017433, 2.0, 11.0, 0.0, 4.0, -0.14479173735784842, -0.21713186390175285, 1.176474609256371, 38.0]
[0.39067004528243965, 6.0, 1.1365801932883728, 4.0, 4.0, 1.0, 4.0, -0.14479173735784842, -0.21713186390175285, -0.03403923708700391, 38.0]

gcloud コマンドライン ツールは、オンライン予測用の改行で区切られた JSON を受け付けます。この特殊な Keras モデルでは、各入力例が数字のフラットリストになっていると想定します。

gcloud ツールを使用せずに REST API にオンライン予測をリクエストする場合、AI Platform では異なる形式にする必要があります。モデルの構築方法でも、予測向けにデータの形式を設定する方法が変わる場合があります。詳細については、オンライン予測に向けたデータの形式設定をご覧ください。

オンライン予測リクエストの送信

次のように、gcloud を使用してオンライン予測リクエストを送信します。

gcloud ai-platform predict \
  --model $MODEL_NAME \
  --region $REGION \
  --version $MODEL_VERSION \
  --json-instances prediction_input.json
DENSE_4
[0.6854287385940552]
[0.011786997318267822]
[0.037236183881759644]
[0.016223609447479248]
[0.0012015104293823242]
[0.23621389269828796]
[0.6174039244651794]
[0.9822691679000854]
[0.3815768361091614]
[0.6715215444564819]
[0.001094043254852295]
[0.43077391386032104]
[0.22132840752601624]
[0.004075437784194946]
[0.22736871242523193]
[0.4111979305744171]
[0.27328649163246155]
[0.6981356143951416]
[0.3309604525566101]
[0.20807647705078125]

モデルにある最後のレイヤでは、そのアクティベーションに sigmoid 関数を使用するので、0 から 0.5 の範囲の出力は負の予測("<= 50K")を表し、0.5 から 1 の範囲の出力は正の予測("> 50K")を表します。

Keras モデルの新規作成

ここまでで、AI Platform 上で機械学習モデルをトレーニングし、そのトレーニング済みモデルを AI Platform 上にバージョン リソースとしてデプロイして、そのデプロイメントからオンライン予測を受け取りました。次のセクションでは、このモデルのトレーニングに使用する Keras コードを再作成する方法について説明します。AI Platform のユーザー向けに機械学習モデルを開発する作業のうち、以下の部分について説明します。

  • データのダウンロードと前処理
  • モデルの設計とトレーニング
  • トレーニングの可視化とトレーニング済みモデルのエクスポート

このセクションでは、前の部分で完了したタスクを詳しく考察していますが、tf.keras の詳細については、TensorFlow の Keras ガイドをご覧ください。AI Platform 用のトレーニング パッケージとしてコードを構造化する方法の詳細については、トレーニング アプリケーションのパッケージングをご覧ください。また、Python パッケージとして構造化されたすべてのトレーニング コードも参照してください。

ライブラリのインポートと定数の定義

まず、次のように、トレーニングに必要な Python ライブラリをインポートします。

import os
from six.moves import urllib
import tempfile

import numpy as np
import pandas as pd
import tensorflow as tf

# Examine software versions
print(__import__('sys').version)
print(tf.__version__)
print(tf.keras.__version__)

続いて、次の有用な情報を定数として定義します。

  • トレーニングと評価のデータをダウンロードするための情報
  • pandas でデータを解釈し、カテゴリ フィールドを数値特徴に変換するために必要な情報
  • トレーニング用のハイパーパラメータ(学習率やバッチサイズなど)
### For downloading data ###

# Storage directory
DATA_DIR = os.path.join(tempfile.gettempdir(), 'census_data')

# Download options.
DATA_URL = 'https://storage.googleapis.com/cloud-samples-data/ai-platform' \
           '/census/data'
TRAINING_FILE = 'adult.data.csv'
EVAL_FILE = 'adult.test.csv'
TRAINING_URL = '%s/%s' % (DATA_URL, TRAINING_FILE)
EVAL_URL = '%s/%s' % (DATA_URL, EVAL_FILE)

### For interpreting data ###

# These are the features in the dataset.
# Dataset information: https://archive.ics.uci.edu/ml/datasets/census+income
_CSV_COLUMNS = [
    'age', 'workclass', 'fnlwgt', 'education', 'education_num',
    'marital_status', 'occupation', 'relationship', 'race', 'gender',
    'capital_gain', 'capital_loss', 'hours_per_week', 'native_country',
    'income_bracket'
]

_CATEGORICAL_TYPES = {
  'workclass': pd.api.types.CategoricalDtype(categories=[
    'Federal-gov', 'Local-gov', 'Never-worked', 'Private', 'Self-emp-inc',
    'Self-emp-not-inc', 'State-gov', 'Without-pay'
  ]),
  'marital_status': pd.api.types.CategoricalDtype(categories=[
    'Divorced', 'Married-AF-spouse', 'Married-civ-spouse',
    'Married-spouse-absent', 'Never-married', 'Separated', 'Widowed'
  ]),
  'occupation': pd.api.types.CategoricalDtype([
    'Adm-clerical', 'Armed-Forces', 'Craft-repair', 'Exec-managerial',
    'Farming-fishing', 'Handlers-cleaners', 'Machine-op-inspct',
    'Other-service', 'Priv-house-serv', 'Prof-specialty', 'Protective-serv',
    'Sales', 'Tech-support', 'Transport-moving'
  ]),
  'relationship': pd.api.types.CategoricalDtype(categories=[
    'Husband', 'Not-in-family', 'Other-relative', 'Own-child', 'Unmarried',
    'Wife'
  ]),
  'race': pd.api.types.CategoricalDtype(categories=[
    'Amer-Indian-Eskimo', 'Asian-Pac-Islander', 'Black', 'Other', 'White'
  ]),
  'native_country': pd.api.types.CategoricalDtype(categories=[
    'Cambodia', 'Canada', 'China', 'Columbia', 'Cuba', 'Dominican-Republic',
    'Ecuador', 'El-Salvador', 'England', 'France', 'Germany', 'Greece',
    'Guatemala', 'Haiti', 'Holand-Netherlands', 'Honduras', 'Hong', 'Hungary',
    'India', 'Iran', 'Ireland', 'Italy', 'Jamaica', 'Japan', 'Laos', 'Mexico',
    'Nicaragua', 'Outlying-US(Guam-USVI-etc)', 'Peru', 'Philippines', 'Poland',
    'Portugal', 'Puerto-Rico', 'Scotland', 'South', 'Taiwan', 'Thailand',
    'Trinadad&Tobago', 'United-States', 'Vietnam', 'Yugoslavia'
  ]),
  'income_bracket': pd.api.types.CategoricalDtype(categories=[
    '<=50K', '>50K'
  ])
}

# This is the label (target) we want to predict.
_LABEL_COLUMN = 'income_bracket'

### Hyperparameters for training ###

# This the training batch size
BATCH_SIZE = 128

# This is the number of epochs (passes over the full training data)
NUM_EPOCHS = 20

# Define learning rate.
LEARNING_RATE = .01

データのダウンロードと前処理

データのダウンロード

次に、トレーニング データと評価データをダウンロードする各種関数を定義します。これらの関数では、データの形式設定にあるわずかな不規則性も修正されます。

def _download_and_clean_file(filename, url):
  """Downloads data from url, and makes changes to match the CSV format.

  The CSVs may use spaces after the comma delimters (non-standard) or include
  rows which do not represent well-formed examples. This function strips out
  some of these problems.

  Args:
    filename: filename to save url to
    url: URL of resource to download
  """
  temp_file, _ = urllib.request.urlretrieve(url)
  with tf.gfile.Open(temp_file, 'r') as temp_file_object:
    with tf.gfile.Open(filename, 'w') as file_object:
      for line in temp_file_object:
        line = line.strip()
        line = line.replace(', ', ',')
        if not line or ',' not in line:
          continue
        if line[-1] == '.':
          line = line[:-1]
        line += '\n'
        file_object.write(line)
  tf.gfile.Remove(temp_file)

def download(data_dir):
  """Downloads census data if it is not already present.

  Args:
    data_dir: directory where we will access/save the census data
  """
  tf.gfile.MakeDirs(data_dir)

  training_file_path = os.path.join(data_dir, TRAINING_FILE)
  if not tf.gfile.Exists(training_file_path):
    _download_and_clean_file(training_file_path, TRAINING_URL)

  eval_file_path = os.path.join(data_dir, EVAL_FILE)
  if not tf.gfile.Exists(eval_file_path):
    _download_and_clean_file(eval_file_path, EVAL_URL)

  return training_file_path, eval_file_path

これらの関数を使用してトレーニング用データをダウンロードし、トレーニングと評価用の CSV ファイルが揃っていることを確認します。

training_file_path, eval_file_path = download(DATA_DIR)

次に、Pandas を使用してこれらのファイルを読み込み、そのデータを調べます。

# This census data uses the value '?' for fields (column) that are missing data.
# We use na_values to find ? and set it to NaN values.
# https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html

train_df = pd.read_csv(training_file_path, names=_CSV_COLUMNS, na_values='?')
eval_df = pd.read_csv(eval_file_path, names=_CSV_COLUMNS, na_values='?')

次の表に、前処理前のデータ(train_df.head())の抜粋を示します。

age workclass fnlwgt education education_num marital_status occupation relationship race gender capital_gain capital_loss hours_per_week native_country income_bracket
0 39 State-gov 77516 Bachelors 13 Never-married Adm-clerical Not-in-family White Male 2174 0 40 United-States <=50K
1 50 Self-emp-not-inc 83311 Bachelors 13 Married-civ-spouse Exec-managerial Husband White Male 0 0 13 United-States <=50K
2 38 Private 215646 HS-grad 9 Divorced Handlers-cleaners Not-in-family White Male 0 0 40 United-States <=50K
3 53 Private 234721 11th 7 Married-civ-spouse Handlers-cleaners Husband Black Male 0 0 40 United-States <=50K
4 28 Private 338409 Bachelors 13 Married-civ-spouse Prof-specialty Wife Black Female 0 0 40 Cuba <=50K

データの前処理

最初の前処理ステップでは、データから特定の特徴を削除し、Keras で使用できるようにカテゴリ特徴を数値に変換します。

詳細については、特徴量エンジニアリングデータのバイアスをご覧ください。

UNUSED_COLUMNS = ['fnlwgt', 'education', 'gender']

def preprocess(dataframe):
  """Converts categorical features to numeric. Removes unused columns.

  Args:
    dataframe: Pandas dataframe with raw data

  Returns:
    Dataframe with preprocessed data
  """
  dataframe = dataframe.drop(columns=UNUSED_COLUMNS)

  # Convert integer valued (numeric) columns to floating point
  numeric_columns = dataframe.select_dtypes(['int64']).columns
  dataframe[numeric_columns] = dataframe[numeric_columns].astype('float32')

  # Convert categorical columns to numeric
  cat_columns = dataframe.select_dtypes(['object']).columns
  dataframe[cat_columns] = dataframe[cat_columns].apply(lambda x: x.astype(
    _CATEGORICAL_TYPES[x.name]))
  dataframe[cat_columns] = dataframe[cat_columns].apply(lambda x: x.cat.codes)
  return dataframe

prepped_train_df = preprocess(train_df)
prepped_eval_df = preprocess(eval_df)

次のテーブル(prepped_train_df.head())は、前処理によって変更されたデータを示しています。特に、モデルが予測を行うようトレーニングしたラベル income_bracket が、<=50K>50K01 に変更されていることに注意してください。

age workclass education_num marital_status occupation relationship race capital_gain capital_loss hours_per_week native_country income_bracket
0 39.0 6 13.0 4 0 1 4 2174.0 0.0 40.0 38 0
1 50.0 5 13.0 2 3 0 4 0.0 0.0 13.0 38 0
2 38.0 3 9.0 0 5 1 4 0.0 0.0 40.0 38 0
3 53.0 3 7.0 2 5 0 2 0.0 0.0 40.0 38 0
4 28.0 3 13.0 2 9 5 2 0.0 0.0 40.0 4 0

次に、データを特徴("x")とラベル("y")に分割し、ラベル配列を後で tf.data.Dataset と使用する形式に再形成します。

# Split train and test data with labels.
# The pop() method will extract (copy) and remove the label column from the dataframe
train_x, train_y = prepped_train_df, prepped_train_df.pop(_LABEL_COLUMN)
eval_x, eval_y = prepped_eval_df, prepped_eval_df.pop(_LABEL_COLUMN)

# Reshape label columns for use with tf.data.Dataset
train_y = np.asarray(train_y).astype('float32').reshape((-1, 1))
eval_y = np.asarray(eval_y).astype('float32').reshape((-1, 1))

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

本番環境システムでは、トレーニング セットで得られた平均値と標準偏差を保存しておき、予測の際にそれらを使用して、テストデータに同一の変換を適用できます。この演習では、便宜上、トレーニング データと評価データを一時的に組み合わせ、それらをすべてスケーリングします。

def standardize(dataframe):
  """Scales numerical columns using their means and standard deviation to get
  z-scores: the mean of each numerical column becomes 0, and the standard
  deviation becomes 1. This can help the model converge during training.

  Args:
    dataframe: Pandas dataframe

  Returns:
    Input dataframe with the numerical columns scaled to z-scores
  """
  dtypes = list(zip(dataframe.dtypes.index, map(str, dataframe.dtypes)))
  # Normalize numeric columns.
  for column, dtype in dtypes:
      if dtype == 'float32':
          dataframe[column] -= dataframe[column].mean()
          dataframe[column] /= dataframe[column].std()
  return dataframe

# Join train_x and eval_x to normalize on overall means and standard
# deviations. Then separate them again.
all_x = pd.concat([train_x, eval_x], keys=['train', 'eval'])
all_x = standardize(all_x)
train_x, eval_x = all_x.xs('train'), all_x.xs('eval')

次のテーブル(train_x.head())は、すべての前処理を完了したデータを示しています。

age workclass education_num marital_status occupation relationship race capital_gain capital_loss hours_per_week native_country
0 0.025997 6 1.136580 4 0 1 4 0.146933 -0.217132 -0.034039 38
1 0.828278 5 1.136580 2 3 0 4 -0.144792 -0.217132 -2.212964 38
2 -0.046938 3 -0.419265 0 5 1 4 -0.144792 -0.217132 -0.034039 38
3 1.047082 3 -1.197188 2 5 0 2 -0.144792 -0.217132 -0.034039 38
4 -0.776285 3 1.136580 2 9 5 2 -0.144792 -0.217132 -0.034039 4

モデルの設計とトレーニング

トレーニング データセットと検証データセットの作成

トレーニングと評価に使用できるように、特徴とラベルを tf.data.Dataset に変換する入力関数を作成します。

def input_fn(features, labels, shuffle, num_epochs, batch_size):
  """Generates an input function to be used for model training.

  Args:
    features: numpy array of features used for training or inference
    labels: numpy array of labels for each example
    shuffle: boolean for whether to shuffle the data or not (set True for
      training, False for evaluation)
    num_epochs: number of epochs to provide the data for
    batch_size: batch size for training

  Returns:
    A tf.data.Dataset that can provide data to the Keras model for training or
      evaluation
  """
  if labels is None:
    inputs = features
  else:
    inputs = (features, labels)
  dataset = tf.data.Dataset.from_tensor_slices(inputs)

  if shuffle:
    dataset = dataset.shuffle(buffer_size=len(features))

  # We call repeat after shuffling, rather than before, to prevent separate
  # epochs from blending together.
  dataset = dataset.repeat(num_epochs)
  dataset = dataset.batch(batch_size)
  return dataset

次に、これらのトレーニングと評価のデータセットを作成します。定義済みのハイパーパラメータ NUM_EPOCHS および BATCH_SIZE を使用して、トレーニング中にトレーニング データセットからモデルにどのように例を提供するかを定義します。検証データセットのすべての例が 1 つのバッチで提供されるように検証データセットを設定します。これにより、トレーニング エポックの終了ごとに単一の検証ステップを実施できます。

# Pass a numpy array by using DataFrame.values
training_dataset = input_fn(features=train_x.values,
                    labels=train_y,
                    shuffle=True,
                    num_epochs=NUM_EPOCHS,
                    batch_size=BATCH_SIZE)

num_eval_examples = eval_x.shape[0]

# Pass a numpy array by using DataFrame.values
validation_dataset = input_fn(features=eval_x.values,
                    labels=eval_y,
                    shuffle=False,
                    num_epochs=NUM_EPOCHS,
                    batch_size=num_eval_examples)

Keras モデルの設計

Keras シーケンシャル API を使用してニューラル ネットワークを設計します。

このディープ ニューラル ネットワーク(DNN)にはいくつかの隠しレイヤがあり、最後のレイヤでは sigmoid アクティベーション関数を使用して 0 から 1 の範囲の値が出力されます。

  • 入力レイヤでは、ReLU アクティベーション関数を使用して 100 ユニットを保持します。
  • 隠しレイヤでは、ReLU アクティベーション関数を使用して 75 ユニットを保持します。
  • 隠しレイヤでは、ReLU アクティベーション関数を使用して 50 ユニットを保持します。
  • 隠しレイヤでは、ReLU アクティベーション関数を使用して 25 ユニットを保持します。
  • 出力レイヤでは、sigmoid アクティベーション関数を使用して 1 ユニットを保持します。
  • オプティマイザーでは、二項交差エントロピー損失関数を使用します。これは、このようなバイナリ分類問題に適しています。

これらのレイヤを自由に変更してモデルを改善できます。

def create_keras_model(input_dim, learning_rate):
  """Creates Keras Model for Binary Classification.

  Args:
    input_dim: How many features the input has
    learning_rate: Learning rate for training

  Returns:
    The compiled Keras model (still needs to be trained)
  """
  Dense = tf.keras.layers.Dense
  model = tf.keras.Sequential(
    [
        Dense(100, activation=tf.nn.relu, kernel_initializer='uniform',
                input_shape=(input_dim,)),
        Dense(75, activation=tf.nn.relu),
        Dense(50, activation=tf.nn.relu),
        Dense(25, activation=tf.nn.relu),
        Dense(1, activation=tf.nn.sigmoid)
    ])

  # Custom Optimizer:
  # https://www.tensorflow.org/api_docs/python/tf/train/RMSPropOptimizer
  optimizer = tf.keras.optimizers.RMSprop(
      lr=learning_rate)

  # Compile Keras model
  model.compile(
      loss='binary_crossentropy', optimizer=optimizer, metrics=['accuracy'])
  return model

次に、Keras モデル オブジェクトを作成します。

num_train_examples, input_dim = train_x.shape
print('Number of features: {}'.format(input_dim))
print('Number of examples: {}'.format(num_train_examples))

keras_model = create_keras_model(
    input_dim=input_dim,
    learning_rate=LEARNING_RATE)

このモデルを keras_model.summary() で調べると、次のような結果が得られます。

Number of features: 11
Number of examples: 32561
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/resource_variable_ops.py:435: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Colocations handled automatically by placer.
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
dense (Dense)                (None, 100)               1200
_________________________________________________________________
dense_1 (Dense)              (None, 75)                7575
_________________________________________________________________
dense_2 (Dense)              (None, 50)                3800
_________________________________________________________________
dense_3 (Dense)              (None, 25)                1275
_________________________________________________________________
dense_4 (Dense)              (None, 1)                 26
=================================================================
Total params: 13,876
Trainable params: 13,876
Non-trainable params: 0
_________________________________________________________________

モデルのトレーニングと評価

トレーニングの進捗に伴い、モデルのパラメータの変化が可能な限り小さくなるように学習率の減少を定義します。

# Setup Learning Rate decay.
lr_decay_cb = tf.keras.callbacks.LearningRateScheduler(
    lambda epoch: LEARNING_RATE + 0.02 * (0.5 ** (1 + epoch)),
    verbose=True)

# Setup TensorBoard callback.
JOB_DIR = os.getenv('JOB_DIR')
tensorboard_cb = tf.keras.callbacks.TensorBoard(
      os.path.join(JOB_DIR, 'keras_tensorboard'),
      histogram_freq=1)

最後に、モデルをトレーニングします。エポックごとにトレーニング データセット全体に対するトレーニングになるように、適切な steps_per_epoch をモデルに指定します(ステップごとの BATCH_SIZE の例を使用します)。各エポックの最後で大きな検証バッチを 1 つ使用して検証精度を計算することをモデルに指示します。

history = keras_model.fit(training_dataset,
                          epochs=NUM_EPOCHS,
                          steps_per_epoch=int(num_train_examples/BATCH_SIZE),
                          validation_data=validation_dataset,
                          validation_steps=1,
                          callbacks=[lr_decay_cb, tensorboard_cb],
                          verbose=1)

トレーニングの進捗状況は次のようになります。

WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.cast instead.

Epoch 00001: LearningRateScheduler reducing learning rate to 0.02.
Epoch 1/20
254/254 [==============================] - 1s 5ms/step - loss: 0.6986 - acc: 0.7893 - val_loss: 0.3894 - val_acc: 0.8329

Epoch 00002: LearningRateScheduler reducing learning rate to 0.015.
Epoch 2/20
254/254 [==============================] - 1s 4ms/step - loss: 0.3574 - acc: 0.8335 - val_loss: 0.3861 - val_acc: 0.8131

...

Epoch 00019: LearningRateScheduler reducing learning rate to 0.010000038146972657.
Epoch 19/20
254/254 [==============================] - 1s 4ms/step - loss: 0.3239 - acc: 0.8512 - val_loss: 0.3334 - val_acc: 0.8496

Epoch 00020: LearningRateScheduler reducing learning rate to 0.010000019073486329.
Epoch 20/20
254/254 [==============================] - 1s 4ms/step - loss: 0.3279 - acc: 0.8504 - val_loss: 0.3174 - val_acc: 0.8523

トレーニングの可視化およびトレーニング済みモデルのエクスポート

トレーニングの可視化

モデルがトレーニング期間中にどのように学習したかを可視化するために matplotlib をインポートします(必要に応じて、先に pip install matplotlib を使用してインストールしておきます)。

from matplotlib import pyplot as plt

各学習エポックの最後に測定した、モデルの損失(二項交差エントロピー)と精度をプロットします。

# Visualize History for Loss.
plt.title('Keras model loss')
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['training', 'validation'], loc='upper right')
plt.show()

# Visualize History for Accuracy.
plt.title('Keras model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.legend(['training', 'validation'], loc='lower right')
plt.show()

時間の経過とともに損失が減少し、精度が向上します。これらが安定した水準に収束するかどうかを確認します。また、トレーニング データと検証データとの間に大きな差異(過剰適合の兆候)があるかどうかも確認します。

詳細については、機械学習モデルを改善する方法をご覧ください。続いて、ハイパーパラメータやモデルのアーキテクチャをさまざまに調整して、もう一度トレーニングします。

予測対象となるモデルのエクスポート

tf.contrib.saved_model.save_keras_model を使用して TensorFlow の SavedModel ディレクトリをエクスポートします。これは、モデルのバージョン リソースを作成するときに AI Platform で必要となる形式です。

すべてのオプティマイザーを SavedModel 形式にエクスポートできるわけではないので、エクスポート処理中に警告が表示されることがあります。予測対象となるグラフを問題なくエクスポートしていれば、AI Platform から SavedModel を使用して予測が提供されます。

# Export the model to a local SavedModel directory
export_path = tf.contrib.saved_model.save_keras_model(keras_model, 'keras_export')
print("Model exported to: ", export_path)
WARNING: The TensorFlow contrib module will not be included in TensorFlow 2.0.
For more information, please see:
  * https://github.com/tensorflow/community/blob/master/rfcs/20180907-contrib-sunset.md
  * https://github.com/tensorflow/addons
If you depend on functionality not listed there, please file an issue.

WARNING:tensorflow:This model was compiled with a Keras optimizer (<tensorflow.python.keras.optimizers.RMSprop object at 0x7fc198c4e400>) but is being saved in TensorFlow format with `save_weights`. The model's weights will be saved, but unlike with TensorFlow optimizers in the TensorFlow format the optimizer's state will not be saved.

Consider using a TensorFlow optimizer from `tf.train`.
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/network.py:1436: update_checkpoint_state (from tensorflow.python.training.checkpoint_management) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.train.CheckpointManager to manage checkpoints rather than manually editing the Checkpoint proto.
WARNING:tensorflow:Model was compiled with an optimizer, but the optimizer is not from `tf.train` (e.g. `tf.train.AdagradOptimizer`). Only the serving graph was exported. The train and evaluate graphs were not added to the SavedModel.
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/saved_model/signature_def_utils_impl.py:205: build_tensor_info (from tensorflow.python.saved_model.utils_impl) is deprecated and will be removed in a future version.
Instructions for updating:
This function will only be available through the v1 compatibility library as tf.compat.v1.saved_model.utils.build_tensor_info or tf.compat.v1.saved_model.build_tensor_info.
INFO:tensorflow:Signatures INCLUDED in export for Classify: None
INFO:tensorflow:Signatures INCLUDED in export for Regress: None
INFO:tensorflow:Signatures INCLUDED in export for Predict: ['serving_default']
INFO:tensorflow:Signatures INCLUDED in export for Train: None
INFO:tensorflow:Signatures INCLUDED in export for Eval: None
INFO:tensorflow:No assets to save.
INFO:tensorflow:No assets to write.
INFO:tensorflow:SavedModel written to: keras_export/1553710367/saved_model.pb
Model exported to:  b'keras_export/1553710367'

必要な権限があれば、SavedModel ディレクトリをローカルのファイル システムまたは Cloud Storage にエクスポートできます。現在の環境では、各自の Google Cloud アカウントを認証し、GOOGLE_APPLICATION_CREDENTIALS 環境変数を設定することによって、Cloud Storage へのアクセス権が付与されます。AI Platform のサービス アカウントには、それぞれのプロジェクトの中で Cloud Storage バケットへのアクセス権が付与されているので、AI Platform のトレーニング ジョブでも Cloud Storage への直接エクスポートができます。

Cloud Storage への直接エクスポートを試してみます。

JOB_DIR = os.getenv('JOB_DIR')

# Export the model to a SavedModel directory in Cloud Storage
export_path = tf.contrib.saved_model.save_keras_model(keras_model, JOB_DIR + '/keras_export')
print("Model exported to: ", export_path)
WARNING:tensorflow:This model was compiled with a Keras optimizer (<tensorflow.python.keras.optimizers.RMSprop object at 0x7fc198c4e400>) but is being saved in TensorFlow format with `save_weights`. The model's weights will be saved, but unlike with TensorFlow optimizers in the TensorFlow format the optimizer's state will not be saved.

Consider using a TensorFlow optimizer from `tf.train`.
WARNING:tensorflow:Model was compiled with an optimizer, but the optimizer is not from `tf.train` (e.g. `tf.train.AdagradOptimizer`). Only the serving graph was exported. The train and evaluate graphs were not added to the SavedModel.
INFO:tensorflow:Signatures INCLUDED in export for Classify: None
INFO:tensorflow:Signatures INCLUDED in export for Regress: None
INFO:tensorflow:Signatures INCLUDED in export for Predict: ['serving_default']
INFO:tensorflow:Signatures INCLUDED in export for Train: None
INFO:tensorflow:Signatures INCLUDED in export for Eval: None
INFO:tensorflow:No assets to save.
INFO:tensorflow:No assets to write.
INFO:tensorflow:SavedModel written to: gs://your-bucket-name/keras-job-dir/keras_export/1553710379/saved_model.pb
Model exported to:  b'gs://your-bucket-name/keras-job-dir/keras_export/1553710379'

これで、このモデルを AI Platform にデプロイし、予測のクイック スタートの手順に沿って予測を提供できます。

クリーンアップ

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

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

# Delete model version resource
gcloud ai-platform versions delete $MODEL_VERSION --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 $JOB_DIR

# If training job is still running, cancel it
gcloud ai-platform jobs cancel $JOB_NAME --quiet

Cloud Storage バケットに他のオブジェクトが含まれていない場合は、gsutil rm -r gs://$BUCKET_NAME を実行してバケットを削除します。

次のステップ

  • このガイドで使用されているトレーニング コード全体を表示します。このコードは、カスタムのハイパーパラメータをコマンドライン上のフラグとして受け入れるようにコードを構成します。
  • AI Platform トレーニング ジョブのコードのパッケージングに関する説明をご覧ください。
  • モデルをデプロイして予測を提供する方法の説明をご覧ください。