Cloud TPU(TF 2.x)での ResNet のトレーニング

このチュートリアルでは、tf.distribute.TPUStrategy を使用して Cloud TPU で Keras ResNet モデルをトレーニングする方法を説明します。

Cloud TPU に慣れていない場合は、TPU と Compute Engine VM を作成する方法について、クイックスタートを参照することを強くおすすめいたします。

目標

  • データセットとモデルの出力を格納する Cloud Storage バケットを作成します。
  • ImageNet データセットに類似したフェイク ImageNet データセットを準備します。
  • トレーニング ジョブを実行します。
  • 出力結果を確認します。

費用

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

  • Compute Engine
  • Cloud TPU
  • Cloud Storage

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを出すことができます。新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

始める前に

このチュートリアルを開始する前に、Google Cloud プロジェクトが正しく設定されていることを確認します。

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

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

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

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

  4. このチュートリアルでは、Google Cloud の課金対象となるコンポーネントを使用します。費用を見積もるには、Cloud TPU の料金ページを確認してください。不要な課金を回避するために、このチュートリアルを完了したら、作成したリソースを必ずクリーンアップしてください。

リソースを設定する

このセクションでは、チュートリアルで使用する Cloud Storage のバケット、VM、Cloud TPU の各リソースを設定する方法を説明します。

  1. Cloud Shell ウィンドウを開きます。

    Cloud Shell を開く

  2. プロジェクト ID の変数を作成します。

    export PROJECT_ID=project-id
    
  3. Cloud TPU を作成するプロジェクトを使用するように gcloud コマンドライン ツールを構成します。

    gcloud config set project ${PROJECT_ID}
    
  4. 次のコマンドを使用して Cloud Storage バケットを作成します。

    gsutil mb -p ${PROJECT_ID} -c standard -l europe-west4 -b on gs://bucket-name
    

    この Cloud Storage バケットには、モデルのトレーニングに使用するデータとトレーニング結果が格納されます。このチュートリアルで使用する ctpu up ツールは、Cloud TPU サービス アカウントのデフォルトの権限を設定します。権限の詳細な設定が必要な場合は、アクセスレベル権限をご覧ください。

    バケットのロケーションは、Compute Engine(VM)および Cloud TPU ノードと同じリージョンにする必要があります。

  5. ctpu up コマンドを使用して Compute Engine VM リソースを起動します。

    ctpu up --zone=europe-west4-a \
     --vm-only \
     --name=resnet-tutorial \
     --disk-size-gb=300 \
     --machine-type=n1-standard-16 \
     --tf-version=2.2

    ctpu ユーティリティの詳細については、CTPU リファレンスをご覧ください。

  6. プロンプトが表示されたら、y キーを押して Cloud TPU リソースを作成します。

    ctpu up コマンドの実行が終了したら、shell プロンプトが username@projectname から username@vm-name に変更されたことを確認します。変更されていれば、Compute Engine VM にログインしていることになります。

    gcloud compute ssh resnet-tutorial --zone=europe-west4-a
    

これ以降、接頭辞 (vm)$ は Compute Engine VM インスタンスでコマンドを実行する必要があることを意味します。

Cloud Storage バケットの変数を設定する

次の環境変数を設定します。bucket-name を Cloud Storage バケットの名前に置き換えます。

(vm)$ export STORAGE_BUCKET=gs://bucket-name
(vm)$ export MODEL_DIR=${STORAGE_BUCKET}/resnet-2x
(vm)$ export DATA_DIR=gs://cloud-tpu-test-datasets/fake_imagenet
(vm)$ export PYTHONPATH="$PYTHONPATH:/usr/share/models/"

トレーニング アプリケーションでは、Cloud Storage でトレーニング データにアクセスできる必要があります。また、トレーニング アプリケーションでは、Cloud Storage バケットを使用してトレーニング中にチェックポイントを保存します。

fake_imagenet を使用して ResNet モデルのトレーニングと評価を行う

ImageNet は画像データベースです。このデータベース内では画像が階層に編成されていて、階層の各ノードを数百、数千もの画像で表しています。

このチュートリアルでは、ImageNet の完全版のデータセットの fake_imagenet と呼ばれるデモバージョンを使用しています。このデモバージョンを使用すると、ストレージ容量と所要時間を ImageNet の完全版のデータセットに対してモデルを実行する際に通常必要となるものより抑えながらチュートリアルを試すことができます。

fake_imagenet データセットは Cloud Storage の次のロケーションにあります。

gs://cloud-tpu-test-datasets/fake_imagenet

fake_imagenet データセットは、Cloud TPU の使用方法を理解し、エンドツーエンドのパフォーマンスを検証する場合にのみ役立ちます。精度の数値と保存されたモデルは意味がありません。

