Cloud TPU での RetinaNet のトレーニング

このドキュメントでは、RetinaNet オブジェクト検出モデルの実装について説明します。コードは、GitHub で入手できます。

以下の手順では、Cloud TPU でモデルを実行する方法をすでに理解していることを前提としています。Cloud TPU を初めて使用する場合は、クイックスタートで基本的な概要をご確認ください。

始める前に

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

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

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

  2. Google Cloud Platform プロジェクトを選択または作成します。

    [リソースの管理] ページに移動

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

    課金を有効にする方法について

  4. TPU デバイスとポッドのいずれかの使用に十分な割り当て量があることを確認します。

リソースを設定する

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

Cloud Storage バケットを作成する

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

作成するバケットは、使用する仮想マシン(VM)および Cloud TPU デバイスまたは Cloud TPU スライス(複数の TPU デバイス)と同じリージョン内に配置する必要があります。

  1. GCP Console の Cloud Storage ページに移動します。

    Cloud Storage ページに移動

  2. 次のオプションを指定して新しいバケットを作成します。

    • 任意の一意な名前
    • デフォルトのストレージ クラス: Regional
    • ロケーション: 単一の Cloud TPU デバイスを使用する場合は、表示されるデフォルト ロケーションを受け入れます。Cloud TPU Pod スライスを使用する場合、Cloud TPU Pod を利用できるリージョンを選択する必要があります。

ctpu ツールを使用する

このセクションでは、Cloud TPU プロビジョニング ツールctpu)を使用して Cloud TPU プロジェクトのリソースを作成、管理する方法を説明します。リソースは、同じ名前が付けられた仮想マシン(VM)と Cloud TPU リソースで構成されます。これらのリソースは、作成したバケットと同じリージョン / ゾーンに存在する必要があります。

VM リソースと TPU リソースを設定するには、gcloud コマンドまたは Cloud Console を使用することもできます。詳細については、VM と TPU のリソース管理をご覧ください。

ctpu up を実行してリソースを作成する

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

    Cloud Shell を開く

  2. gcloud config set project <Your-Project> を実行して、Cloud TPU の作成に使用するプロジェクトを設定します。

  3. Cloud TPU デバイスまたは Pod スライスのいずれかを示すフラグを指定して ctpu up を実行します。フラグのオプションと説明については、CTPU リファレンスをご覧ください。

  4. Cloud TPU デバイスか、Pod スライスのいずれかを設定します。

TPU デバイス

Cloud TPU デバイスを設定します。

$ ctpu up --tpu-size=v3-8 --machine-type n1-standard-8

構成に関する次のメッセージが表示されます。

ctpu will use the following configuration:

