このチュートリアルを Colab のノートブックとして実行 | 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 ガイドでは、上記の要件を満たすための詳しい手順を説明しています。要約した手順を次に示します。
virtualenv をインストールして、Python 3 を使用する仮想環境を作成します。
その環境をアクティブにします。
次のセクションにある手順に沿って、Google Cloud SDK をインストールします。
Google Cloud プロジェクトの設定
- 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.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the AI Platform Training & Prediction and Compute Engine APIs.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the AI Platform Training & Prediction and Compute Engine APIs.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
GCP アカウントの認証
認証を設定するには、サービス アカウント キーを作成し、そのサービス アカウント キーへのファイルパスの環境変数を設定する必要があります。
-
サービス アカウントを作成します。
-
Google Cloud コンソールで [サービス アカウントの作成] ページに移動します。
- [サービス アカウント名] フィールドに名前を入力します。
- 省略可: [サービス アカウントの説明] フィールドに説明を入力します。
- [作成] をクリックします。
- [ロールを選択] フィールドをクリックします。[すべてのロール] で、[AI Platform] > [AI Platform 管理者] の順に選択します。
- [別の役割を追加] をクリックします。
-
[ロールを選択] フィールドをクリックします。[すべてのロール] で、[Cloud Storage] > [ストレージ オブジェクト管理者] を選択します。
-
[完了] をクリックして、サービス アカウントを作成します。
ブラウザ ウィンドウは閉じないでください。次のステップでこれを使用します。
-
-
認証に使用するサービス アカウント キーを作成します。
- Google Cloud コンソールで、作成したサービス アカウントのメールアドレスをクリックします。
- [キー] をクリックします。
- [鍵を追加]、[新しい鍵を作成] の順にクリックします。
- [作成] をクリックします。JSON キーファイルがパソコンにダウンロードされます。
- [閉じる] をクリックします。
-
環境変数 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 Training と AI 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
年齢 | workclass | education_num | marital_status | 職業 | 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]
年齢 | workclass | fnlwgt | 教育 | education_num | marital_status | 職業 | 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 | 白 | 男性 | 0 | 0 | 35 | United-States | <=50K |
2430 | 26 | プライベート | 197967 | HS-grad | 9 | Never-married | Craft-repair | Own-child | 白 | 男性 | 0 | 0 | 40 | United-States | <=50K |
4214 | 22 | プライベート | 221694 | Some-college | 10 | Never-married | Protective-serv | Not-in-family | 白 | 男性 | 0 | 0 | 60 | United-States | <=50K |
10389 | 30 | プライベート | 96480 | Assoc-voc | 11 | Never-married | Adm-clerical | Own-child | 白 | 女性 | 0 | 0 | 32 | United-States | <=50K |
14525 | 18 | プライベート | 146225 | 10 日 | 6 | Never-married | Other-service | Own-child | Amer-Indian-Eskimo | 女性 | 0 | 0 | 40 | United-States | <=50K |
15040 | 37 | Self-emp-not-inc | 50096 | Assoc-voc | 11 | Married-civ-spouse | Craft-repair | Husband | 白 | 男性 | 0 | 0 | 30 | United-States | <=50K |
8409 | 42 | プライベート | 102988 | Masters | 14 | Married-civ-spouse | Prof-specialty | Husband | 白 | 男性 | 0 | 0 | 55 | エクアドル | >50K |
10628 | 40 | Local-gov | 284086 | Masters | 14 | Married-civ-spouse | Prof-specialty | Husband | 白 | 男性 | 7688 | 0 | 40 | United-States | >50K |
10942 | 44 | Self-emp-not-inc | 52505 | Some-college | 10 | Married-civ-spouse | Farming-fishing | Husband | 白 | 男性 | 0 | 0 | 99 | United-States | <=50K |
5129 | 54 | プライベート | 106728 | Bachelors | 13 | Married-civ-spouse | Tech-support | Husband | 白 | 男性 | 0 | 0 | 40 | United-States | <=50K |
2096 | 21 | プライベート | 190916 | Some-college | 10 | Never-married | Sales | Own-child | 白 | 女性 | 0 | 0 | 20 | United-States | <=50K |
12463 | 29 | プライベート | 197565 | HS-grad | 9 | Married-civ-spouse | Other-service | Wife | 白 | 女性 | 0 | 1902 | 35 | United-States | >50K |
8528 | 46 | プライベート | 193188 | Masters | 14 | Never-married | Exec-managerial | Unmarried | 白 | 男性 | 0 | 0 | 40 | United-States | <=50K |
7093 | 20 | プライベート | 273147 | HS-grad | 9 | Never-married | Machine-op-inspct | Own-child | 黒 | 男性 | 0 | 0 | 40 | United-States | <=50K |
12565 | 46 | プライベート | 203653 | Bachelors | 13 | Divorced | Sales | Other-relative | 黒 | 男性 | 0 | 0 | 40 | United-States | <=50K |
5655 | 57 | プライベート | 174662 | HS-grad | 9 | Married-civ-spouse | Craft-repair | Husband | 白 | 男性 | 0 | 0 | 40 | United-States | <=50K |
2322 | 48 | プライベート | 232149 | Bachelors | 13 | Divorced | Tech-support | Own-child | 白 | 女性 | 0 | 0 | 40 | United-States | <=50K |
12652 | 39 | プライベート | 82521 | Bachelors | 13 | Married-civ-spouse | Sales | Husband | 白 | 男性 | 0 | 0 | 45 | United-States | >50K |
4755 | 33 | プライベート | 330715 | HS-grad | 9 | Married-civ-spouse | Sales | Husband | 白 | 男性 | 0 | 0 | 55 | United-States | <=50K |
4413 | 44 | State-gov | 128586 | Bachelors | 13 | Never-married | Farming-fishing | Not-in-family | 白 | 男性 | 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()
)の抜粋を示します。
年齢 | workclass | fnlwgt | 教育 | education_num | marital_status | 職業 | 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 | 白 | 男性 | 2174 | 0 | 40 | United-States | <=50K |
1 | 50 | Self-emp-not-inc | 83311 | Bachelors | 13 | Married-civ-spouse | Exec-managerial | Husband | 白 | 男性 | 0 | 0 | 13 | United-States | <=50K |
2 | 38 | プライベート | 215646 | HS-grad | 9 | Divorced | Handlers-cleaners | Not-in-family | 白 | 男性 | 0 | 0 | 40 | United-States | <=50K |
3 | 53 | プライベート | 234721 | 11 日 | 7 | Married-civ-spouse | Handlers-cleaners | Husband | 黒 | 男性 | 0 | 0 | 40 | United-States | <=50K |
4 | 28 | プライベート | 338409 | Bachelors | 13 | Married-civ-spouse | Prof-specialty | Wife | 黒 | 女性 | 0 | 0 | 40 | キューバ | <=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
と >50K
を 0
と 1
に変更されていることに注意してください。
年齢 | workclass | education_num | marital_status | 職業 | 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()
)は、すべての前処理を完了したデータを示しています。
年齢 | workclass | education_num | marital_status | 職業 | 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 トレーニング ジョブのコードのパッケージングに関する説明をご覧ください。
- モデルをデプロイして予測を提供する方法の説明をご覧ください。