1. 概要
このラボでは、Google Cloud で ML トレーニング ワークフロー全体を体験し、PyTorch を使用してモデルを構築します。Cloud AI Platform Notebooks 環境から、トレーニング ジョブをパッケージ化して、ハイパーパラメータ調整を使用して AI Platform Training で実行する方法を学習します。
学習内容
次の方法を学習します。
- AI Platform Notebooks インスタンスを作成する
- PyTorch モデルを作成する
- AI Platform Training でハイパーパラメータ調整を使用してモデルをトレーニングする
このラボを Google Cloud で実行するための総費用は約 $1 です。
2. 環境を設定する
この Codelab を実行するには、課金が有効になっている Google Cloud Platform プロジェクトが必要です。プロジェクトを作成するには、こちらの手順に沿って操作してください。
ステップ 1: Cloud AI Platform Models API を有効にする
Cloud コンソールの [AI Platform Models] セクションに移動し、まだ有効になっていない場合は [有効にする] をクリックします。

ステップ 2: Compute Engine API を有効にする
[Compute Engine] に移動し、まだ有効になっていない場合は [有効にする] を選択します。これはノートブック インスタンスを作成するために必要です。
ステップ 3: AI Platform Notebooks インスタンスを作成する
Cloud コンソールの AI Platform Notebooks セクションに移動し、[新しいインスタンス] をクリックします。次に、最新の PyTorch インスタンス タイプ(GPU なし)を選択します。

デフォルトのオプションを使用するか、必要に応じてカスタム名を付けて、[作成] をクリックします。インスタンスが作成されたら、[JUPYTERLAB を開く] を選択します。

次に、ランチャーから Python 3 ノートブック インスタンスを開きます。

