Google AI Platform - Cloud ML Engineを初心者が動かして理解(後編)

前半記事[「Google AI Platform - Cloud ML Engineを初心者が動かして理解(前編)」](https://qiita.com/FukuharaYohei/items/b9421c2d2837e14eb049)では、print文だけのプログラムを動かしました。今回の記事はTensorFlowで簡単な機械学習をします。
[公式チュートリアル](https://cloud.google.com/ml-engine/docs/tensorflow/getting-started-training-prediction)実行に関しては、記事[「Google Cloud ML EngineでTensorFlow機械学習訓練実行」](https://qiita.com/FukuharaYohei/items/2a435ef83ecf1702395c)を参照ください。
ファイルの読み書きをしたい場合には、記事[「Google AI Platform - Cloud ML EngineとファイルI/O」](https://qiita.com/FukuharaYohei/items/56bbd3843fa791bfb7dd)を参照ください。

# 環境
[前半記事](https://qiita.com/FukuharaYohei/items/b9421c2d2837e14eb049#%E7%92%B0%E5%A2%83)と同じです。

|種類|バージョン|内容|
|:--|:--|:--|
|OS|Ubuntu18.04.01 LTS|仮想で動かしています|
|Google Cloud SDK|250.0.0||

# 前提
[前半記事](https://qiita.com/FukuharaYohei/items/b9421c2d2837e14eb049#%E7%92%B0%E5%A2%83)と同じです。

- GCPのアカウントを持っていること
- GCPでプロジェクトを作成済でAPI有効化であること(今回は"aip-test02"というIDで作成しています)
- Google Cloud SDKがインストールされていること


# 手順
基本的にジョブ実行時のパラメータ以外は[前半記事](https://qiita.com/FukuharaYohei/items/b9421c2d2837e14eb049#%E7%92%B0%E5%A2%83)と同じです。今度はTensorFlowを動かすので、python-versionとruntime-versionを指定します。
※[「注意すべきパラメータ」](https://qiita.com/FukuharaYohei/items/b9421c2d2837e14eb049#%E6%B3%A8%E6%84%8F%E3%81%99%E3%81%B9%E3%81%8D%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF)参照。

```bash
gcloud ai-platform jobs submit training $JOB_NAME \
     --job-dir $OUTPUT_PATH \
     --module-name trainer.task \
     --package-path trainer/ \
     --python-version 3.5 \
     --runtime-version 1.13 \
```

# 実行プログラム
プログラム全体は[GitHub](https://github.com/YoheiFukuhara/gcp-aip-test02)に置いています。
[推奨プロジェクト構成](https://cloud.google.com/ml-engine/docs/tensorflow/packaging-trainer#project-structure)に準じたディレクトリ構成にしています。ディレクトリ["trainer"](https://github.com/YoheiFukuhara/gcp-aip-test02/tree/master/trainer)に訓練時に必要となる4つのpythonプログラムを入れています(["\_\_init\_\_.py"](https://github.com/YoheiFukuhara/gcp-aip-test02/blob/master/trainer/__init__.py)の中身は空です)。
今回のプログラム解説については、別記事[「【Keras入門(1)】単純なディープラーニングモデル定義」](https://qiita.com/FukuharaYohei/items/579cc0184885b4ba75df)を参照ください。

```
.
└── trainer
    ├── __init__.py
    ├── model.py
    ├── task.py
    └── util.py
```


## [task.py](https://github.com/YoheiFukuhara/gcp-aip-test02/blob/master/trainer/task.py)
メインとなるプログラム["task.py"](https://github.com/YoheiFukuhara/gcp-aip-test02/blob/master/trainer/task.py)です。"util.load_data"から訓練データ、"model.create_keras_model"からモデルを受け取り[fit関数](https://keras.io/ja/models/sequential/#fit)で実行しています。後で気づいたのですが、fit関数でverbose=2に指定した方がログが見やすくなります。

```python
import tensorflow as tf
from . import model
from . import util


def train_and_evaluate():

    train_x, train_y = util.load_data()


    # Create the Keras Model
    keras_model = model.create_keras_model()

    keras_model.fit(train_x, train_y, epochs=300, validation_split=0.2)


if __name__ == '__main__':
    tf.logging.set_verbosity("INFO")
    train_and_evaluate()
```

## [util.py](https://github.com/YoheiFukuhara/gcp-aip-test02/blob/master/trainer/util.py)
訓練データを乱数で生成しています。通常はここで、Google Storageからデータを読み込んで編集します。

```python
import numpy as np

NUM_TRAIN = 128


def load_data():
    data = np.random.rand(NUM_TRAIN, 2)

    labels = (np.sum(data, axis=1) > 1.0) * 1
    labels = labels.reshape(NUM_TRAIN, 1)

    return data, labels
```

## [model.py](https://github.com/YoheiFukuhara/gcp-aip-test02/blob/master/trainer/model.py)
TensorFlowに統合されたKerasを使ってモデルを定義しています。

```python
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense


def create_keras_model():
    # Sequentialモデル使用(Sequentialモデルはレイヤを順に重ねたモデル)
    model = Sequential()

    # 結合層(2層->4層)
    model.add(Dense(4, input_dim=2, activation="tanh"))

    # 結合層(4層->1層)：入力次元を省略すると自動的に前の層の出力次元数を引き継ぐ
    model.add(Dense(1, activation="sigmoid"))

    # モデルをコンパイル
    model.compile(loss="binary_crossentropy", optimizer="sgd", metrics=["accuracy"])

    model.summary()

    return model
```