Name: [your TPU's name]
Zone: [your project's zone]
GCP Project: [your project's name]
TensorFlow Version: 1.14
VM:
  Machine Type: [your machine type]
  Disk Size: [your disk size]
  Preemptible: [true or false]
Cloud TPU:
  Size: [your TPU size]
  Preemptible: [true or false]

OK to create your Cloud TPU resources with the above configuration? [Yn]:

y キーを押して、Cloud TPU リソースを作成します。

TPU Pod

作業しているゾーン内の VM 上に、Cloud TPU スライスを設定します。

$ ctpu up --tpu-size=v3-32 --machine-type n1-standard-8

構成に関する次のメッセージが表示されます。

ctpu will use the following configuration:

Name: [your TPU's name]
Zone: [your project's zone]
GCP Project: [your project's name]
TensorFlow Version: 1.14
VM:
  Machine Type: [your machine type]
  Disk Size: [your disk size]
  Preemptible: [true or false]
Cloud TPU:
  Size: [your TPU size]
  Preemptible: [true or false]

OK to create your Cloud TPU resources with the above configuration? [Yn]:

y キーを押して、Cloud TPU リソースを作成します。

ctpu up コマンドにより、仮想マシン(VM)と Cloud TPU サービスが作成されます。

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

Compute Engine VM を確認する

ctpu up コマンドの実行が終了したら、shell プロンプトが username@tpuname になっていることを確認します。これは、Compute Engine VM にログインしていることを意味します。

RetinaNet モデルを確認する

ctpu コマンドは Compute Engine 仮想マシン(VM)を起動するときに、次の場所にある TensorFlow ブランチから自動的に RetinaNet モデルファイルを取得して配置します。

(vm)$ ls /usr/share/tpu/models/official/detection/

COCO データセットを準備する

モデルをトレーニングするには、その前に、トレーニング データを準備する必要があります。RetinaNet モデルは、COCO データセットでトレーニングするように構成されています。

YOUR-BUCKET-NAME を Cloud Storage バケットの名前に置き換えて、次の環境変数を設定します。

(vm)$ export STORAGE_BUCKET=gs://YOUR-BUCKET-NAME

download_and_preprocess_coco.sh スクリプトを実行して、COCO データセットを、トレーニング アプリケーションで使用可能な一連の TFRecord(*.tfrecord)に変換します。

(vm)$ bash /usr/share/tpu/tools/datasets/download_and_preprocess_coco.sh ./data/dir/coco

これにより、必要なライブラリがインストールされてから、前処理スクリプトが実行されます。ローカルのデータ ディレクトリにいくつかの *.tfrecord ファイルが出力されます。COCO のダウンロードと変換スクリプトが完了するまでには約 1 時間かかります。

出力されたファイルを Cloud Storage にコピーして、トレーニング中にモデルがアクセスできるようにします。gsutil を使用して、ローカルデータ ディレクトリから Cloud Storage バケットにファイルをコピーします。アノテーション ファイルも保存する必要があります。アノテーション ファイルによって、モデルのパフォーマンスが検証されます。

(vm)$ gsutil -m cp ./data/dir/coco/*.tfrecord ${STORAGE_BUCKET}/coco
(vm)$ gsutil cp ./data/dir/coco/raw-data/annotations/*.json ${STORAGE_BUCKET}/coco

追加のパッケージをインストールする

RetinaNet トレーニング アプリケーションには、いくつかの追加パッケージが必要です。現時点で、これらのパッケージをインストールしておきます。

(vm)$ sudo apt-get install -y python-tk
(vm)$ pip install Cython matplotlib opencv-python-headless pyyaml Pillow
(vm)$ pip install 'git+https://github.com/cocodataset/cocoapi#egg=pycocotools&subdirectory=PythonAPI'

VM 接続に対するキープアライブ値を更新する

このチュートリアルでは、Compute Engine インスタンスへの長時間接続が必要となります。インスタンスへの接続が切断されないようにするには、次のコマンドを実行します。

(vm)$ sudo /sbin/sysctl \
       -w net.ipv4.tcp_keepalive_time=60 \
       net.ipv4.tcp_keepalive_intvl=60 \
       net.ipv4.tcp_keepalive_probes=5

モデル ディレクトリのパスを設定する

(vm)$ export PYTHONPATH="$PYTHONPATH:/usr/share/tpu/models"

モデルを実行する

このセクションでは、RetinaNet モデルを実行する 5 つの方法を説明します。いずれも TensorFlow 1.13 または TensorFlow 1.14 で実行します。

  • トレーニングのみ行う(単一の TPU デバイス)
  • 評価のみ行う(単一の TPU デバイス)
  • トレーニングと評価を交互に行う(単一の TPU デバイス)
  • 推論用のモデルをエクスポートする(単一の TPU デバイス)
  • Cloud TPU Pod でトレーニングを行う

単一の Cloud TPU デバイスタイプでのトレーニングと評価

以下のトレーニング スクリプトは、Cloud TPU v3-8 で実行されたものです。トレーニング時間は長くなりますが、Cloud TPU v2-8 でも実行できます。より大規模な Cloud TPU タイプでトレーニングする場合は、Cloud TPU Pod でのトレーニングをご覧ください。

トレーニングのみ

このスクリプトは、22,500 ステップのトレーニングを行います。Cloud TPU v3-8 で実行する場合、トレーニングは約 2 時間かかります。

  1. 次の環境変数を設定します。

    (vm)$ TPU_NAME=$TPU_NAME  \
    export MODEL_DIR=${STORAGE_BUCKET}/retinanet-model-train; \
    export RESNET_CHECKPOINT=gs://cloud-tpu-artifacts/resnet/resnet-nhwc-2018-10-14/model.ckpt-112602; \
    export TRAIN_FILE_PATTERN=${STORAGE_BUCKET}/coco/train-*; \
    export EVAL_FILE_PATTERN=${STORAGE_BUCKET}/coco/val-*; \
    export VAL_JSON_FILE=${STORAGE_BUCKET}/coco/instances_val2017.json
    
  2. トレーニング スクリプトを実行します。

    (vm)$ python /usr/share/tpu/models/official/detection/main.py \
    --use_tpu=True \
    --tpu="${TPU_NAME?}" \
    --num_cores=8 \
    --model_dir="${MODEL_DIR?}" \
    --mode="train" \
    --eval_after_training=True \
    --params_override="{ type: retinanet, train: { checkpoint: { path: ${RESNET_CHECKPOINT?}, prefix: resnet50/ }, train_file_pattern: ${TRAIN_FILE_PATTERN?} }, eval: { val_json_file: ${VAL_JSON_FILE?}, eval_file_pattern: ${EVAL_FILE_PATTERN?}, eval_samples: 5000 } }"
    
    • --tpu は、Cloud TPU の名前を指定します。ctpu はこの名前を環境変数(TPU_NAME)として Compute Engine VM に渡します。
    • RESNET_CHECKPOINT は、事前トレーニングされたチェックポイントを指定します。RetinaNet には、バックボーン ネットワークとして事前トレーニングされた画像分類モデル(ResNet など)が必要です。この例では、ResNet デモモデルで作成された、事前トレーニングされたチェックポイントを使用しています。必要に応じて、独自の ResNet モデルをトレーニングし、ResNet モデル ディレクトリ内のチェックポイントを指定することもできます。

評価のみ

次の手順では、COCO 評価データを使用します。評価ステップが完了するまでには約 10 分かかります。

  1. 次の環境変数を設定します。

    (vm)$ TPU_NAME=$TPU_NAME  \
    export MODEL_DIR=${STORAGE_BUCKET}/retinanet-model-train; \
    export EVAL_FILE_PATTERN=${STORAGE_BUCKET}/coco/val-*; \
    export VAL_JSON_FILE=${STORAGE_BUCKET}/coco/instances_val2017.json \
    export EVAL_SAMPLES=5000
    
  2. 評価スクリプトを実行します。

    (vm)$ python /usr/share/tpu/models/official/detection/main.py \
    --use_tpu=True \
    --tpu="${TPU_NAME?}" \
    --num_cores=8 \
    --model_dir="${MODEL_DIR?}" \
    --mode="eval" \
    --params_override="{ type: retinanet, eval: { val_json_file: ${VAL_JSON_FILE?}, eval_file_pattern: ${EVAL_FILE_PATTERN?}, eval_samples: ${EVAL_SAMPLES?} } }"
    
    • --tpu は、Cloud TPU の名前を指定します。ctpu はこの名前を環境変数(TPU_NAME)として Compute Engine VM に渡します。

トレーニングと評価

このスクリプトは合計 22,500 ステップのトレーニングを行います。1,000 ステップのトレーニングと 5,000 個の評価サンプルの評価を交互に行います。v3-8 Cloud TPU の場合、トレーニングと評価がすべて完了するまでに約 9 時間かかります。

  1. 次の環境変数を設定します。

    (vm)$ TPU_NAME=$TPU_NAME  \
    export MODEL_DIR=${STORAGE_BUCKET}/retinanet-train-eval; \
    export RESNET_CHECKPOINT=gs://cloud-tpu-artifacts/resnet/resnet-nhwc-2018-10-14/model.ckpt-112602; \
    export TRAIN_FILE_PATTERN=${STORAGE_BUCKET}/coco/train-*; \
    export EVAL_FILE_PATTERN=${STORAGE_BUCKET}/coco/val-*; \
    export VAL_JSON_FILE=${STORAGE_BUCKET}/coco/instances_val2017.json \
    export EVAL_SAMPLES=5000 \
    export NUM_STEPS_PER_EVAL=1000
    
  2. トレーニングおよび評価スクリプトを実行します。

    (vm)$ python /usr/share/tpu/models/official/detection/main.py \
    --use_tpu=True \
    --tpu="${TPU_NAME?}" \
    --num_cores=8 \
    --model_dir="${MODEL_DIR?}" \
    --mode="train_and_eval" \
    --params_override="{ type: retinanet, train: { checkpoint: { path: ${RESNET_CHECKPOINT?}, prefix: resnet50/ }, train_file_pattern: ${TRAIN_FILE_PATTERN?} }, eval: { val_json_file: ${VAL_JSON_FILE?}, eval_file_pattern: ${EVAL_FILE_PATTERN?}, eval_samples: ${EVAL_SAMPLES?}, num_steps_per_eval: ${NUM_STEPS_PER_EVAL?} } }"
    
    • --tpu は、Cloud TPU の名前を指定します。ctpu はこの名前を環境変数(TPU_NAME)として Compute Engine VM に渡します。

モデルのエクスポート

次のスクリプトは、トレーニング済みのモデルを高レベルの TensorFlow 形式(SavedModel)に保存して、推論に使用できるようにします。

  1. 次の環境変数を設定します。

    (vm)$ export EXPORT_DIR="Target directory to store the SavedModel" \
    export CHECKPOINT_PATH="Path to the trained checkpoint" \
    export USE_TPU=true \
    export PARAMS_OVERRIDE="" \
    export BATCH_SIZE=1 \
    export INPUT_TYPE="image_bytes" \
    export INPUT_NAME="input" \
    export INPUT_IMAGE_SIZE="640,640" \
    export OUTPUT_IMAGE_INFO=true \
    export OUTPUT_NORMALIZED_COORDINATES=false \
    export CAST_NUM_DETECTIONS_TO_FLOAT=true
    
  2. モデルのエクスポート スクリプトを実行します。

    (vm)$ /usr/share/tpu/models/official/detection/export_saved_model.py \
    --export_dir="${EXPORT_DIR?}" \
    --checkpoint_path="${CHECKPOINT_PATH?}" \
    --use_tpu="${USE_TPU?}" \
    --params_overrides="${PARAMS_OVERRIDE?}" \
    --batch_size="${BATCH_SIZE?}" \
    --input_type="${INPUT_TYPE?}" \
    --input_name="${INPUT_NAME?}" \
    --input_image_size="${INPUT_IMAGE_SIZE?}" \
    --output_image_info="${OUTPUT_IMAGE_INFO?}" \
    --output_normalized_coordinates="${OUTPUT_NORMALIZED_COORDINATES?}" \
    --cast_num_detections_to_float="${CAST_NUM_DETECTIONS_TO_FLOAT?}"
    

Cloud TPU Pod でのトレーニング

以下のトレーニングは v3-32 TPU タイプで実行されています。別の Pod TPU タイプを使用する場合は、その TPU タイプのコア数に合わせて --num_cores パラメータの値を調整してください。また、train_batch_size には使用 TPU タイプのコア数で割り切れる値を設定する必要があります。

このスクリプトは 2,109 ステップのトレーニングを行います。トレーニングが完了するまでにかかる時間は、v3-32 TPU タイプでは約 30 分、v3-128 TPU タイプでは約 10 分です。

  1. 次の環境変数を設定します。

    (vm)$ TPU_NAME=$TPU_NAME  \
    export MODEL_DIR=${STORAGE_BUCKET}/retinanet-model-pod; \
    export  RESNET_CHECKPOINT=gs://cloud-tpu-artifacts/resnet/resnet-nhwc-2018-10-14/model.ckpt-112602; \
    export TRAIN_FILE_PATTERN=${STORAGE_BUCKET}/coco/train-*;
    
  2. Pod トレーニング スクリプトを実行します。

    (vm)$ python /usr/share/tpu/models/official/detection/main.py \
      --use_tpu=True \
      --tpu="${TPU_NAME?}" \
      --num_cores=32 \
      --model_dir="${MODEL_DIR?}" \
      --mode="train" \
      --eval_after_training=False \
      --params_override="{ type: retinanet, train: { train_batch_size: 1024, total_steps: 2109, learning_rate: { warmup_steps: 820, init_learning_rate: 0.64, learning_rate_levels: [0.064, 0.0064], learning_rate_steps: [1641, 1992] }, checkpoint: { path: ${RESNET_CHECKPOINT?}, prefix: resnet50/ }, train_file_pattern: ${TRAIN_FILE_PATTERN?} }, resnet: { batch_norm: { batch_norm_momentum: 0.9 }}, fpn: { batch_norm: { batch_norm_momentum: 0.9 }}, retinanet_head: { batch_norm: { batch_norm_momentum: 0.9 }} }"
    

トレーニングの状況を確認する

TensorBoard を使用して、トレーニングの進行状況を可視化します。

評価 VM を設定すると、新しいチェックポイントが継続的に読み取られ、評価イベントが model_dir ディレクトリに出力されます。TensorBoard で、トレーニングと評価の現在の状況と評価を確認できます。

TensorBoard の設定ガイドに従い、TensorBoard の Cloud TPU ツールを使ってみてください。

クリーンアップ

このトピックで使用したリソースについて GCP アカウントに課金されないようにする手順は次のとおりです。

  1. Compute Engine VM との接続を解除します。

    (vm)$ exit
    

    プロンプトが user@projectname と表示され、Cloud Shell 内にいることが示されます。

  2. Cloud Shell で、Cloud TPU の設定時に使用した --zone フラグを指定して ctpu delete を実行し、Compute Engine VM と Cloud TPU を削除します。

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

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

    $ gsutil rm -r gs://YOUR-BUCKET-NAME
    

次のステップ

さまざまなサイズの画像でトレーニングする

より規模の大きいバックボーン ネットワーク(たとえば ResNet-50 ではなく ResNet-101)を使用した場合の違いを調べることができます。サイズの大きい入力画像とより強力なバックボーンを使用すると、処理時間は長くなるものの、モデルの精度が高くなります。

別のベースを使用する

また、独自のデータセットで ResNet モデルを事前トレーニングし、それを RetinaNet モデルのベースとして使用することもできます。少々手間をかければ、ResNet を別のバックボーン ネットワークで置き換えることもできます。最終的に独自のオブジェクト検出モデルを実装しようと考えている場合は、このネットワークが実験基盤として役立ちます。

TPU Pod でのバッチサイズを大きくする

Cloud TPU Pod を使用する場合、より大きいバッチサイズを指定すると、トレーニング時間を短縮できます。たとえば 8 コアの Cloud TPU ではバッチサイズとして 64 を使用し、32 コアの Cloud TPU では 256、128 コアの Cloud TPU では 1,024 を使用します。所与のバッチサイズに対して、モデルは学習率を比例的にスケーリングします。

(vm)$ export MODEL_DIR=${STORAGE_BUCKET}/retinanet-model; \
export RESNET_CHECKPOINT=gs://cloud-tpu-artifacts/resnet/resnet-nhwc-2018-10-14/model.ckpt-112602; \
export TRAIN_FILE_PATTERN=${STORAGE_BUCKET}/coco/train-*; \
python /usr/share/tpu/models/experimental/detection/main.py \
  --use_tpu=True \
  --tpu="${TPU_NAME?}" \
  --num_cores=128 \
  --model_dir="${MODEL_DIR?}" \
  --mode="train" \
  --eval_after_training=False \
  --params_override="{ type: retinanet, train: { train_batch_size: 1024, total_steps: 2109, learning_rate: { warmup_steps: 820, init_learning_rate: 0.64, learning_rate_levels: [0.064, 0.0064], learning_rate_steps: [1641, 1992] }, checkpoint: { path: ${RESNET_CHECKPOINT?}, prefix: resnet50/ }, train_file_pattern: ${TRAIN_FILE_PATTERN?} }, resnet: { batch_norm: { batch_norm_momentum: 0.9 }}, fpn: { batch_norm: { batch_norm_momentum: 0.9 }}, retinanet_head: { batch_norm: { batch_norm_momentum: 0.9 }} }"

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...