ImageNet データセット全体をダウンロードして処理する方法については、ImageNet データセットのダウンロード、前処理、アップロードをご覧ください。

  1. ctpu ユーティリティを使用して Cloud TPU リソースを起動します。

    (vm)$ ctpu up --tpu-only \
     --tpu-size=v3-8  \
     --name=resnet-tutorial \
     --zone=europe-west4-a \
     --tf-version=2.2
    
  2. Cloud TPU 名の変数を設定します。これは、--name パラメータで ctpu up に指定した名前か、デフォルトのユーザー名になります。

    (vm)$ export TPU_NAME=resnet-tutorial
    
  3. ResNet トレーニング スクリプトには、追加のパッケージが必要です。この時点でインストールしておきます。

    (vm)$ sudo pip3 install tensorflow-model-optimization>=0.1.3
    
  4. ResNet-50 モデル ディレクトリに移動します。

    (vm)$ cd /usr/share/models/official/vision/image_classification/resnet/
    
  5. トレーニング スクリプトを実行します。 これは、fake_imagenet データセットを使用し、ResNet を 1 エポック、トレーニングします。

    (vm)$ python3 resnet_ctl_imagenet_main.py \
     --tpu=${TPU_NAME} \
     --model_dir=${MODEL_DIR} \
     --data_dir=${DATA_DIR} \
     --batch_size=1024 \
     --steps_per_loop=500 \
     --train_epochs=1 \
     --use_synthetic_data=false \
     --dtype=fp32 \
     --enable_eager=true \
     --enable_tensorboard=true \
     --distribution_strategy=tpu \
     --log_steps=50 \
     --single_l2_loss_op=true \
     --use_tf_function=true
    
    パラメータ 説明
    tpu TPU_NAME 変数で指定された名前を使用します。
    data_dir トレーニング入力用の Cloud Storage のパスを指定します。この例では、fake_imagenet データセットに設定されています。
    model_dir モデルのトレーニング中にチェックポイントとサマリーが保存されるディレクトリを指定します。該当するフォルダがない場合は、プログラムによって作成されます。Cloud TPU を使用する場合、model_dir を Cloud Storage パス(「gs://...」)にする必要があります。以前のチェックポイントが、同じサイズの TPU と TensorFlow バージョンを使用して作成されていれば、既存のフォルダを再利用して現在のチェックポイント データを読み込んで追加のチェックポイントを保存できます。
    distribution_strategy TPU で ResNet モデルを実行するには、「distribution_strategy」を「tpu」に設定する必要があります。

これにより ResNet を 1 エポック トレーニングし、v3-8 TPU ノードでは 10 分以内に完了します。トレーニングが終了すると、次のような出力が表示されます。

I1107 20:28:57.561836 140033625347520 resnet_ctl_imagenet_main.py:222] Training 1 epochs, each epoch has 1251 steps, total steps: 1251; Eval 48 steps
I1107 20:34:09.638025 140033625347520 resnet_ctl_imagenet_main.py:358] Training loss: 0.6292637, accuracy: 0.99680257 at epoch 1
I1107 20:34:21.682796 140033625347520 resnet_ctl_imagenet_main.py:372] Test loss: 3.8977659, accuracy: 0.0% at epoch: 1
I1107 20:34:22.028973 140033625347520 resnet_ctl_imagenet_main.py:392]
Run stats:
{'train_loss': 0.6292637, 'train_acc': 0.99680257, 'eval_acc': 0.0, 'step_timestamp_log':
['BatchTimestamp < batch_index: 1, timestamp: 1573158554.11 >'],
'train_finish_time': 1573158861.683073, 'eval_loss': 3.8977659>}
収束するように ResNet をトレーニングするには、次のスクリプトに示すように 90 エポックで実行します。トレーニングと評価は一緒に行われます。合計 112,590 ステップ中、各エポックには、1,251 のトレーニング ステップと 48 の評価ステップがあります。
   (vm)$ python3 resnet_ctl_imagenet_main.py \
    --tpu=${TPU_NAME} \
    --model_dir=${MODEL_DIR} \
    --data_dir=${DATA_DIR} \
    --batch_size=1024 \
    --steps_per_loop=500 \
    --train_epochs=90 \
    --use_synthetic_data=false \
    --dtype=fp32 \
    --enable_eager=true \
    --enable_tensorboard=true \
    --distribution_strategy=tpu \
    --log_steps=50 \
    --single_l2_loss_op=true \
    --use_tf_function=true
   

トレーニングと評価は fake_imagenet データセットに対して行われているため、出力結果には、実際のデータセットでトレーニングと評価を行った場合の出力は反映されません。