これで準備ができました。
ステップ 5: Python パッケージをインポートする
ノートブックの最初のセルに次のインポートを追加して、セルを実行します。実行するには、上部のメニューの右矢印ボタンを押すか、command-enter を押します。
import datetime
import numpy as np
import os
import pandas as pd
import time
ここでは PyTorch をインポートしていません。これは、ノートブック インスタンスからではなく、AI Platform Training でトレーニング ジョブを実行しているためです。
3. トレーニング ジョブのパッケージを作成する
AI Platform Training でトレーニング ジョブを実行するには、トレーニング コードを Notebooks インスタンスにローカルでパッケージ化し、ジョブのアセットを保存する Cloud Storage バケットが必要です。まず、ストレージ バケットを作成します。すでにバケットがある場合は、この手順をスキップできます。
ステップ 1: モデルの Cloud Storage バケットを作成する
まず、この Codelab の残りの部分で使用する環境変数を定義しましょう。以下の値に、Google Cloud プロジェクトの名前と、作成する Cloud Storage バケットの名前(グローバルに一意である必要があります)を入力します。
# Update these to your own GCP project, model, and version names
GCP_PROJECT = 'your-gcp-project'
BOCKET_URL = 'gs://storage_bucket_name'
これで、ストレージ バケットを作成する準備ができました。トレーニング ジョブを開始するときに、このバケットを指定します。
ノートブック内から次の gsutil コマンドを実行して、バケットを作成します。
!gsutil mb $BUCKET_URL
ステップ 2: Python パッケージの初期ファイルを作成する
AI Platform でトレーニング ジョブを実行するには、コードを Python パッケージとして構成する必要があります。これは、外部パッケージの依存関係を指定するルート ディレクトリ内の setup.py ファイル、パッケージの名前のサブディレクトリ(ここでは trainer/)、このサブディレクトリ内の空の __init__.py ファイルで構成されます。
まず、setup.py ファイルを作成しましょう。iPython %%writefile マジックを使用して、ファイルをインスタンスに保存します。ここでは、トレーニング コードで使用する 3 つの外部ライブラリ(PyTorch、Scikit-learn、Pandas)を指定しました。
%%writefile setup.py
from setuptools import find_packages
from setuptools import setup
REQUIRED_PACKAGES = ['torch>=1.5', 'scikit-learn>=0.20', 'pandas>=1.0']
setup(
name='trainer',
version='0.1',
install_requires=REQUIRED_PACKAGES,
packages=find_packages(),
include_package_data=True,
description='My training application package.'
)
次に、trainer/ ディレクトリとその中の空の init.py ファイルを作成します。Python はこのファイルを使用して、これがパッケージであることを認識します。
!mkdir trainer
!touch trainer/__init__.py
これで、トレーニング ジョブの作成を開始する準備ができました。
4. データセットをプレビューする
このラボでは、モデルをトレーニングするためのツールに重点を置いていますが、モデルのトレーニングに使用するデータセットを簡単に見てみましょう。BigQuery で利用可能な 出生率データセットを使用します。これには、米国における数十年にわたる出生データが含まれています。データセットのいくつかの列を使用して、赤ちゃんの出生時体重を予測します。元のデータセットは非常に大きく、Cloud Storage バケットで利用できるようにしたサブセットを使用します。
ステップ 1: BigQuery 出生率データセットをダウンロードする
Cloud Storage で利用できるようにしたデータセットのバージョンを Pandas DataFrame にダウンロードしてプレビューしましょう。
natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
natality.head()
このデータセットには 10 万行弱が含まれています。5 つの特徴を使用して、赤ちゃんの出生時体重を予測します。母親と父親の年齢、妊娠週数、母親の体重増加(ポンド)、赤ちゃんの性別(ブール値)です。
5. ハイパーパラメータ調整を使用してトレーニング ジョブを定義する
トレーニング スクリプトは、先ほど作成した trainer/ サブディレクトリ内の model.py というファイルに書き込みます。トレーニング ジョブは AI Platform Training で実行され、AI Platform のハイパーパラメータ調整サービスを使用して、ベイジアン最適化を利用してモデルの最適なハイパーパラメータを見つけます。
ステップ 1: トレーニング スクリプトを作成する
まず、トレーニング スクリプトを含む Python ファイルを作成しましょう。次に、その内容を詳しく見ていきます。この %%writefile コマンドを実行すると、モデルコードがローカルの Python ファイルに書き込まれます。
%%writefile trainer/model.py
import argparse
import hypertune
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.utils import shuffle
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import normalize
def get_args():
"""Argument parser.
Returns:
Dictionary of arguments.
"""
parser = argparse.ArgumentParser(description='PyTorch MNIST')
parser.add_argument('--job-dir', # handled automatically by AI Platform
help='GCS location to write checkpoints and export ' \
'models')
parser.add_argument('--lr', # Specified in the config file
type=float,
default=0.01,
help='learning rate (default: 0.01)')
parser.add_argument('--momentum', # Specified in the config file
type=float,
default=0.5,
help='SGD momentum (default: 0.5)')
parser.add_argument('--hidden-layer-size', # Specified in the config file
type=int,
default=8,
help='hidden layer size')
args = parser.parse_args()
return args
def train_model(args):
# Get the data
natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
natality = natality.dropna()
natality = shuffle(natality, random_state = 2)
natality.head()
natality_labels = natality['weight_pounds']
natality = natality.drop(columns=['weight_pounds'])
train_size = int(len(natality) * 0.8)
traindata_natality = natality[:train_size]
trainlabels_natality = natality_labels[:train_size]
testdata_natality = natality[train_size:]
testlabels_natality = natality_labels[train_size:]
# Normalize and convert to PT tensors
normalized_train = normalize(np.array(traindata_natality.values), axis=0)
normalized_test = normalize(np.array(testdata_natality.values), axis=0)
train_x = torch.Tensor(normalized_train)
train_y = torch.Tensor(np.array(trainlabels_natality))
test_x = torch.Tensor(normalized_test)
test_y = torch.Tensor(np.array(testlabels_natality))
# Define our data loaders
train_dataset = torch.utils.data.TensorDataset(train_x, train_y)
train_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True)
test_dataset = torch.utils.data.TensorDataset(test_x, test_y)
test_dataloader = torch.utils.data.DataLoader(test_dataset, batch_size=128, shuffle=False)
# Define the model, while tuning the size of our hidden layer
model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
nn.ReLU(),
nn.Linear(args.hidden_layer_size, 1))
criterion = nn.MSELoss()
# Tune hyperparameters in our optimizer
optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum)
epochs = 20
for e in range(epochs):
for batch_id, (data, label) in enumerate(train_dataloader):
optimizer.zero_grad()
y_pred = model(data)
label = label.view(-1,1)
loss = criterion(y_pred, label)
loss.backward()
optimizer.step()
val_mse = 0
num_batches = 0
# Evaluate accuracy on our test set
with torch.no_grad():
for i, (data, label) in enumerate(test_dataloader):
num_batches += 1
y_pred = model(data)
mse = criterion(y_pred, label.view(-1,1))
val_mse += mse.item()
avg_val_mse = (val_mse / num_batches)
# Report the metric we're optimizing for to AI Platform's HyperTune service
# In this example, we're mimizing error on our test set
hpt = hypertune.HyperTune()
hpt.report_hyperparameter_tuning_metric(
hyperparameter_metric_tag='val_mse',
metric_value=avg_val_mse,
global_step=epochs
)
def main():
args = get_args()
print('in main', args)
train_model(args)
if __name__ == '__main__':
main()
トレーニング ジョブは、作業の大部分が行われる 2 つの関数で構成されています。
get_args(): トレーニング ジョブを作成するときに渡すコマンドライン引数と、AI Platform で最適化するハイパーパラメータを解析します。この例では、引数のリストには、最適化するハイパーパラメータ(モデルの学習率、モメンタム、隠れ層のニューロン数)のみが含まれています。train_model(): ここでは、データを Pandas DataFrame にダウンロードして正規化し、PyTorch テンソルに変換して、モデルを定義します。モデルを構築するために、PyTorchnn.SequentialAPI を使用します。これにより、モデルをレイヤのスタックとして定義できます。
model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
nn.ReLU(),
nn.Linear(args.hidden_layer_size, 1))
モデルの隠れ層のサイズをハードコードするのではなく、AI Platform が調整するハイパーパラメータにします。詳細については、次のセクションをご覧ください。
ステップ 2: AI Platform のハイパーパラメータ調整サービスを使用する
さまざまなハイパーパラメータ値を手動で試して、そのたびにモデルを再トレーニングするのではなく、Cloud AI Platform の ハイパーパラメータ最適化サービスを使用します。ハイパーパラメータ引数を使用してトレーニング ジョブを設定すると、AI Platform は ベイジアン最適化 を使用して、指定したハイパーパラメータの最適な値を見つけます。
ハイパーパラメータ調整では、1 つの トライアル は、特定のハイパーパラメータ値の組み合わせでモデルを 1 回トレーニング実行することです。実行するトライアルの数に応じて、AI Platform は完了したトライアルの結果を使用して、今後のトライアルで選択するハイパーパラメータを最適化します。ハイパーパラメータ調整を構成するには、最適化する各ハイパーパラメータに関するデータを含む構成ファイルを、トレーニング ジョブの開始時に渡す必要があります。
次に、構成ファイルをローカルに作成します。
%%writefile config.yaml
trainingInput:
hyperparameters:
goal: MINIMIZE
maxTrials: 10
maxParallelTrials: 5
hyperparameterMetricTag: val_mse
enableTrialEarlyStopping: TRUE
params:
- parameterName: lr
type: DOUBLE
minValue: 0.0001
maxValue: 0.1
scaleType: UNIT_LINEAR_SCALE
- parameterName: momentum
type: DOUBLE
minValue: 0.0
maxValue: 1.0
scaleType: UNIT_LINEAR_SCALE
- parameterName: hidden-layer-size
type: INTEGER
minValue: 8
maxValue: 32
scaleType: UNIT_LINEAR_SCALE
各ハイパーパラメータについて、タイプ、検索する値の範囲、さまざまなトライアルで値を増やすスケールを指定します。
ジョブの開始時に、最適化する指標も指定します。上記の train_model() 関数の最後に、トライアルが完了するたびにこの指標を AI Platform に報告します。ここでは、モデルの平均二乗誤差を最小化するため、モデルの平均二乗誤差が最も小さいハイパーパラメータを使用します。 この指標の名前(val_mse)は、トライアルの最後に report_hyperparameter_tuning_metric() を呼び出すときに報告する名前と一致します。
6. AI Platform でトレーニング ジョブを実行する
このセクションでは、AI Platform でハイパーパラメータ調整を使用してモデル トレーニング ジョブを開始します。
ステップ 1: 環境変数を定義する
まず、トレーニング ジョブの開始に使用する環境変数を定義しましょう。別のリージョンでジョブを実行する場合は、以下の REGION 変数を更新します。
MAIN_TRAINER_MODULE = "trainer.model"
TRAIN_DIR = os.getcwd() + '/trainer'
JOB_DIR = BUCKET_URL + '/output'
REGION = "us-central1"
AI Platform の各トレーニング ジョブには一意の名前を付ける必要があります。次のコマンドを実行して、タイムスタンプを使用してジョブの名前の変数を定義します。
timestamp = str(datetime.datetime.now().time())
JOB_NAME = 'caip_training_' + str(int(time.time()))
ステップ 2: トレーニング ジョブを開始する
トレーニング ジョブは、Google Cloud CLI である gcloud を使用して作成します。このコマンドは、ノートブックで直接実行し、上記で定義した変数を参照できます。
!gcloud ai-platform jobs submit training $JOB_NAME \
--scale-tier basic \
--package-path $TRAIN_DIR \
--module-name $MAIN_TRAINER_MODULE \
--job-dir $JOB_DIR \
--region $REGION \
--runtime-version 2.1 \
--python-version 3.7 \
--config config.yaml
ジョブが正しく作成されたら、AI Platform コンソールの [Jobs] section に移動してログをモニタリングします。
ステップ 3: ジョブをモニタリングする
コンソールの [ジョブ] セクションで、開始したジョブをクリックして詳細を表示します。

