Google Cloud ML EngineでTensorFlow機械学習訓練実行

[Google Cloud ML Engine](https://cloud.google.com/ml-engine/docs/tensorflow/technical-overview?hl=ja)でTensorFlowを使って機械学習をします。クラウド側で実行すれば、GPUが手軽に使えるので非常に速く実行できます。

#参考

- [公式チュートリアル](https://cloud.google.com/ml-engine/docs/tensorflow/getting-started-training-prediction)
- [GitHub(GoogleCloudPlatform/cloudml-samples)](https://github.com/GoogleCloudPlatform/cloudml-samples/tree/master/census)
- [Google AI Platform - Cloud ML Engineを初心者が動かして理解(前半)](https://qiita.com/FukuharaYohei/items/b9421c2d2837e14eb049)
- [Google AI Platform - Cloud ML Engineを初心者が動かして理解(後半)](https://qiita.com/FukuharaYohei/items/a4621e0a80063047e340)
- [Google AI Platform - Cloud ML EngineとファイルI/O](https://qiita.com/FukuharaYohei/items/56bbd3843fa791bfb7dd)


#環境
|種類|バージョン|内容|
|:--|:--|:--|
|Host OS|Windows8.1 64bit|自宅環境なのでProfessionalでもないです|
|Guest OS|Ubuntu18.04 LTS 64bit|Oracle VirtualBox上に環境作成|
|Python|Python3.5|[Google Cloud MLのランタイム1.10](https://cloud.google.com/ml-engine/docs/tensorflow/runtime-version-list?hl=ja#supported_cloud_ml_engine_runtime_versions)を使うのでPythonは最新の3.7を使いません(2018/12/24時点)|
|TensorFlow|TensorFlow1.10|[Google Cloud MLのランタイム1.10](https://cloud.google.com/ml-engine/docs/tensorflow/runtime-version-list?hl=ja#supported_cloud_ml_engine_runtime_versions)を使うのでTensorFlowは最新の1.12を使いません(2018/12/24時点)|

※**Google Cloud MLのランタイムを確認するときは[英語のページ](https://cloud.google.com/ml-engine/docs/tensorflow/runtime-version-list?hl=en#supported_runtime_versions)で見てください。**日本語ページは更新が遅れています。

#前提
pyenvはインストール済
GCPのアカウントを持っていること

#手順
##1. GCP プロジェクトの設定
[公式ガイド](https://cloud.google.com/ml-engine/docs/tensorflow/getting-started-training-prediction?hl=ja#gcp-)をもとにGoogle Cloud Platform設定。
###1.1.  プロジェクト作成
[「リソースの管理」](https://console.cloud.google.com/cloud-resource-manager?hl=ja&_ga=2.104735616.-1822452666.1543377741)ページでプロジェクト作成
「プロジェクトを作成」ボタンクリック
![10.ConfigureGCP01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/7740f699-e396-420b-9229-9300559aa62e.jpeg)

「プロジェクト名」を入力して「作成」ボタンクリック
![10.ConfigureGCP02.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/4587fd10-2244-9945-29cb-20e118e2d69f.jpeg)

###1.2. 課金有効の確認
[ガイド](https://cloud.google.com/billing/docs/how-to/modify-project?hl=ja#enable_billing_for_a_project) をもとにプロジェクトに対して課金が有効かを確認します(デフォルトで有効っぽい)。

###1.3. API有効化
[GCPコンソール](https://console.cloud.google.com/flows/enableapi?apiid=ml.googleapis.com%2Ccompute_component&hl=ja&_ga=2.30853951.-1822452666.1543377741)からCloud Machine Learning Engine と Compute Engine API（複数）を有効化
プロジェクトを選択して「続行」ボタンクリック
![10.ConfigureGCP03.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/88b76663-2a11-2e49-a395-b20de7c1c4a2.jpeg)

###1.4. 認証情報設定
[「サービス アカウント キーの作成」ページ](https://console.cloud.google.com/apis/credentials/serviceaccountkey?hl=ja&_ga=2.163958719.-1822452666.1543377741)で新しいサービスアカウントを作成(「役割」はプロジェクトオーナー)してJSON形式で秘密鍵を保存。
![10.ConfigureGCP05.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/c15e93fd-5f91-a48e-c9c1-98b1f33ee25a.jpeg)

環境変数にダウンロードしたJSON形式の秘密鍵を設定(下記のファイルパスとファイル名を変更してください)。

```bash
export GOOGLE_APPLICATION_CREDENTIALS="/home/<user>/Downloads/<service-account-file.json>"
```

###1.5. Google Cloud SDKインストール
[公式ガイド](https://cloud.google.com/sdk/downloads?hl=JA#apt-get)に従い、Google Cloud SDKをインストールします。Ubuntuなのでapt-getを使っています。

```bash
export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)"
echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-get update && sudo apt-get install google-cloud-sdk
gcloud init
```
Google Cloud SDK の確認をします。
まずは下記コマンド実行するとURLを返してくれるので、ブラウザでそのURLにアクセスします。

```bash
gcloud auth login
```

![10.ConfigureGCP06.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/42fc51ec-3ca7-dfd8-1f6a-5cc7e8218334.jpeg)

アカウントを選択
![10.ConfigureGCP07.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/b8017a42-9f6e-1e53-0377-223419ee4279.jpeg)

「許可」ボタンをクリック
![10.ConfigureGCP08.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/a675acc0-8939-30e8-a285-ed83b249afe1.jpeg)

これでGoogle Cloud SDKの設定ができたので、プロジェクト名を設定してモデル一覧を表示します(まだ作っていないので0で返ってきます)。プロジェクト名はIDであることに注意ください。

```bash
gcloud config set project <project id>
# 昔は gcloud ml-engine だった(2019/7/8)追記
gcloud ai-platform models list
```

##2. 訓練コードとデータ設定
訓練用コードとデータをダウンロードし、クラウドにアップロードします。

###2.1. 訓練用コードダウンロード
[GitHub](https://github.com/GoogleCloudPlatform/cloudml-samples/archive/master.zip)から訓練用のコードをダウンロードして解凍します(git cloneでもいいはず)。

###2.2. 訓練データダウンロード
カレントディレクトリを手順「2.1. 訓練用コードダウンロード」で解凍したcloudml-samples-master/census/estimatorに設定して、"data"フォルダーを作り、公開されているGoogle Cloud Storageから訓練データをダウンロードします。

```bash
cd cloudml-samples-master/census/estimator
mkdir data
gsutil -m cp gs://cloud-samples-data/ml-engine/census/data/* data/
```

###2.3. 環境変数の設定
TRAIN_DATA および EVAL_DATA 変数をローカル ファイルパスに設定します。

```bash
TRAIN_DATA=$(pwd)/data/adult.data.csv
EVAL_DATA=$(pwd)/data/adult.test.csv
```

##3. Python環境構築
###3.1. Pythonバージョン3.5設定 
前提としてpyenv(ver1.2.8)とvenvを使っています。
pyenvでPythonバージョンを3.5.6に設定します。今回はローカル環境ではなく、クラウド側で訓練をするのでPythonは必須ではありません。TensorBoardで訓練情報を確認するためだけに構築します。
pyenvとvenvに関しては記事[「WSLのUbuntuにpyenvとvenvでPython開発環境構築」](https://qiita.com/FukuharaYohei/items/2820f7bda6678ce26ea7)も参考にしてください。

```bash
pyenv global 3.5.6
python --version
which python
```

###3.2. 仮想環境作成 
カレントディレクトリをvenv用の場所に設定して、venvで"clml-tf10"という仮想環境を作成し、有効化。

```bash
python -m venv clml-tf10
source clml-tf10/bin/activate
```

###3.3. TensorFlow等インストール
カレントディレクトリを手順「2.1. 訓練用コードダウンロード」で解凍したcloudml-samples-master/census/estimatorに設定して、requirementsファイルからTensorFlow等をインストールします。[チュートリアル](https://cloud.google.com/ml-engine/docs/tensorflow/getting-started-training-prediction?hl=ja#install_tensorflow)通りに--userオプションをつけると仮想環境にインストールされないので注意してください。

```bash
  pip install -r ../requirements.txt
```

##4. 訓練実行
###4.1. バケット関連の環境変数設定。 
バケット(Google Cloud Storage)関連の環境変数としてバケット名とリージョンを設定。

```bash
BUCKET_NAME="cl-ml01"
REGION=us-central1
```

###4.2. バケットに訓練データアップロード
バケットに訓練データをアップロードし、環境変数にそのパスを設定します。

```bash
gsutil cp -r data gs://$BUCKET_NAME/data
gsutil cp ../test.json gs://$BUCKET_NAME/data/test.json
TRAIN_DATA=gs://$BUCKET_NAME/data/adult.data.csv
EVAL_DATA=gs://$BUCKET_NAME/data/adult.test.csv
TEST_JSON=gs://$BUCKET_NAME/data/test.json
```

###4.3. 訓練ジョブ関連の環境変数設定
訓練ジョブ関連の環境変数を設定します。

```bash
JOB_NAME=census_single_1
OUTPUT_PATH=gs://$BUCKET_NAME/$JOB_NAME
```

###4.4. 訓練ジョブ実行
訓練ジョブをクラウド上で実行します。

```bash
gcloud ml-engine jobs submit training $JOB_NAME \
    --stream-logs \
    --runtime-version 1.10 \
    --job-dir $OUTPUT_PATH \
    --module-name trainer.task \
    --package-path trainer/ \
    --region $REGION \
    -- \
    --train-files $TRAIN_DATA \
    --eval-files $EVAL_DATA \
    --train-steps 1000 \
    --eval-steps 100 \
```

##5. 結果確認
###5.1. コンソールから確認
[GCPのコンソール](https://console.cloud.google.com/mlengine/jobs)でジョブステータスを確認します。
![20.GCPLog01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/7ad9a016-f98e-c1d3-f471-5f09a89f8c8b.jpeg)

View Logsのリンクをクリックすると詳細画面に行けます。トラブルシュートする場合に、このログが非常に重要です。
![20.GCPLog02.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/ac0eec38-bb10-8b6e-8f85-389d11f5d35b.jpeg)


###5.2. TensorBoardから確認  
TensorBoardを起動しようとしたら権限エラーが出たので、事前にログインしておきます。

```bash
gcloud auth application-default login
```

以下のコマンドでTensorBoardを起動して訓練情報を確認します。Windowsの場合、logdirにGoogle Cloud Storageのパスを指定して実行できませんでした。

```bash
tensorboard --logdir=$OUTPUT_PATH
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/134273/76a26991-3950-5c0a-742c-c831f75d7b87.png)