この時点で、このチュートリアルを終了して、GCP リソースをクリーンアップすることも、Cloud TPU Pod でのモデルの実行をさらに詳しく調べることもできます。

Cloud TPU Pod を使用してモデルをスケーリングする

Cloud TPU Pod を使用してモデルをスケーリングすると、より迅速に結果を得ることができます。完全にサポートされている ResNet-50 モデルは、次の Pod スライスに対応しています。

  • v2-32
  • v3-32

Cloud TPU Pod では、トレーニングと評価が同時に行われます。

Cloud TPU Pod を使用したトレーニング

  1. 単一のデバイスでモデルをトレーニングするために作成した Cloud TPU リソースを削除します。

    (vm)$ ctpu delete --zone=europe-west4-a \
     --tpu-only \
     --name=resnet-tutorial
  2. Cloud TPU が削除されたら、新しい Cloud TPU Pod を作成します。使用する Pod スライスを指定するための tpu-sizeパラメータを使用して、ctpu up コマンドを実行します。たとえば、次のコマンドは v3-32 の Pod スライスを使用します。

    (vm)$ ctpu up --zone=europe-west4-a \
    --tpu-only \
    --name=resnet-tutorial \
    --tpu-size=v3-32
    
    注: Compute Engine インスタンスに接続していない場合は、次のコマンドを実行して接続できます。
    gcloud compute ssh resnet-tutorial --zone=europe-west4-a
    
  3. 必要な環境変数を設定します。

    (vm)$ export TPU_NAME=resnet-tutorial
    (vm)$ export MODEL_DIR=${STORAGE_BUCKET}/resnet-2x-pod
    
  4. スクリプト ディレクトリに移動します。

    (vm)$ cd /usr/share/models/official/vision/image_classification/resnet
    
  5. モデルをトレーニングします。

    (vm)$ python3 resnet_ctl_imagenet_main.py \
      --tpu=${TPU_NAME} \
      --model_dir=${MODEL_DIR} \
      --data_dir=${DATA_DIR} \
      --batch_size=4096 \
      --steps_per_loop=500 \
      --train_epochs=1 \
      --use_synthetic_data=false \
      --dtype=fp32 \
      --enable_eager=true \
      --enable_tensorboard=true \
      --distribution_strategy=tpu \
      --log_steps=50 \
      --single_l2_loss_op=true \
      --use_tf_function=true
     

この手順は、fake_imagnet データセットに対してモデルを 1 エポックまでトレーニング(合計 312 トレーニング ステップ、12 評価ステップ)します。このトレーニングは、v3-32 Cloud TPU 上で約 2 分かかります。トレーニングと評価が完了すると、次のようなメッセージが表示されます。

1107 22:45:19.821746 140317155378624 resnet_ctl_imagenet_main.py:358] Training loss: 0.22576721, accuracy: 0.838141 at epoch 1
I1107 22:45:33.892045 140317155378624 resnet_ctl_imagenet_main.py:372] Test loss: 0.26673648, accuracy: 0.0% at epoch: 1
I1107 22:45:34.851322 140317155378624 resnet_ctl_imagenet_main.py:392] Run stats:
{'train_loss': 0.22576721, 'train_acc': 0.838141, 'eval_acc': 0.0, 'step_timestamp_log': ['BatchTimestamp'], 'train_finish_time': 1573166733.892282, 'eval_loss': 0.26673648}

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

  1. Compute Engine インスタンスとの接続を切断していない場合は切断します。

    (vm)$ exit
    

    プロンプトが username@projectname に変わります。これは、現在、Cloud Shell 内にいることを示しています。

  2. Cloud Shell で、Compute Engine VM と Cloud TPU の設定時に使用した --zone フラグを指定して ctpu delete コマンドを実行します。これにより、VM と Cloud TPU の両方が削除されます。

    $ ctpu delete --zone=europe-west4-a \
      --name=resnet-tutorial
    
  3. TPU の使用に対して不要な料金が発生しないように、ctpu status を実行してインスタンスが割り当てられていないことを確認します。削除には数分かかることがあります。次のようなレスポンスは、割り当てられたインスタンスがないことを示します。

    $ ctpu status --zone=europe-west4-a
    
    2018/04/28 16:16:23 WARNING: Setting zone to "europe-west4-a"
    No instances currently exist.
            Compute Engine VM:     --
            Cloud TPU:             --
    
  4. 次に示すように gsutil を実行します。bucket-name の部分は、このチュートリアルで作成した Cloud Storage バケット名に置き換えてください。

    $ gsutil rm -r gs://bucket-name
    

次のステップ