最初のトライアルが開始されると、各トライアルで選択されたハイパーパラメータ値が表示されます。

トライアルが完了すると、最適化指標の結果値(この場合は val_mse)がここに記録されます。ジョブの実行には 15 ~ 20 分かかります。ジョブが完了すると、ダッシュボードは次のようになります(正確な値は異なります)。

潜在的な問題をデバッグしてジョブを詳細にモニタリングするには、ジョブの詳細ページで [ログを表示] をクリックします。

モデル トレーニング コードのすべての print() ステートメントがここに表示されます。問題が発生した場合は、print ステートメントを追加して、新しいトレーニング ジョブを開始してみてください。
トレーニング ジョブが完了したら、val_mse が最も小さいハイパーパラメータを見つけます。これらを使用して、モデルの最終バージョンをトレーニングしてエクスポートすることも、追加のハイパーパラメータ調整トライアルで別のトレーニング ジョブを開始するためのガイダンスとして使用することもできます。
7. クリーンアップ
このノートブックを引き続き使用する場合は、使用しないときにオフにすることをおすすめします。Cloud コンソールの Notebooks UI で、ノートブックを選択して [停止] をクリックします。

このラボで作成したリソースをすべて削除する場合は、ノートブック インスタンスを停止するのではなく、削除します。
Cloud コンソールのナビゲーション メニューで [ストレージ] に移動し、モデルアセットを保存するために作成した両方のバケットを削除します。