ホーム » 分散 TensorFlow

分散 TensorFlow」カテゴリーアーカイブ

TensorFlow 2.0 Alpha : ガイド : TensorFlow で分散訓練

TensorFlow 2.0 Alpha : ガイド : TensorFlow で分散訓練 (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 03/21/2019

* 本ページは、TensorFlow の本家サイトの TF 2.0 Alpha の以下のページを翻訳した上で適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

ガイド : TensorFlow で分散訓練

概要

tf.distribute.Strategy はマルチ GPU、マルチマシンや TPU に渡り訓練を分散するための TensorFlow API です。この API を使用して、ユーザは既存のモデルと訓練コードを最小限のコード変更で分散できます。tf.distribute.Strategy はこれらの主要なゴールに留意して設計されています : * 容易に使用できて研究者、ML 技術者, etc. を含むマルチ・ユーザセグメントをサポートします。* 良いパフォーマンスを独創的に提供します。* ストラテジー間の容易な切り替え。

tf.distribute.Strategy は TensorFlow の高位 API、tf.keras と tf.estimator で単に数行のコード変更で利用できます。それはまたカスタム訓練ループ (そして一般に TensorFlow を使用する任意の計算) を分散するために使用できる API も提供します。TensorFlow 2.0 では、ユーザはプログラムを eagerly に、あるいは tf.function を使用してグラフ内で実行できます。tf.distribute.Strategy はこれらの実行モードの両者をサポートすることを意図します。このガイドの時間の殆どで訓練について語るかも知れませんが、この API は異なるプラットフォーム上で評価と予測を分散するためにも使用できることに注意してください。

すぐに見るように、貴方のコードで tf.distribute.Strategy を使用するためには非常に少しの変更が必要とされます。これは strategy-aware とするために TensorFlow の基礎的なコンポーネントを変更したからです。これは変数、層、モデル、optimizer、メトリクス、要約そしてチェックポイントを含みます。

このガイドでは、様々なタイプのストラテジーについてとそれらを異なる状況でどのように使用できるかについて話します。

# Import TensorFlow
from __future__ import absolute_import, division, print_function
!pip install -q tensorflow==2.0.0-alpha0
import tensorflow as tf

 

ストラテジーのタイプ

tf.distribute.Strategy は異なる軸に沿った多くのユースケースをカバーすることを意図しています。これらの組み合わせの幾つかは現在サポートされていて他のものは将来的に追加されます。これらの軸の幾つかは : * 同期 vs 非同期訓練です : これらはデータ並列で訓練を分散する 2 つの一般的な方法です。同期訓練では、総てのワーカーは入力データの異なるスライスに渡り同期的に訓練して、各ステップで勾配を集めます。非同期訓練では、総てのワーカーは入力データに渡り独立的に訓練して変数を非同期的に更新します。典型的には同期訓練は all-reduce を通してそして非同期 (訓練) はパラメータサーバ・アーキテクチャを通してサポートされます。* ハードウェア・プラットフォーム: ユーザは一つのマシンかネットワーク内のマルチマシン (それぞれ 0 かそれ以上の GPU) 上のマルチ GPU、あるいはクラウド TPU 上に彼らの訓練をスケールすることを望むかもしれません。

これらのユースケースをサポートするために、利用可能な 4 つのストラテジーを持ちます。次のセクションでは現時点で TF 2.0-alpha 内でどのシナリオにおいてこれらのどれがサポートされるかについて話しをします。

 

MirroredStrategy

tf.distribute.MirroredStrategy は一つのマシン上のマルチ GPU 上で同期分散訓練をサポートします。それは GPU デバイス毎に一つのレプリカを作成します。モデルの各変数は総てのレプリカに渡りミラーリングされます。一緒に、これらの変数は MirroredVariable と呼ばれる単一の概念的な変数を形成します。これらの変数は同一の更新を適用することにより互いに同期されます。

効率的な all-reduce アルゴリズムはデバイスを通して変数更新を伝達するために使用されます。all-reduce は総てのデバイスに渡り tensor をそれらを合計することにより集めてそれらを各デバイスで利用可能にします。それは融合されたアルゴリズムで非常に効率的で同期のオーバーヘッドを著しく減らせます。デバイス間で利用可能な通信のタイプに依拠して、利用可能な多くの all-reduce アルゴリズムと実装があります。デフォルトでは、それは all-reduce 実装として NVIDIA NCCL を使用します。ユーザはまた提供する 2, 3 の他のオプション間で選択できて、彼ら自身のものを書くこともできます。

ここに MirroredStrategy を作成する最も単純な方法があります :

mirrored_strategy = tf.distribute.MirroredStrategy()
WARNING: Logging before flag parsing goes to stderr.
W0307 18:06:27.818398 139925123892992 cross_device_ops.py:1111] Not all devices in `tf.distribute.Strategy` are visible to TensorFlow.

これは MirroredStrategy インスタンスを作成します、これは TensorFlow に見える総ての GPU を使用して、そして交差デバイス通信として NCCL を使用します。

貴方のマシン上の GPU の一部だけを利用することを望む場合、それをこのようにできます :

mirrored_strategy = tf.distribute.MirroredStrategy(devices=["/gpu:0", "/gpu:1"])
W0307 18:06:27.835354 139925123892992 cross_device_ops.py:1106] Not all devices in `tf.distribute.Strategy` are visible to TensorFlow.

交差デバイス通信をオーバーライドすることを望む場合、cross_device_ops 引数を使用して tf.distribute.CrossDeviceOps のインスタンスを供給することによりそれを行なうことができます。デフォルトの tf.distribute.NcclAllReduce 以外の 2 つの他のオプションとして現在 tf.distribute.HierarchicalCopyAllReduce と tf.distribute.ReductionToOneDevice を提供しています。

mirrored_strategy = tf.distribute.MirroredStrategy(
    cross_device_ops=tf.distribute.HierarchicalCopyAllReduce())
W0307 18:06:27.850420 139925123892992 cross_device_ops.py:1111] Not all devices in `tf.distribute.Strategy` are visible to TensorFlow.

 

MultiWorkerMirroredStrategy

tf.distribute.experimental.MultiWorkerMirroredStrategy は MirroredStrategy に非常に類似しています。それはマルチ・ワーカーに渡る同期分散訓練を実装し、それぞれ潜在的にマルチ GPU を持ちます。MirroredStrategy と同様に、それはモデルの総ての変数のコピーを総てのワーカーに渡り各デバイス上に作成します。

それは CollectiveOps を変数の同期を取るために使用されるマルチワーカー all-reduce 通信メソッドとして使用します。collective op は TensorFlow グラフの単一 op で、それはハードウェア、ネットワーク・トポロジーそして tensor サイズに従って TensorFlow ランタイムで all-reduce アルゴリズムを自動的に選択できます。

それは追加のパフォーマンス最適化も実装します。例えば、それは小さい tensor 上のマルチ all-reductions をより巨大な tensor 上のより少ない all-reductions に変換する静的最適化を含みます。更に、それをプラグイン・アーキテクチャを持つように設計していますので、将来的にユーザは彼らのハードウェアのためにより良く調整されたアルゴリズムをプラグインできるでしょう。collective ops はまた broadcast と all-gather のような他の collective 演算も実装することに注意してください。

ここに MultiWorkerMirroredStrategy を作成する最も単純な方法があります :

multiworker_strategy = tf.distribute.experimental.MultiWorkerMirroredStrategy()
W0307 18:06:27.865478 139925123892992 cross_device_ops.py:1111] Not all devices in `tf.distribute.Strategy` are visible to TensorFlow.

MultiWorkerMirroredStrategy は現在 collective ops の 2 つの異なる実装間で選択することを可能にします。CollectiveCommunication.RING は gRPC を通信層として使用して ring-based collectives を実装します。CollectiveCommunication.NCCL は collectives を実装するために Nvidia の NCCL を使用します。CollectiveCommunication.AUTO は選択を実行時まで延期します。collective 実装の最善の選択は GPU の数と種類、そしてクラスタのネットワーク相互接続に依拠します。それらをこのように指定できます :

multiworker_strategy = tf.distribute.experimental.MultiWorkerMirroredStrategy(
    tf.distribute.experimental.CollectiveCommunication.NCCL)
W0307 18:06:27.882048 139925123892992 cross_device_ops.py:1111] Not all devices in `tf.distribute.Strategy` are visible to TensorFlow.

マルチ GPU 訓練と比較して、マルチワーカー訓練を進めるための主要な違いの一つはマルチワーカー・セットアップです。”TF_CONFIG” 環境変数はクラスタの一部である各ワーカーへのクラスタ構成を指定するための TensorFlow の標準的な方法です。どのようにこれが成されるかのより詳細については下の “TF_CONFIG” セクションを見てください。

Note: このストラテジーは 実験的 です、何故ならば現在それを改良してより多くのシナリオで動作するようにしているからです。その一環として、 将来的に API が変更されることを想定してください。

 

TPUStrategy

tf.distribute.experimental.TPUStrategy はユーザに彼らの TensorFlow 訓練を Tensor 処理ユニット (TPU) 上で実行させます。TPU は機械学習ワークロードを劇的に高速化するように設計された Google の特化された ASIC です。それらは Google Colab、TensorFlow Research Cloud そして Google Compute Engine で利用可能です。

分散訓練アーキテクチャの観点からは、TPUStrategy は同じ MirroredStrategy です – それは同期分散訓練を実装します。TPU はマルチ TPU コアに渡る効率的な all-reduce のそれら自身の実装と他の collective 演算を提供します、それらは TPUStrategy で使用されます。

ここにどのように TPUStrategy をインスタンス化するかがあります。Note: このコードを Colab で実行するには、Colab 実行時に TPU を選択すべきです。実行可能なバージョンについては Using TPUs ガイド (訳注: リンク切れ) を見てください。

resolver = tf.distribute.cluster_resolver.TPUClusterResolver()
tf.tpu.experimental.initialize_tpu_system(resolver)
tpu_strategy = tf.distribute.experimental.TPUStrategy(resolver)

TPUClusterResolver インスタンスは TPU を見つける助けをします。Colab では、それにどのような引数も指定する必要がありません。これを Cloud TPU で使用することを望む場合、tpu 引数で貴方の TPU リソースの名前を指定する必要があります。またプログラムの最初で tpu システムを明示的に初期化する必要もあります。これは TPU が計算のために使用できる前に必要で理想的には最初に成されるべきです、何故ならばそれはまた TPU メモリも拭き取るために総ての状態が失われるからです。

 

ParameterServerStrategy

tf.distribute.experimental.ParameterServerStrategy はパラメータサーバ訓練をサポートします。それはマルチ GPU 同期ローカル訓練か非同期マルチマシン訓練のために使用できます。一つのマシン上のローカルで訓練するために使用されるとき、変数はミラーリングされません、代わりにそれらは CPU に置かれて演算は総てのローカル GPU に渡り複製されます。マルチマシン設定では、幾つかのマシンはワーカーとしてそして幾つかはパラメータサーバとして指定されます。モデルの各変数は一つのパラメータサーバに置かれます。計算は総てのワーカーの総ての GPU に渡り複製されます。

コードの観点からは、それは他のストラテジーと同様に見えます :

ps_strategy = tf.distribute.experimental.ParameterServerStrategy()

マルチワーカー訓練については、”TF_CONFIG” はクラスタのパラメータサーバとワーカーの構成を指定する必要があります、それについて下の “TF_CONFIG” で更に読むことができます。

ここまで利用可能な異なるストラテジーが何であるかそしてそれらをどのようにインスタンス化できるかについて話してきました。次の幾つかのセクションでは、貴方の訓練を分散するためにそれらを使用する異なる方法について話します。このガイドでは短いコードスニペットを示して、end-to-end で実行できる完全なチュートリアルへリンクします。

 

Keras で tf.distribute.Strategy を使用する

私達は tf.distribute.Strategy を tf.keras に統合しました、これは Keras API 仕様の TensorFlow 実装です。tf.keras はモデルを構築して訓練するための高位 API です。

tf.keras バックエンドに統合することで、Keras ユーザに Keras 訓練フレームワークで書かれた彼らの訓練を分散することをシームレスにしました。ユーザのプログラムで変更が必要なものは以下だけです : (1) 適切な tf.distribute.Strategy のインスタンスを作成します。そして (2) Keras モデルの作成とコンパイルを strategy.scope の内側に移す。

ここに一つの dense 層を持つ非常に簡単な Keras モデルのためにこれを行なうコードのスニペットがあります :

mirrored_strategy = tf.distribute.MirroredStrategy()
with mirrored_strategy.scope():
  model = tf.keras.Sequential([tf.keras.layers.Dense(1, input_shape=(1,))])
  model.compile(loss='mse', optimizer='sgd')
W0307 18:06:27.907308 139925123892992 cross_device_ops.py:1111] Not all devices in `tf.distribute.Strategy` are visible to TensorFlow.

この例では MirroredStrategy を使用していますのでこれをマルチ GPU を持つ (一つの) マシン上で実行できます。strategy.scope() はコードのどの部分を分散して実行するかを示しました。このスコープの内側でモデルを作成すると通常の変数の代わりにミラーリングされた変数を作成することを可能にします。このスコープ下でコンパイルするとユーザはこのストラテジーを使用してモデルを訓練することを意図していることを知ることができます。ひとたびこれがセットアップされれば、モデルを通常するように fit できます。MirroredStrategy は勾配を集める等、利用可能な GPU 上でモデルの訓練を複製する処理をします。

dataset = tf.data.Dataset.from_tensors(([1.], [1.])).repeat(100).batch(10)
model.fit(dataset, epochs=2)
model.evaluate(dataset)
W0307 18:06:28.070022 139925123892992 training_utils.py:1353] Expected a shuffled dataset but input dataset `x` is not shuffled. Please invoke `shuffle()` on input dataset.

Epoch 1/2
10/10 [==============================] - 0s 7ms/step - loss: 2.1846
Epoch 2/2
10/10 [==============================] - 0s 2ms/step - loss: 2.0163
10/10 [==============================] - 0s 5ms/step - loss: 1.9289

1.9288513660430908

ここで訓練と評価入力を提供するために tf.data.Dataset を使用しました。numpy 配列も使用できます :

import numpy as np
inputs, targets = np.ones((100, 1)), np.ones((100, 1))
model.fit(inputs, targets, epochs=2, batch_size=10)
Epoch 1/2
10/10 [==============================] - 0s 2ms/step - loss: 1.8610
Epoch 2/2
10/10 [==============================] - 0s 2ms/step - loss: 1.7176

<tensorflow.python.keras.callbacks.History at 0x7f4274ade400>

両者のケース (dataset か numpy) で、与えられた入力の各バッチはマルチレプリカの中で均等に分割されます。例えば、2 GPU で MirroredStrategy を使用する場合、size 10 の各バッチは 2 GPU の間で分割されて、それぞれが各ステップで 5 入力サンプルを受け取ります。それで貴方がより多くの GPU を追加するにつれて各エポックはより高速に訓練されます。典型的には、貴方がより多くのアクセラレータを追加するとき特別な計算パワーを効果的に利用するためにバッチサイズを増やすことを望むでしょう、またモデルに依拠して、学習率を再調整する必要もあるでしょう。レプリカの数を得るために strategy.num_replicas_in_sync を使用できます。

# Compute global batch size using number of replicas.
BATCH_SIZE_PER_REPLICA = 5
global_batch_size = (BATCH_SIZE_PER_REPLICA * 
                     mirrored_strategy.num_replicas_in_sync)
dataset = tf.data.Dataset.from_tensors(([1.], [1.])).repeat(100)
dataset = dataset.batch(global_batch_size)

LEARNING_RATES_BY_BATCH_SIZE = {5: 0.1, 10: 0.15}
learning_rate = LEARNING_RATES_BY_BATCH_SIZE[global_batch_size]

 

今は何がサポートされますか?

TF 2.0 alpha リリースでは、MirroredStrategy を使用した Keras による訓練と、ParameterServerStrategy を使用した一つのマシンのパラメータサーバをサポートします。他のストラテジーのためのサポートは間もなくです。API とどのように使用するかも上と正確に同じです。TF 2.0 の Keras で TPUStrategy や MultiWorkerMirorredStrategy のような他のストラテジーを使用することを望む場合、現在は eager execution を無効にする (tf.compat.v1.disable_eager_execution()) ことによりそれを行なうことができます。注意すべきもう一つのことは Keras でマルチワーカーのために MultiWorkerMirorredStrategy を使用するとき、現在ユーザは異なるワーカーのためにデータを明示的にシャードするかシャッフルしなければならないことですが、将来的には知的に入力データを自動的にシャードするようにこれを変更します。

 

サンプルとチュートリアル

ここに Keras の end-to-end で上の統合を示すチュートリアルとサンプルのリストがあります : 1. MirroredStrategy で MNIST を訓練する チュートリアル。2. TPUStrategy で Fashion MNIST を訓練する チュートリアル (訳注: リンク切れ) (現在は disable_eager_execution を使用)。3. MirroredStrategy を使用して ImageNet データで公式 ResNet50 訓練。4. TPUStrategy で Cloud TPU 上 Imagenet データで訓練された ResNet50。このサンプルは現在は TensorFlow 1.x で動作のみ動作することに注意してください。

 

Estimator で tf.distribute.Strategy を使用する

tf.estimator は分散訓練 TensorFlow API で、それは非同期パラメータサーバのアプローチを元々サポートしていました。Keras でのように、私達は tf.distribute.Strategy を tf.Estimator に統合しました、その結果 Estimator を訓練に使用しているユーザは彼らのコードへの僅かの変更で訓練を容易に分散に変更できます。これにより、estimater ユーザは今では TPU の使用に加えて、マルチ GPU とマルチワーカー上で同期分散訓練を行なうことができます。

tf.distribute.Strategy の使用方法は Keras の場合と僅かに異なります。strategy.scope を使用する代わりに、今は strategy オブジェクトを Estimator のための RunConfig に渡します。

ここに premade estimator LinearRegressor と MirroredStrategy でこれを示すコードスニペットがあります :

mirrored_strategy = tf.distribute.MirroredStrategy()
config = tf.estimator.RunConfig(
    train_distribute=mirrored_strategy, eval_distribute=mirrored_strategy)
regressor = tf.estimator.LinearRegressor(
    feature_columns=[tf.feature_column.numeric_column('feats')],
    optimizer='SGD',
    config=config)
W0307 18:06:33.035279 139925123892992 cross_device_ops.py:1111] Not all devices in `tf.distribute.Strategy` are visible to TensorFlow.
W0307 18:06:33.037824 139925123892992 estimator.py:1799] Using temporary folder as model directory: /tmp/tmp9yy5cqbb

ここでは premade Estimator を使用しますが、同じコードがカスタム Estimator でもまた動作します。train_evaluate は訓練がどのように分散されるかを決定し、そして eval_distribute は評価がどのように分散されるかを決定します。これはもう一つの Keras との違いです、そこでは訓練と評価の両者のために同じ strategy を使用します。

今ではこの Estimator を input 関数で訓練して評価することができます :

def input_fn():
  dataset = tf.data.Dataset.from_tensors(({"feats":[1.]}, [1.]))
  return dataset.repeat(1000).batch(10)
regressor.train(input_fn=input_fn, steps=10)
regressor.evaluate(input_fn=input_fn, steps=10)
W0307 18:06:33.136213 139916847593216 distribute_lib.py:830] Partitioned variables are disabled when using current tf.distribute.Strategy.
W0307 18:06:33.151402 139916847593216 deprecation.py:323] From /usr/local/lib/python3.5/dist-packages/tensorflow/python/feature_column/feature_column_v2.py:2758: to_float (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.cast` instead.
W0307 18:06:34.565543 139925123892992 deprecation.py:323] From /usr/local/lib/python3.5/dist-packages/tensorflow/python/training/saver.py:1276: checkpoint_exists (from tensorflow.python.training.checkpoint_management) is deprecated and will be removed in a future version.
Instructions for updating:
Use standard file APIs to check for files with this prefix.

{'average_loss': 1.4210855e-14,
 'global_step': 10,
 'label/mean': 1.0,
 'loss': 1.4210855e-14,
 'prediction/mean': 0.99999994}

ここで強調したい Estimator と Keras 間のもう一つの違いは入力処理です。Keras では、dataset の各バッチはマルチ・レプリカに渡り分割されることに言及しました。Estimator では、けれども、ユーザは input_fn を提供して彼らのデータがワーカーとデバイスに渡りどのように分散されることを望むかについて完全な制御を持ちます。私達はバッチの自動的分割を行ないませんし、異なるワーカーに渡りデータを自動的にシャードもしません。提供される input_fn はワーカー毎に一度呼び出され、ワーカー毎に一つの dataset を与えます。それからその dastaset から一つのバッチがそのワーカー上の一つのレプリカに供給され、従って 1 ワーカー上の N レプリカのために N バッチを消費します。換言すれば、input_fn から返される dataset はサイズ PER_REPLICA_BATCH_SIZE のバッチを提供するべきです。そしてステップのためのグローバル・バッチサイズは PER_REPLICA_BATCH_SIZE * strategy.num_replicas_in_sync として得られます。マルチワーカー訓練を行なうとき、ユーザはまたデータをワーカーに渡り分割するかそれぞれの上でランダムシードでシャッフルすることもまた望むでしょう。これをどのように行なうかのサンプルを マルチワーカー・チュートリアル で見ることができます。

Estimator で MirroredStrategy を使用するサンプルを示しました。貴方はまた Estimator で TPUStrategy を使用することもまたできます、正確に同じ方法で :

config = tf.estimator.RunConfig(
    train_distribute=tpu_strategy, eval_distribute=tpu_strategy)

そして同様に、マルチワーカーとパラメータサーバのストラテジーもまた使用できます。コードは同じままですが、tf.estimator.train_and_evaluate を使用してクラスタで動作する各バイナリに対して “TF_CONFIG” 環境変数を設定する必要があります。

 

今は何がサポートされますか?

TF 2.0 alpha リリースでは、総てのストラテジーを使用して Estimater による訓練をサポートします。

 

サンプルとチュートリアル

ここに幾つかのサンプルがあります、これらは Estimator で様々なストラテジーの end-to-end の使用方法を示します :

  1. MultiWorkerMirroredStrategy を使用してマルチワーカーで MNIST を訓練する [Tutorial]((../tutorials/distribute/multi_worker)
  2. Kuberentes テンプレートを使用した tensorflow/ecosystem のマルチワーカー訓練のための end-to-end サンプル。このサンプルは Keras モデルから始めてそれを tf.keras.estimator.model_to_estimator API を使用して Estimator に変換します。
  3. 公式 ResNet50 モデル、これは MirroredStrategy か MultiWorkerMirroredStrategy を使用して訓練できます。
  4. TPUStrategy による ResNet50 サンプル。

 

カスタム訓練ループで tf.distribute.Strategy を使用する

貴方が見たように、高位 API で tf.distrbute.Strategy を使用するのは 2, 3 行のコード変更だけです。もう少しの努力で、tf.distrbute.Strategy はこれらのフレームワークを使用していない他のユーザによっても使用できます。

TensorFlow は様々な種類のユースケースのために使用されて (研究者のような) あるユーザは彼らの訓練ループに渡るより多くの柔軟性と制御を必要とします。これは彼らに Estimator や Keras のような高位フレームワークを使用することを困難にします。例えば、GAN を使用するある人は各ラウンドで異なる数の generator や discriminator ステップを取ることを望むかもしれません。同様に、高位フレームワークは強化学習訓練のためにはそれほど適してはいません。そのためこれらのユーザは通常は彼ら自身の訓練ループを書きます。

これらのユーザのために、tf.distrbute.Strategy クラスを通してメソッドのコアセットを提供します。これらの使用は初期化でコードの少量の再構成が必要かもしれませんが、ひとたびそれが成されれば、strategy インスタンスを単に変更することによりユーザは GPU / TPU / マルチマシンの間で切り替えることができるはずです。

ここで前と同じ Keras モデルを使用して単一の訓練サンプルのためのこのユースケースを表わす簡単なスニペットを示します。Note: これらの API は依然として実験的で TensorFlow 2.0 でそれらをよりユーザフレンドリーにするために改良しています。

最初に、strategy のスコープの内側でモデルと optimizer を作成します。これはこのモデルと optimizer で作成された任意の変数がミラーリングされる変数であることを確かなものにします。

with mirrored_strategy.scope():
  model = tf.keras.Sequential([tf.keras.layers.Dense(1, input_shape=(1,))])
  optimizer = tf.keras.optimizers.SGD()

次に、入力 dataset を作成して strategy に基づいて dataset を分散するために make_dataset_iterator を呼び出します。この API は近い将来に変更されることが予定されています。

with mirrored_strategy.scope():
  dataset = tf.data.Dataset.from_tensors(([1.], [1.])).repeat(1000).batch(
      global_batch_size)
  input_iterator = mirrored_strategy.make_dataset_iterator(dataset)

それから、訓練のワンステップを定義します。勾配を計算するために tf.GradientTape を使用してモデルの変数を更新するためにそれらの勾配を適用するために optimizer を使用します。この訓練ループを分散するために、関数 step_fn を中に入れてそれを前に作成された iterator と一緒に strategy.experimental_run に渡します :

@tf.function
def train_step():
  def step_fn(inputs):
    features, labels = inputs

    with tf.GradientTape() as tape:
      logits = model(features)
      cross_entropy = tf.nn.softmax_cross_entropy_with_logits(
          logits=logits, labels=labels)  
      loss = tf.reduce_sum(cross_entropy) * (1.0 / global_batch_size)

    grads = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(list(zip(grads, model.trainable_variables)))
    return loss

  per_replica_losses = mirrored_strategy.experimental_run(
      step_fn, input_iterator)
  mean_loss = mirrored_strategy.reduce(
      tf.distribute.ReduceOp.MEAN, per_replica_losses)
  return mean_loss

上のコードで注意すべき 2, 3 の他のこと: 1. 損失を計算するために tf.nn.softmax_cross_entropy_with_logits を使用しました。そしてそれからトータル損失をグローバル・バッチサイズでスケールしました。これは重要です、何故ならば総てのレプリカは同期して訓練して訓練の各ステップのサンプル数はグローバル・バッチだからです。もし tf.losses や tf.keras.losses から TensorFlow の標準損失を使用していれば、それらは分散 aware で strategy がスコープにあるときはいつでもレプリカ数によるスケーリングを処理します。2. experimental_run により返される結果を集計するために strategy.reduce API を使用しました。experimental_run は strategy の各ローカル・レプリカからの結果を返して、そしてこれらの結果を消費するための複数の方法があります。集計値を得るためにそれらを reduce できます。ローカル・レプリカ毎に一つ、結果に含まれる値のリストを得るために strategy.unwrap(results)* を行なうこともできます。

* 変更される予定です。

最後に、ひとたび訓練ステップを定義したならば、 iterator を初期化してループで訓練を実行できます :

with mirrored_strategy.scope():
  input_iterator.initialize()
  for _ in range(10):
    print(train_step())
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(0.0, shape=(), dtype=float32)

上の例では、入力を貴方の訓練に提供するために make_dataset_iterator を使用しました。私達はまた 2 つの追加の API を提供します : 他の種類の入力をサポートするための make_input_fn_iterator と make_experimental_numpy_iterator。tf.distribute.Strategy のそれらのドキュメントを見てくださいそしてそれらが make_dataset_iterator とどのように違うのかを。

これはカスタム訓練ループを分散するために tf.distribute.Strategy API を使用する最も単純なケースをカバーします。私達はこれらの API を改良する過程にあります。このユースケースはユーザ側のより多くのワークを必要としますので、将来的にこのユースケースのための個別の詳細なガイドを公開します。

 

今は何がサポートされますか?

TF 2.0 alpha リリースでは、上で示されたように MirroredStrategy を使用してカスタム訓練ループを持つ訓練をサポートします。他のストラテジーのサポートは間もなくです。カスタム訓練ループで TF 2.0 で TPUStrategy のような他のストラテジーを使用することを望むのであれば、現在 eager execution を無効にすることによりそれを行なうことができます (tf.compat.v1.disable_eager_execution())。コードは同様のままです、訓練を実行するために TF 1.x グラフとセッションを使用する必要があることを除いて。MultiWorkerMirorredStrategy サポートは将来的にもたらされます。

 

サンプルとチュートリアル

ここにカスタム訓練ループで分散ストラテジーを使用するためのサンプルがあります : 1. MirroredStrategy を使用して MNIST を訓練する チュートリアル。2. MirroredStrategy を使用する DenseNet サンプル。

 

他のトピック

このセクションでは、複数のユースケースに関連する幾つかのトピックをカバーします。

 

TF_CONFIG 環境変数をセットアップする

マルチワーカー訓練のためには、前に言及したように、貴方のクラスタの各バイナリ実行のために “TF_CONFIG” 環境変数を設定する必要があります。”TF_CONFIG” 環境変数は JSON 文字列でこれは何のタスクがクラスタを構成するか、それらのアドレスとクラスタの各タスクの役割りを指定します。tensorflow/ecosystem レポで Kubernetes テンプレートを提供します、これは貴方の訓練タスクのために “TF_CONFIG” を設定します。

“TF_CONFIG” の一つの例は :

os.environ["TF_CONFIG"] = json.dumps({
    "cluster": {
        "worker": ["host1:port", "host2:port", "host3:port"],
        "ps": ["host4:port", "host5:port"]
    },
   "task": {"type": "worker", "index": 1}
})

この “TF_CONFIG” はクラスタに 3 つのワーカーと 2 つの ps タスクがそれらのホストとポートと一緒にあることを指定しています。”task” パートはクラスタの現在のタスクの役割り, ワーカー 1 (2 番目のワーカー) を指定しています。クラスタの有効な役割りは “chief”, “worker”, “ps” と “evaluator” です。tf.distribute.experimental.ParameterServerStrategy を使用するとき以外は “ps” ジョブはないはずです。

 

以上



TensorFlowOnSpark (readme翻訳)

TensorFlowOnSpark (readme 翻訳)
翻訳 : (株)クラスキャット セールスインフォメーション
日時 : 02/14/2017

* 本ページは、github TensorFlowOnSpark の readme を翻訳したものです:
    https://github.com/yahoo/TensorFlowOnSpark/blob/master/README.md

 

TensorFlowOnSpark とは何か?

TensorFlowOnSpark はスケーラブルな深層学習を Apache Hadoop と Apache Spark にもたらしました。深層学習フレームワーク TensorFlow とビッグデータ・フレームワーク Apache Spark / Apache Hadoop 由来の顕著な特徴を結合することにより、TensorFlowOnSpark は GPU と CPU サーバ・クラスタ上の分散深層学習を可能にします。

TensorFlowOnSpark は Apache Spark クラスタ上の分散 TensorFlow トレーニングと推論を可能にします。それは共有グリッド上にある TensorFlow プログラムを実行するために必要なコード変更の総量を最小化するように努めます。その Spark 互換な API は TensorFlow クラスタを次のステップで管理することを手助けします :

  1. Reservation(予約) – 各 executor 上の TensorFlow プロセスのためのポートを予約し、また data/control メッセージのためのリスナーを開始します。
  2. Startup – executor 上で TensorFlow main 関数を launch します。
  3. データ摂取 (Data ingestion)
    • Readers & QueueRunners – TensorFlow の Reader 機構を HDFS から直接データファイルを読むために進化させます。
    • Feeding – Spark RDD データを feed_dict 機構を使用して TensorFlow ノードへ送ります。HDFS 上の TFRecords へのアクセスのために Hadoop Input/Output フォーマットを改良している (= leverage) ことに注意してください。
  4. Shutdown – TensorFlow workers と executors 上の PS ノードを停止します。

Infiniband ネットワーク上のリモート・ダイレクトメモリアクセス (RDMA, direct access to remote memory) をサポートするためにもまた TensorFlow を拡張しました。

TensorFlowOnSpark は Yahoo のプライベート・クラウドの Hadoop クラスタ上で大規模な分散深層学習のために Yahoo により開発されました。

 

何故 TensorFlowOnSpark か?

TensorFlowOnSpark は他の選択肢の深層学習ソリューションを超える幾つかの重要なメリット(ブログ 参照)を提供します。

  • <10 行のコード変更ですべての既存の TensorFlow プログラムを簡単に migrate します ;
  • すべての TensorFlow 機能をサポートします : 同期/非同期なトレーニング、モデル/データの並列処理、推論そして TensorBoard ;
  • サーバ to サーバのダイレクト・コミュニケーションが利用可能であれば、より高速な学習を達成します ;
  • HDFS 上と他のソース上のデータセットに Spark で push され TensorFlow で pull されることを可能にします ;
  • 貴方の既存のデータ処理パイプラインと機械学習アルゴリズム (ex. MLlib, CaffeOnSpark) を簡単に統合できます ;
  • クラウドでもオンプレでも簡単にデプロイされます: CPU & GPU, Ethernet そして Infiniband。
 

以上

Google Cloud Machine Learning : 入門編 (2) – 分散訓練 & ハイパーパラメータ調整

Google Cloud Machine Learning : 入門編 (2) – 分散訓練 & ハイパーパラメータ調整

Google Cloud ML 入門編 (1) の続編です。先の入門編 (1) では Google Cloud ML パブリック Beta のクライアント環境のセットアップと MNIST のシングル・ワーカー・ジョブの投入までを試しました。

本記事 – 入門編 (2) では Cloud ML の TensorFlow 分散訓練の方法から始めてハイパーパラメータ調整を行ないます。予備知識として TensorFlow : How To : 分散 TensorFlow に目を通しておくと良いでしょう。

* あくまでベータですので仕様が変更される可能性はありますのでご注意ください

(続) Training クイックスタート

クラウド上でトレーニングする : 分散

Training Quickstart の以下の項目から始めます :

Train on the cloud: distributed | Training Quickstart | Google Cloud Machine Learning

Cloud ML においてマルチワーカー上で TensorFlow モデルのトレーニング・ジョブを実行することはシングル・ワーカー上と殆ど同じくらい簡単です。先に利用した TensorFlow MNIST サンプルはシングル・ワーカー上でのトレーニングのみが可能ですが、TensorFlow : How To : 分散 TensorFlow でアドバイスされている方法によって分散トレーニングを可能にするため、アップデートします。

備考 : Cloud ML のオンライン & バッチ予測サービスをサポートするためにもまたサンプルをアップデートしています。これらについては( Prediction Quickstart のために)予測サービスに配備するモデルを保存することになります。

アップデートされたコードは以下で見つかります :

cd ~/google-cloud-ml/samples/mnist/distributed/

 

トレーニング・コードをローカルでテストする

最初に、モデルが(シングル・ワーカー上)ローカルでトレーニングできることを確認します :

# 以前のローカル実行からの出力をクリア
rm -rf output/
# ローカルでトレーニング
python -m trainer.task \
  --train_data_paths=gs://cloud-ml-data/mnist/train.tfr.gz \
  --eval_data_paths=gs://cloud-ml-data/mnist/eval.tfr.gz \
  --output_path=output

以下は実行結果の一部です(実際はかなり長いです) :

$ python -m trainer.task \
> --train_data_paths=gs://cloud-ml-data/mnist/train.tfr.gz \
> --eval_data_paths=gs://cloud-ml-data/mnist/eval.tfr.gz \
> --output_path=output
INFO:root:Original job data: {}
INFO:tensorflow:global_step/sec: 0
INFO:tensorflow:global_step/sec: 0
INFO:root:Train [master/0], step 1: loss: 2.312, accuracy: 0.040 (0.126 sec) 7.9 global steps/s, 7.9 local steps/s
INFO:root:Eval, step 1: loss: 2.298, accuracy: 0.094
INFO:root:Train [master/0], step 145: loss: 1.997, accuracy: 0.386 (3.407 sec) 43.9 global steps/s, 43.9 local steps/s
INFO:root:Eval, step 145: loss: 1.683, accuracy: 0.550
INFO:root:Adjusting eval interval from 1.00s to 1.39s
INFO:root:Train [master/0], step 288: loss: 1.697, accuracy: 0.528 (5.804 sec) 59.7 global steps/s, 59.7 local steps/s
INFO:root:Train [master/0], step 341: loss: 1.592, accuracy: 0.569 (6.189 sec) 137.6 global steps/s, 137.6 local steps/s
INFO:root:Eval, step 341: loss: 0.908, accuracy: 0.816
INFO:root:Train [master/0], step 482: loss: 1.362, accuracy: 0.642 (8.503 sec) 60.9 global steps/s, 60.9 local steps/s
INFO:root:Train [master/0], step 536: loss: 1.286, accuracy: 0.665 (8.889 sec) 140.1 global steps/s, 140.1 local steps/s
INFO:root:Eval, step 536: loss: 0.601, accuracy: 0.857

(... 略 ...)

INFO:root:Train [master/0], step 4908: loss: 0.428, accuracy: 0.882 (245.001 sec) 26.9 global steps/s, 26.9 local steps/s
INFO:root:Train [master/0], step 4934: loss: 0.427, accuracy: 0.882 (246.208 sec) 21.5 global steps/s, 21.5 local steps/s
INFO:root:Train [master/0], step 4944: loss: 0.427, accuracy: 0.883 (246.484 sec) 36.3 global steps/s, 36.3 local steps/s
INFO:root:Eval, step 4944: loss: 0.236, accuracy: 0.935
INFO:root:Train [master/0], step 4969: loss: 0.426, accuracy: 0.883 (253.471 sec) 3.6 global steps/s, 3.6 local steps/s
INFO:root:Train [master/0], step 4991: loss: 0.425, accuracy: 0.883 (254.472 sec) 22.0 global steps/s, 22.0 local steps/s
INFO:root:Exporting prediction graph to output/model
INFO:root:Final metrics after 5000 steps, loss: 0.236, accuracy: 0.934

 

トレーニング・ジョブを submit する

トレーニング・ジョブのための名前を選択します、e.g. “mnist_distributed_yourusername”。
英字で始まり英数字とアンダースコアのみを含めることができます。

JOB_NAME=<your job name>

以前のクラウド実行からの出力をクリアしておきます :

PROJECT_ID=`gcloud config list project --format "value(core.project)"`
TRAIN_BUCKET=gs://${PROJECT_ID}-ml
TRAIN_PATH=${TRAIN_BUCKET}/${JOB_NAME}
gsutil rm -rf ${TRAIN_PATH}

単純な config ファイルを作成します、これは Cloud ML STANDARD_1 scale tier(= 多くのワーカーと2、3 (= a few) のパラメータ・サーバ)を指定するものです :

cat << EOF > config.yaml
trainingInput:
  # Use a cluster with many workers and a few parameter servers.
  scaleTier: STANDARD_1
EOF

そして最後にトレーニング・ジョブを submit します :

gcloud beta ml jobs submit training ${JOB_NAME} \
  --package-path=trainer \
  --module-name=trainer.task \
  --staging-bucket="${TRAIN_BUCKET}" \
  --region=us-central1 \
  --config=config.yaml \
  -- \
  --train_data_paths="gs://cloud-ml-data/mnist/train.tfr.gz" \
  --eval_data_paths="gs://cloud-ml-data/mnist/eval.tfr.gz" \
  --output_path="${TRAIN_PATH}/output"

実際に実行してみます :

$ gcloud beta ml jobs submit training ${JOB_NAME} \
>   --package-path=trainer \
>   --module-name=trainer.task \
>   --staging-bucket="${TRAIN_BUCKET}" \
>   --region=us-central1 \
>   --config=config.yaml \
>   -- \
>   --train_data_paths="gs://cloud-ml-data/mnist/train.tfr.gz" \
>   --eval_data_paths="gs://cloud-ml-data/mnist/eval.tfr.gz" \
>   --output_path="${TRAIN_PATH}/output"
createTime: '2016-10-17T09:05:49Z'
jobId: mnist_distributed_classcat
state: QUEUED
trainingInput:
  args:
  - --train_data_paths=gs://cloud-ml-data/mnist/train.tfr.gz
  - --eval_data_paths=gs://cloud-ml-data/mnist/eval.tfr.gz
  - --output_path=gs://classcat-tensorflow-ml/mnist_distributed_classcat/output
  packageUris:
  - gs://classcat-tensorflow-ml/cloudmldist/1476695147/trainer-0.0.0.tar.gz
  pythonModule: trainer.task
  region: us-central1
  scaleTier: STANDARD_1

ステータス確認。もちろん Cloud Platform コンソールからも確認できます :

$ gcloud beta ml jobs describe --project ${PROJECT_ID} ${JOB_NAME}
createTime: '2016-10-17T09:05:49Z'
jobId: mnist_distributed_classcat
startTime: '2016-10-17T09:06:25Z'
state: RUNNING
trainingInput:
  args:
  - --train_data_paths=gs://cloud-ml-data/mnist/train.tfr.gz
  - --eval_data_paths=gs://cloud-ml-data/mnist/eval.tfr.gz
  - --output_path=gs://classcat-tensorflow-ml/mnist_distributed_classcat/output
  packageUris:
  - gs://classcat-tensorflow-ml/cloudmldist/1476695147/trainer-0.0.0.tar.gz
  pythonModule: trainer.task
  region: us-central1
  scaleTier: STANDARD_1

成功しました :

$ gcloud beta ml jobs describe --project ${PROJECT_ID} ${JOB_NAME}
createTime: '2016-10-17T09:05:49Z'
endTime: '2016-10-17T09:13:17Z'
jobId: mnist_distributed_classcat
startTime: '2016-10-17T09:06:25Z'
state: SUCCEEDED
trainingInput:
  args:
  - --train_data_paths=gs://cloud-ml-data/mnist/train.tfr.gz
  - --eval_data_paths=gs://cloud-ml-data/mnist/eval.tfr.gz
  - --output_path=gs://classcat-tensorflow-ml/mnist_distributed_classcat/output
  packageUris:
  - gs://classcat-tensorflow-ml/cloudmldist/1476695147/trainer-0.0.0.tar.gz
  pythonModule: trainer.task
  region: us-central1
  scaleTier: STANDARD_1

 

出力を inspect する

この例では出力は ${TRAIN_PATH}/output に保存されていますので、リストを取るには ”
gsutil ls ${TRAIN_PATH}/output” を実行します :

$ gsutil ls $TRAIN_PATH/output
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/checkpoint
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695558.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695559.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695560.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695562.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695564.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695566.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695568.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695571.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695573.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695575.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695578.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695580.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695583.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/events.out.tfevents.1476695585.master-63d9-0-ytvx3
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/export
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/export.meta
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/graph.pbtxt
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/model.ckpt-2496
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/model.ckpt-2496.meta
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/model.ckpt-3117
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/model.ckpt-3117.meta
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/model.ckpt-4018
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/model.ckpt-4018.meta
gs://classcat-tensorflow-ml/mnist_distributed_classcat/output/model.ckpt-5006

 

Stackdriver ログを inspect する

マルチ・ワーカー上でモデルがトレーニングされたことを確認するために Stackdriver ロギングが使用できます。

ジョブのログを見つける最も簡単な方法は(シングル・ワーカー上の場合と同じように)Cloud Platform コンソールで「ログを表示」をクリックすることです。「すべてのログ」ドロップダウンの中から master-replica-0 をクリックすると、以下のようなログが閲覧できます :
gcml_distributed_log_master0b

次に master-replicat-0 の代わりに worker-replica-0 を選択すると、次のようなログが閲覧できます :
gcml_distributed_log_worker0b

alternative として、コマンドライン上でもログを読むことができます :

gcloud beta logging read --project ${PROJECT_ID} --format=json \
  "labels.\"ml.googleapis.com/task_name\"=\"master-replica-0\" AND \
   labels.\"ml.googleapis.com/job_id\"=\"${JOB_NAME}\""

以下は実行例です :

$ gcloud beta logging read --project ${PROJECT_ID} --format=json   "labels.\"ml.googleapis
.com/task_name\"=\"master-replica-0\" AND \
   labels.\"ml.googleapis.com/job_id\"=\"${JOB_NAME}\"" | head -40
[
  {
    "insertId": "15cxtb6f1ae12i",
    "jsonPayload": {
      "created": 1476695587.16638,
      "levelname": "INFO",
      "lineno": 690,
      "message": "Task completed successfully.",
      "pathname": "/runcloudml.py"
    },
    "labels": {
      "compute.googleapis.com/resource_id": "6857495858232852682",
      "compute.googleapis.com/resource_name": "master-63d9-0-ytvx3",
      "compute.googleapis.com/resource_type": "instance",
      "ml.googleapis.com/job_id": "mnist_distributed_classcat",
      "ml.googleapis.com/job_id/log_area": "root",
      "ml.googleapis.com/task_name": "master-replica-0",
      "ml.googleapis.com/trial_id": ""
    },
    "logName": "projects/classcat-tensorflow/logs/master-replica-0",
    "resource": {
      "labels": {
        "job_id": "mnist_distributed_classcat",
        "task_name": "master-replica-0"
      },
      "type": "ml_job"
    },
    "severity": "INFO",
    "timestamp": "2016-10-17T09:13:07.166379928Z"
  },
  {
    "insertId": "15cxtb6f1ae12h",
    "jsonPayload": {
      "created": 1476695587.16607,
      "levelname": "INFO",
      "lineno": 688,
      "message": "Clean up finished.",
      "pathname": "/runcloudml.py"
    },
    "labels": {

 

要約ログを inspect する

この例のために TensorBoard を実行するには、”–logdir=${TRAIN_PATH}/output” を指定すれば良いです :

$ echo ${TRAIN_PATH}
gs://classcat-tensorflow-ml/mnist_distributed_classcat
$ tensorboard --logdir=${TRAIN_PATH}/output --port 8080

以下は損失グラフ :
gcml_distributed_tb_loss2

そして精度グラフです :
gcml_distributed_tb_accu2

 

クラウド上でトレーニングする : ハイパーパラメータ調整

最後に、(この場合は)以下のより良い値を自動的に見つけることによりモデル精度をあげるためにハイパーパラメータ調整を利用できます :

  • 2つの隠れ層のサイズ
  • 学習率

ハイパーパラメータ調整を有効にするためには、前のセクションで使用したサンプルコードに小さな変更を行なう必要があります。興味があれば、これらの変更は Increasing Model Accuracy with Hyperparameter Tuning how-to に記述されていますが、このクイックスタートのためには既に変更を行なっています; 単に作業ディレクトリを ~/google-cloud-ml/samples/mnist/hptuning/ に移してください :

cd ~/google-cloud-ml/samples/mnist/hptuning/

 

トレーニング・コードをローカルでテストする

最初に、モデルを(ハイパーパラメータ調整なし、シングルワーカー上の)ローカルでトレーニング可能なことを確認します :

# Clear the output from any previous local run.
rm -rf output/
# Train locally.
python -m trainer.task \
  --train_data_paths=gs://cloud-ml-data/mnist/train.tfr.gz \
  --eval_data_paths=gs://cloud-ml-data/mnist/eval.tfr.gz \
  --output_path=output

上記の分散トレーニングのためのローカル実行からの出力と同様の出力を見るはずです。
実際の出力は以下のような感じです :

INFO:root:Original job data: {}
INFO:tensorflow:global_step/sec: 0
INFO:tensorflow:global_step/sec: 0
INFO:root:Train [master/0], step 1: loss: 2.322, accuracy: 0.100 (0.117 sec) 8.5 global steps/s, 8.5 local steps/s
INFO:root:Eval, step 1: loss: 2.312, accuracy: 0.108
INFO:root:Train [master/0], step 1352: loss: 0.973, accuracy: 0.742 (12.467 sec) 109.4 global steps/s, 109.4 local steps/s
INFO:root:Eval, step 1352: loss: 0.593, accuracy: 0.846
INFO:root:Train [master/0], step 2626: loss: 0.775, accuracy: 0.801 (24.021 sec) 110.3 global steps/s, 110.3 local steps/s
INFO:root:Eval, step 2626: loss: 0.512, accuracy: 0.887
INFO:root:Train [master/0], step 3914: loss: 0.687, accuracy: 0.830 (35.433 sec) 112.9 global steps/s, 112.9 local steps/s
INFO:root:Eval, step 3914: loss: 0.479, accuracy: 0.899
INFO:root:Exporting prediction graph to output/model
INFO:root:Final metrics after 5000 steps, loss: 0.455, accuracy: 0.908

 

トレーニング・ジョブを submit する

トレーニング・ジョブのための名前を選択します、e.g. “mnist_hptuning_yourusername”。
英字から始まり英数字とアンダースコアを含みます。

JOB_NAME=<your job name>

以前のクラウド実行からの出力をクリアしておきます :

PROJECT_ID=`gcloud config list project --format "value(core.project)"`
TRAIN_BUCKET=gs://${PROJECT_ID}-ml  # gs://ccml-beta-ml
TRAIN_PATH=${TRAIN_BUCKET}/${JOB_NAME}  # gs://ccml-beta-ml/mnist_hptunint_classcat
gsutil rm -rf ${TRAIN_PATH}

最適化したい ハイパーパラメータscale tier を指定する config ファイルを作成します :

cat << EOF > config.yaml
trainingInput:
  # Use a cluster with many workers and a few parameter servers.
  scaleTier: STANDARD_1
  # Hyperparameter-tuning specification.
  hyperparameters:
    # Maximize the objective value.
    goal: MAXIMIZE
    # Run at most 10 trials with different hyperparameters.
    maxTrials: 10
    # Run two trials at a time.
    maxParallelTrials: 2
    params:
      # Allow the size of the first hidden layer to vary between 40 and 400.
      # One value in this range will be passed to each trial via the
      # --hidden1 command-line flag.
      - parameterName: hidden1
        type: INTEGER
        minValue: 40
        maxValue: 400
        scaleType: UNIT_LINEAR_SCALE
      # Allow the size of the second hidden layer to vary between 5 and 250.
      # One value in this range will be passed to each trial via the
      # --hidden2 command-line flag.
      - parameterName: hidden2
        type: INTEGER
        minValue: 5
        maxValue: 250
        scaleType: UNIT_LINEAR_SCALE
      # Allow the learning rate to vary between 0.0001 and 0.5.
      # One value in this range will be passed to each trial via the
      # --learning_rate command-line flag.
      - parameterName: learning_rate
        type: DOUBLE
        minValue: 0.0001
        maxValue: 0.5
        scaleType: UNIT_LOG_SCALE
EOF

最後に、トレーニング・ジョブを submit します :

gcloud beta ml jobs submit training ${JOB_NAME} \
  --package-path=trainer \
  --module-name=trainer.task \
  --staging-bucket="${TRAIN_BUCKET}" \
  --region=us-central1 \
  --config=config.yaml \
  -- \
  --train_data_paths="gs://cloud-ml-data/mnist/train.tfr.gz" \
  --eval_data_paths="gs://cloud-ml-data/mnist/eval.tfr.gz" \
  --output_path="${TRAIN_PATH}/output"

このコマンドは、ハイパーパラメータ調整の指定を追加した点を除けば、上述の分散トレーニングのために使ったものと同じです。

実行直後です :

createTime: '2016-10-22T14:03:36Z'
jobId: mnist_hptunint_classcat
state: QUEUED
trainingInput:
  args:
  - --train_data_paths=gs://cloud-ml-data/mnist/train.tfr.gz
  - --eval_data_paths=gs://cloud-ml-data/mnist/eval.tfr.gz
  - --output_path=gs://ccml-beta-ml/mnist_hptunint_classcat/output
  hyperparameters:
    goal: MAXIMIZE
    maxParallelTrials: 2
    maxTrials: 10
    params:
    - maxValue: 400.0
      minValue: 40.0
      parameterName: hidden1
      scaleType: UNIT_LINEAR_SCALE
      type: INTEGER
    - maxValue: 250.0
      minValue: 5.0
      parameterName: hidden2
      scaleType: UNIT_LINEAR_SCALE
      type: INTEGER
    - maxValue: 0.5
      minValue: 0.0001
      parameterName: learning_rate
      scaleType: UNIT_LOG_SCALE
      type: DOUBLE
  packageUris:
  - gs://ccml-beta-ml/cloudmldist/1477145014/trainer-0.0.0.tar.gz
  pythonModule: trainer.task
  region: us-central1
  scaleTier: STANDARD_1

 

トレーニング・ジョブの終了を待つ

ジョブの進行をチェックして終了することを待ちます :

gcloud beta ml jobs describe --project ${PROJECT_ID} ${JOB_NAME}

ジョブが完了すればステート SUCCEEDED が確認できます。
ドキュメントにはおよそ 20 分かかるとありましたが、実際のジョブ実行時間は 27 分かかりました。以下は成功後の出力です :

$ gcloud beta ml jobs describe --project ${PROJECT_ID} ${JOB_NAME}
createTime: '2016-10-22T14:03:36Z'
endTime: '2016-10-22T14:30:40Z'
jobId: mnist_hptunint_classcat
startTime: '2016-10-22T14:03:38Z'
state: SUCCEEDED
trainingInput:
  args:
  - --train_data_paths=gs://cloud-ml-data/mnist/train.tfr.gz
  - --eval_data_paths=gs://cloud-ml-data/mnist/eval.tfr.gz
  - --output_path=gs://ccml-beta-ml/mnist_hptunint_classcat/output
  hyperparameters:
    goal: MAXIMIZE
    maxParallelTrials: 2
    maxTrials: 10
    params:
    - maxValue: 400.0
      minValue: 40.0
      parameterName: hidden1
      scaleType: UNIT_LINEAR_SCALE
      type: INTEGER
    - maxValue: 250.0
      minValue: 5.0
      parameterName: hidden2
      scaleType: UNIT_LINEAR_SCALE
      type: INTEGER
    - maxValue: 0.5
      minValue: 0.0001
      parameterName: learning_rate
      scaleType: UNIT_LOG_SCALE
      type: DOUBLE
  packageUris:
  - gs://ccml-beta-ml/cloudmldist/1477145014/trainer-0.0.0.tar.gz
  pythonModule: trainer.task
  region: us-central1
  scaleTier: STANDARD_1
trainingOutput:
  completedTrialCount: '10'
  trials:
  - finalMetric:
      objectiveValue: 1.0
      trainingStep: '801'
    hyperparameters:
      hidden1: '400'
      hidden2: '243'
      learning_rate: '0.35743598509131963'
    trialId: '2'
  - finalMetric:
      objectiveValue: 1.0
      trainingStep: '155'
    hyperparameters:
      hidden1: '400'
      hidden2: '78'
      learning_rate: '0.46075871302559684'
    trialId: '4'
  - finalMetric:
      objectiveValue: 1.0
      trainingStep: '59'
    hyperparameters:
      hidden1: '318'
      hidden2: '156'
      learning_rate: '0.49635208597915981'
    trialId: '7'
  - finalMetric:
      objectiveValue: 1.0
      trainingStep: '77'
    hyperparameters:
      hidden1: '400'
      hidden2: '171'
      learning_rate: '0.40330855230836954'
    trialId: '9'
  - finalMetric:
      objectiveValue: 0.9635
      trainingStep: '57'
    hyperparameters:
      hidden1: '202'
      hidden2: '250'
      learning_rate: '0.062366331313038155'
    trialId: '10'
  - finalMetric:
      objectiveValue: 0.9632
      trainingStep: '53'
    hyperparameters:
      hidden1: '400'
      hidden2: '199'
      learning_rate: '0.028588163150300036'
    trialId: '5'
  - finalMetric:
      objectiveValue: 0.9573
      trainingStep: '65'
    hyperparameters:
      hidden1: '169'
      hidden2: '24'
      learning_rate: '0.47690789477002721'
    trialId: '8'
  - finalMetric:
      objectiveValue: 0.9515
      trainingStep: '47'
    hyperparameters:
      hidden1: '68'
      hidden2: '175'
      learning_rate: '0.49684846231717211'
    trialId: '6'
  - finalMetric:
      objectiveValue: 0.7194
      trainingStep: '687'
    hyperparameters:
      hidden1: '134'
      hidden2: '87'
      learning_rate: '0.000949340820855901'
    trialId: '1'
  - finalMetric:
      objectiveValue: 0.3354
      trainingStep: '254'
    hyperparameters:
      hidden1: '399'
      hidden2: '19'
      learning_rate: '0.00010892698020942698'
    trialId: '3'

この出力は 10 試行の各々に使用されたハイパーパラメータと、目的値 (= objective value) (この場合は精度)を含みます。目的値によりソートされています。

 

出力を inspect する

このサンプルでは、出力は ${TRAIN_PATH}/output に保存されます :

gsutil ls ${TRAIN_PATH}/output

各試行のための 10 個の出力ディレクトリが見てとれます :

$ gsutil ls ${TRAIN_PATH}/output/
gs://ccml-beta-ml/mnist_hptunint_classcat/output/1/
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/
gs://ccml-beta-ml/mnist_hptunint_classcat/output/2/
gs://ccml-beta-ml/mnist_hptunint_classcat/output/3/
gs://ccml-beta-ml/mnist_hptunint_classcat/output/4/
gs://ccml-beta-ml/mnist_hptunint_classcat/output/5/
gs://ccml-beta-ml/mnist_hptunint_classcat/output/6/
gs://ccml-beta-ml/mnist_hptunint_classcat/output/7/
gs://ccml-beta-ml/mnist_hptunint_classcat/output/8/
gs://ccml-beta-ml/mnist_hptunint_classcat/output/9/

$ gsutil ls ${TRAIN_PATH}/output/10
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/checkpoint
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/events.out.tfevents.1477146511.master-f3ea-0-5rb4e
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/events.out.tfevents.1477146512.master-f3ea-0-5rb4e
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/events.out.tfevents.1477146523.master-f3ea-0-5rb4e
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/events.out.tfevents.1477146524.master-f3ea-0-5rb4e
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/events.out.tfevents.1477146534.master-f3ea-0-5rb4e
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/events.out.tfevents.1477146535.master-f3ea-0-5rb4e
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/export
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/export.meta
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/graph.pbtxt
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/model.ckpt-1
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/model.ckpt-1.meta
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/model.ckpt-1771
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/model.ckpt-1771.meta
gs://ccml-beta-ml/mnist_hptunint_classcat/output/10/model.ckpt-5007

 

要約ログを inspect する

例えば –logdir=${TRAIN_PATH}/output/1 で TensorBoard が利用できます。
以下はまとめて閲覧したところです :

gcml_hyperparameter_tuning0

gcml_hyperparameter_tuning0b

以下は結果の良かった Id 2 のグラフです :

gcml_hyperparameter_tuning2b

 

ここまでで Training クイックスタートを通して動作確認したことになります。

 

以上

TensorFlow GPU クラスタによる分散型の深層学習サービスを2016年5月から AWS EC2 で提供開始

cc_logo_square

Press Release
2016年04月20日
TensorFlow GPU クラスタによる分散型の深層学習サービスを
2016年5月から AWS EC2 で提供開始
ー 「ClassCat® Distributed Deep Learning Service」 ー

 

株式会社クラスキャット(本社:東京都港区赤坂、代表取締役社長:佐々木規行)は、TensorFlow GPU クラスタによる分散型の深層学習サービス「ClassCat® Distributed Deep Learning Service」を AWS (Amazon Web Service) 上で2016年05月から提供開始することを発表致しました。TensorFlow は米 Google 社によりオープンソース化された深層学習フレームワークです。
本サービスでは日本語ドキュメントが提供され、オプションでコンサルティング・サービスの利用も可能となっています。

深層学習は機械学習の一分野で多層構造な深層ニューラルネットワーク (DNN = Deep Neural Network) における最新の学習手法です。深層学習は分類問題をはじめ、機械学習全般の問題に役立つとされていますが、主として画像認識や音声認識などで強力なパターン認識力を持つことが実証され、大きな注目を浴びています。本サービス「ClassCat® Distributed Deep Learning Service」では深層学習に特化したフレームワーク TensorFlow を GPU クラスタ構成で高速化を図ったマネージドサービスとして提供します。

TensorFlow は米 Google 社によりオープンソース化された深層学習フレームワークです。TensorFlow は多くの優れた特徴を持ちます。例えばデータフローグラフとして表現できさえすれば(ニューラルネットワーク以外でも)処理できる柔軟性があり、同じコードで CPU でも GPU でも動作し、トレーニングされたモデルのモバイルシステムへの配備も可能なポータビリティがあります。また学術的な研究と実製品でコードも共有されています。その他にも自動微分の機能や動作環境の最大限の活用を可能にする機能も持ちます。そして TensorFlow 最新版 0.8.0 では分散コンピューティングがサポートされました。

新サービス「ClassCat® Distributed Deep Learning Service」ではこの TensorFlow 0.8.0 を利用して Amazon EC2 の G2 インスタンスで GPU クラスタを構成し、分散コンピューティングによる深層学習を実現しています。各インスタンスは Ubuntu 14.04 LTS をベースに GPU 対応ドライバ及びアクセラレータがインストール済みです。

また、各種チュートリアルを含む、充実した日本語ドキュメントが提供されますが、導入に当たってはコンサルティング・サービスの利用も可能です。


【販売概要】

製品名  : ClassCat® Distributed Deep Learning Service
販売時期 : 2016年5月
販売形態 : 直接販売・販売パートナー経由・OEM
販売価格 : オープンプライス

【動作環境】

製品名  : ClassCat® Distributed Deep Learning Service
OS    : Ubuntu Server 14.04 LTS
ハードウェア : IaaS パブリッククラウド上でサービス提供致します。
※ GPU が利用可能な仮想サーバが必須です。

お問合せ
本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット
〒107-0052 東京都港区赤坂 7-5-6
セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com
WebSite: http://www.classcat.com/

※ ClassCat は株式会社クラスキャットの登録商標です。
※ TensorFlow, the TensorFlow logo and any related marks are trademarks of Google Inc.
※ AWS は米国その他の諸国における Amazon.com, Inc. またはその関連会社の商標です。
※ その他、記載されている会社名・製品名は各社の登録商標または商標です。

TensorFlow : Deploy : 分散 TensorFlow

TensorFlow : Deploy : 分散 TensorFlow(翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
更新日時 : 09/16/2017
作成日時 : 04/16/2016

* 本ページは、TensorFlow 本家サイトの Deploy : Distributed TensorFlow を翻訳した上で
適宜、補足説明したものです:

* (obsolete) 本ページは、TensorFlow 本家サイトの以下のページを翻訳した上で適宜、補足説明したものです:
    https://www.tensorflow.org/versions/r0.8/how_tos/distributed/index.html
* サンプルコードの動作確認はしておりますが、適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 
本文

この文書は TensorFlow サーバのクラスタをどのように作成し、そのクラスタに渡って計算グラフをどのように分散するかを示します。TensorFlow プログラムを書く 基本コンセプト に慣れていることを想定しています。

 

Hello 分散 (distributed) TensorFlow!

このチュートリアルではあなたが TensorFlow nightly build を使用していることを想定しています。ローカル・サーバを次のように開始して使用することであなたのインストールをテストすることができます :

# TensorFlow サーバを単一プロセス「クラスタ」として開始します。
$ python
>>> import tensorflow as tf
>>> c = tf.constant("Hello, 分散 TensorFlow!")
>>> server = tf.train.Server.create_local_server()
>>> sess = tf.Session(server.target)  # サーバ上でセッションを作成します。
>>> sess.run(c)
'Hello, 分散 TensorFlow!'

tf.train.Server.create_local_server() (訳注: リンク切れ) メソッドは、in-process サーバで、単一プロセス・クラスタを作成します。

 

クラスタを作成する

TensorFlow「クラスタ」は、TensorFlow グラフの分散実行に参加する「タスク」の集合です。各タスクは TensorFlow「サーバ」と関係し、これはセッションを作成するために使用可能な「マスター」、そしてグラフにおける演算を実行する「ワーカー」を含みます。クラスタは一つまたはそれ以上の「ジョブ」にも分割されます、そこでは各ジョブは一つまたはそれ以上のタスクを含みます。

クラスタを作成するためには、クラスタ内でタスク毎に TensorFlow サーバ一つを開始します。各タスクは典型的には異なるマシン上実行されますが、同じマシンで複数のタスクを実行することもできます(e.g. 異なる GPU デバイスを制御するため等)。各タスクでは、次を行ないます :

  • tf.train.ClusterSpec を作成します、これはクラスタの全てのタスクを記述します。これは各タスクで同じであるべきです。
  • tf.train.Server を作成します、コンストラクタには tf.train.ClusterSpec を渡して、ジョブ名とタスク・インデックスでローカル・タスクを識別します。

クラスタを記述するために tf.train.ClusterSpec を作成する

tf.train.ClusterSpec コンストラクション

利用可能なタスク
tf.train.ClusterSpec({“local”: [“localhost:2222”, “localhost:2223”]})
/job:local/task:0
/job:local/task:1
tf.train.ClusterSpec({
    "worker": [
        "worker0.example.com:2222", 
        "worker1.example.com:2222",
        "worker2.example.com:2222"
    ],
    "ps": [
        "ps0.example.com:2222",
        "ps1.example.com:2222"
    ]})
/job:worker/task:0
/job:worker/task:1
/job:worker/task:2
/job:ps/task:0
/job:ps/task:1

各タスクで tf.train.Server インスタンスを作成する

tf.train.Server オブジェクトはローカル・デバイスの集合、tf.train.ClusterSpec における他のタスクへの接続 (connections) の集合、そして分散計算を遂行するためにこれらを使用できる「セッション・ターゲット」を含みます。各サーバは特定の名前のジョブのメンバーで、そのジョブ内のタスクインデックスを持ちます。サーバはクラスタにおける任意の他のサーバと通信可能です

例えば、 localhost:2222 と localhost:2223 上で動作する2つのサーバによるクラスタを起動するためには、ローカルマシン上で次のスニペットを2つの異なるプロセスで実行します :

# In task 0:
cluster = tf.train.ClusterSpec({"local": ["localhost:2222", "localhost:2223"]})
server = tf.train.Server(cluster, job_name="local", task_index=0)

# In task 1:
cluster = tf.train.ClusterSpec({"local": ["localhost:2222", "localhost:2223"]})
server = tf.train.Server(cluster, job_name="local", task_index=1)

[Note] これらのクラスタ仕様を手動で指定するのは長く退屈なものです、特に大規模クラスタに対しては。私たちはプログラミング的にタスクを起動するためのツールについてワークしています、e.g. Kubernetes のようなクラスタ・マネージャを使用します。サポートを望む特定のクラスタ・マネージャがある場合には、GitHub issue をあげてください。

 

モデルで分散デバイスを指定する

特定のプロセスに演算を配置するためには、ops を CPU か GPU で実行するかを指定するのに使用されるのと同じ tf.device() 関数をが使用できます。例えば :

with tf.device("/job:ps/task:0"):
  weights_1 = tf.Variable(...)
  biases_1 = tf.Variable(...)

with tf.device("/job:ps/task:1"):
  weights_2 = tf.Variable(...)
  biases_2 = tf.Variable(...)

with tf.device("/job:worker/task:7"):
  input, labels = ...
  layer_1 = tf.nn.relu(tf.matmul(input, weights_1) + biases_1)
  logits = tf.nn.relu(tf.matmul(layer_1, weights_2) + biases_2)
  # ...
  train_op = ...

with tf.Session("grpc://worker7.example.com:2222") as sess:
  for _ in range(10000):
    sess.run(train_op)

上の例では、変数は ps ジョブの2つのタスク上に作成され、そしてモデルの数値計算部はワーカー・ジョブで作成されます。TensorFlow はジョブ間に適当なデータ転送を挿入します(forward pass のためには ps からワーカーに、そして勾配の適用のためにはワーカーから ps に)。

 

レプリケーションされた (Replicated) 訓練

「データ並列性 (data parallelism)」と呼ばれる、一般的な訓練構成 (configuration) は同じモデルをデータ上の異なるミニ・バッチで訓練する、ワーカー・ジョブの複数のタスクを含み、ps ジョブにおける一つまたは複数のタスクにホストされる共有パラメータを更新します。全てのタスクは典型的には異なるマシン上で実行されます。TensorFlow でこの構造を指定するには多くの方法あり、レプリケーション・モデル (replicated model) を指定するワークを単純にするライブラリを構築しています。可能なアプローチは次のようなものです :

  • グラフ内 (In-graph) レプリケーション。このアプローチでは、クライアントは、(/job:ps に固定された tf.Variable ノードの) パラメータのワンセットを含む 単一の tf.Graph を構築します; そしてモデルの数値計算部の複数のコピーは、それぞれ /job:worker の異なるタスクに固定されます。
  • グラフ間 (Between-graph) レプリケーション。このアプローチでは、各 /job:worker タスクに対して分離したクライアントがあり、典型的にはワーカータスクとしての同じプロセス内にあります。各クライアントはパラメータを含む同様のグラフを構築します。(パラメータは同じように /job:ps に固定されてそれらを同じタスクに決定論的にマップするために tf.train.replica_device_setter() (訳注: リンク切れ) を使用します); そしてモデルの数値計算部の一つのコピーは、/job:worker のローカルタスクに固定されます。
  • 非同期 (Asynchronous) 訓練。このアプローチでは、グラフの各レプリカは、連携なし (w/o coordination) に実行される独立的な訓練ループを持ちます。上のリプリケーション形式の両者と互換性があります。
  • 同期 (Synchronous) 訓練。このアプローチでは、全てのレプリカは 現在のパラメータについて同じ値を読み、並列に勾配を計算し、そしてそれらを一緒に適用します。これは in-graph リプリケーションと互換で(e.g. CIFAR-10 マルチ-GPU トレーナー 内のように勾配平均を使用)、そして between-graph レプリケーションと互換です(e.g. tf.train.SyncReplicasOptimizer を使用)。

まとめ: サンプル・トレーナー・プログラム

次のコードは分散トレーナー・プログラムのスケルトンを示し、between-graph リプリケーションと非同期訓練を実装しています。これはパラメータ・サーバとワーカー・タスクのためのコードを含みます。

import tensorflow as tf

# tf.train.ClusterSpec を定義するためのフラグ
tf.app.flags.DEFINE_string("ps_hosts", "",
                           "Comma-separated list of hostname:port pairs")
tf.app.flags.DEFINE_string("worker_hosts", "",
                           "Comma-separated list of hostname:port pairs")

# tf.train.Server を定義するためのフラグ
tf.app.flags.DEFINE_string("job_name", "", "One of 'ps', 'worker'")
tf.app.flags.DEFINE_integer("task_index", 0, "Index of task within the job")

FLAGS = tf.app.flags.FLAGS


def main(_):
  ps_hosts = FLAGS.ps_hosts.split(",")
  worker_hosts = FLAGS.worker_hosts(",")

  # パラメータ・サーバとワーカー・ホストからクラスタを作成します。
  cluster = tf.train.ClusterSpec({"ps": ps_hosts, "worker": worker_hosts})
  
  # ローカル・タスクのためのサーバを作成して開始します。
  server = tf.train.Server(cluster,
                           job_name=FLAGS.job_name,
                           task_index=FLAGS.task_index)

  if FLAGS.job_name == "ps":
    server.join()
  elif FLAGS.job_name == "worker":

    # デフォルトで ops をローカル・ワーカーに割り当てます。
    with tf.device(tf.train.replica_device_setter(
        worker_device="/job:worker/task:%d" % FLAGS.task_index,
        cluster=cluster)):

      # モデルを構築します...
      loss = ...
      global_step = tf.Variable(0)

      train_op = tf.train.AdagradOptimizer(0.01).minimize(
          loss, global_step=global_step)

      saver = tf.train.Saver()
      summary_op = tf.merge_all_summaries()
      init_op = tf.initialize_all_variables()

    # 「スーパーバイザ」を作成します、これは訓練プロセスを監視します。
    sv = tf.train.Supervisor(is_chief=(FLAGS.task_index == 0),
                             logdir="/tmp/train_logs",
                             init_op=init_op,
                             summary_op=summary_op,
                             saver=saver,
                             global_step=global_step,
                             save_model_secs=600)

    # スーパーバイザはセッション初期化をケアしてチェックポイントから復旧します。
    sess = sv.prepare_or_wait_for_session(server.target)

    # 入力パイプラインに対してキュー・ランナーを開始します(もしあれば)。
    sv.start_queue_runners(sess)

    # スーパーバイザがシャットダウンするまでロープします(あるいは 1000000 ステップが完了するまで)。
    step = 0
    while not sv.should_stop() and step < 1000000:
      # 訓練ステップを非同期に実行します。
      # *同期* 訓練をどのように遂行するかについての追加の詳細情報は `tf.train.SyncReplicasOptimizer` を参照。
      _, step = sess.run([train_op, global_step])


if __name__ == "__main__":
  tf.app.run()

2つのパラメータ・サーバと2つのワーカーでトレーナーを開始するには、次のコマンドラインを使用します(スクリプトは trainer.py とします) :

# On ps0.example.com:
$ python trainer.py \
     --ps_hosts=ps0.example.com:2222,ps1.example.com:2222 \
     --worker_hosts=worker0.example.com:2222,worker1.example.com:2222 \
     --job_name=ps --task_index=0
# On ps1.example.com:
$ python trainer.py \
     --ps_hosts=ps0.example.com:2222,ps1.example.com:2222 \
     --worker_hosts=worker0.example.com:2222,worker1.example.com:2222 \
     --job_name=ps --task_index=1
# On worker0.example.com:
$ python trainer.py \
     --ps_hosts=ps0.example.com:2222,ps1.example.com:2222 \
     --worker_hosts=worker0.example.com:2222,worker1.example.com:2222 \
     --job_name=worker --task_index=0
# On worker1.example.com:
$ python trainer.py \
     --ps_hosts=ps0.example.com:2222,ps1.example.com:2222 \
     --worker_hosts=worker0.example.com:2222,worker1.example.com:2222 \
     --job_name=worker --task_index=1
 

用語集

[クライアント]
クライアントは典型的には、TensorFlow グラフを構築してクラスタと相互作用するために `tensorflow::Session` をコンストラクトするプログラムです。クライアントは典型的には Python または C++ で書かれます。単一のクライアント・プロセスは複数の TensorFlow サーバと直接的に相互作用可能です(上の「リプリケーション訓練」を参照)、そして単一のサーバは複数のクライアントにサービスが提供できます。

[クラスタ]
TensorFlow クラスタは一つまたはそれ以上の「ジョブ」から成り、それぞれは一つまたはそれ以上の「タスク」のリストに分割されます。クラスタは典型的には、多くのマシンを並列に使用してニューラルネットワークを訓練するような、特定の高位レベルの目的に貢献 (dedicated) します。クラスタは `tf.train.ClusterSpec` オブジェクトで定義されます。

[ジョブ]
ジョブは、典型的には共通の目的のためにサービスを提供する、「タスク」のリストから成ります。例えば、`ps` (「パラメータ・サーバ (parameter server)」)と命名されるジョブは典型的には変数をストアして更新するホスト・ノードです; 一方、`worker` と命名されるジョブは典型的には数値計算タスクを遂行するホスト・ステートレス・ノードです。ジョブのタスクは典型的には異なるマシン上で実行されます。ジョブのセットの役割は柔軟です: 例えば、ある `worker` はある状態を維持するかもしれません。

[マスター・サービス]
RPC サービスで、分散デバイスのセットへのリモート・アクセスを提供し、セッション・ターゲットとして動作します。マスター・サービスは tensorflow::Session インターフェイスを実装し、そして一つまたはそれ以上の「ワーカー・サービス」に渡るワークをコーディネートする責任があります。全ての TensorFlow サーバはマスター・サービスを実装します。

[タスク]
タスクは特定の TensorFlow サーバに該当し、そして典型的には単一のプロセスに該当します。タスクは特定の「ジョブ」に属してジョブのタスクリストのインデックスで識別されます。

[TensorFlow サーバ]
tf.train.Server インスタンスを実行するプロセスで、クラスタのメンバーで、そして「マスター・サービス」と「ワーカー・サービス」をエクスポートします。

[ワーカー・サービス]
RPC サービスで、ローカルデバイスを使用して TensorFlow グラフの一部を実行します。ワーカー・サービスは worker_service.proto を実行します。全ての TensorFlow サーバはワーカー・サービスを実装します。

 

以上

TensorFlow 0.8 – 分散コンピューティング・サポート(翻訳/要約)

TensorFlow 0.8 – 分散コンピューティング・サポート (翻訳/要約)
翻訳 : (株)クラスキャット セールスインフォメーション
日時 : 04/14/2016

* TensorFlow が 0.8 リリースでついに分散コンピューティングをサポートしました。
* 本ページは Google Research Blog の4月13日の投稿を参考のため翻訳/要約したものです:
    Announcing TensorFlow 0.8 – now with distributed computing support!

 
本文

Google はその製品の広い範囲に渡り機械学習を使用しています。モデルを継続的に改良するためには、訓練プロセスができる限り速いことが重要です。これを行なう一つの方法は数百台のマシンに渡って TensorFlow を実行することで、これは幾つかのモデルのための訓練プロセスを数週間から数時間に短くし、そして増大するサイズと複雑さを持つモデルでの実験を可能にします。TensorFlow をオープンソース・プロジェクトとしてリリースしてからずっと、分散訓練サポートが最もリクエストを受けた特徴の一つです。もう待つ必要はありません。

今日、分散コンピューティング・サポートを持つ TensorFlow 0.8 を興奮とともにリリース致しました。これはあなた自身のインフラ上の分散モデルを訓練するに必要な全てを含んでいます。分散 TensorFlow は高性能な gRPC ライブラリにより強化されており、これは数百台のマシン上で並列に訓練することをサポートします。これは Google Cloud Machine Learning の最近のアナウンスを補完するもので、これは Google Cloud Platform のパワーを使用して TensorFlow モデルを訓練してサービスを提供することを可能にします。

TensorFlow 0.8 リリースに合わせて、TensorFlow モデル・レポジトリに Inception 画像分類 (image classification)・ニューラルネットワークを公開しました。分散トレーナーを使って、Inception ネットワークを 100 GPU を使用して 65 時間未満で 78% の精度まで訓練しました。小さなクラスタ — あるいは机の上の2台のマシン — さえも分散 TensorFlow から利益を得られます、何故なら更なる GPU の追加は全体のスループットを改善し、正確な結果をより速く生成するからです。

分散トレーナーはまた Kubernetes のようなクラスタ管理システムを使用して訓練をスケールアウトすることをも可能にします。更に、モデルをひとたび訓練したら、製品用にデプロイして Kubernetes 上の TensorFlow Serving を使用して推論を高速化 できます。

分散 Inception を超えて、0.8 リリースはあなた自身の分散モデルを定義するための 新しいライブラリ を含みます。TensorFlow の分散アーキテクチャはモデル定義において多くの柔軟性を与えます、何故ならクラスタの全てのプロセスは汎用計算 (general-purpose computation) を遂行できるからです。私たちの以前のシステム DistBelief は(追随する多くのシステムのように)共有モデルパラメータを管理するために特別な「パラメータ・サーバ」を使用していました。そこではパラメータ・サーバは共有パラーメータを取得し更新するために単純な read/write インターフェイスを持ちます。TensorFlow では、全ての計算 — パラメータ管理を含む — はデータフロー・グラフで表されます、そしてシステムは利用可能なプロセス群においてグラフを(マルチコア CPU、汎用 GPU、そしてモバイル・プロセッサのような)異種デバイス上にマップします。TensorFlow をより簡単に使用するために、(単一プロセス上で実行されて訓練のために複数レプリカを使用するためにスケールされる)モデルを簡単に書けるようにする Python ライブラリを含めました。

このアーキテクチャは単一プロセス・ジョブをクラスタを使用するためにスケールして、そしてまた分散訓練のための新しいアーキテクチャによって実験することを簡単にします。その例として、TensorFlow で実装された、synchronous SGD with backup workers が画像モデル訓練のために改善された時間-to-精度 (time-to-accuracy) を達成することを、私の同僚は最近示しました。

TensorFlow の分散コンピューティング・サポートの現行バージョンは単なるスタートに過ぎません。私たちは分散訓練のパフォーマンスを改良する方法を研究し続けていきます — 技術とアルゴリズム的な改善の両者を通じて — そしてこれらの改良を GutHub 上 でコミュニティと共有します。

(謝辞省略)

 

以上

TensorFlow : Get Started : 基本的な使い方

TensorFlow : Get Started : 基本的な使い方 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション

[更新日時 : 04/15/2016]
* TensorFlow 0.8 から分散コンピューティングがサポートされました。分散関連の記述を追記しました。

[作成日時 : 01/17/2016]
* 本ページは、TensorFlow の本家サイトの Get Started – Basic Usage を翻訳した上で
適宜、補足説明したものです:
    https://www.tensorflow.org/versions/master/get_started/basic_usage.html
* サンプルコードの動作確認はしておりますが、適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 
本文

TensorFlow を利用するためには、TensorFlow がどのようにして:

  • 計算をグラフとして表すか、
  • グラフをセッションのコンテキストで実行するか、
  • データをテンソルとして表すか、
  • 変数の状態を保持するか、
  • 任意の演算に対してデータを供給し取得するために(どのように) “供給/取得” (feeds/fetches) を使用するか、

を理解する必要があります。

 

TensorFlow 概要

TensorFlow は計算をグラフとして表すプログラミング・システムです。グラフのノードは(operation(s) の略で)OP(s) と呼ばれます。OP はゼロあるいはそれ以上のテンソルを受け取り、何某かの計算を実行し、ゼロあるいはそれ以上のテンソルを生成します。テンソルは型づけられた多次元配列です。例えば、画像のミニバッチを次元 [batch, height, width, channels] の浮動小数点 4-D 配列として表現できます。

TensorFlow グラフは計算の表現です。何かを計算するためには、グラフはセッションの中で launch される必要があります。セッションはグラフ OP を例えば CPU や GPU デバイスに置きそれらを実行する方法を提供します。これらの方法は OP により生成されたテンソルを numpy ndarray オブジェクトとして返します。C/C++ では tensorflow::Tensor インスタンスを返します。

 

計算グラフ

TensorFlow プログラムは通常は構築/組み立て (construction) フェイズと実行 (execution) フェイズで構成されます。前者はグラフを組み立て、後者はグラフの OP を実行するためにセッションを使用します。

例えば一般的に、構築フェイズにおいてニューラルネットワークを表現し学習させるグラフを作成し、そしてそれから実行フェイズではグラフの学習 OP のセットを繰り返し実行します。

TensorFlow は C、C++ そして Python プログラムから利用可能です。グラフを組み立てるには Python ライブラリを使用するのが現在のところ遥に簡単です。何故なら C と C++ ライブラリでは利用できないヘルパー関数の大きなセットを提供しているからです。

セッション・ライブラリは3つの言語で同等の機能を持ちます。

グラフの構築

グラフを組み立てるには、例えば constant(定数)のように、一切の入力を必要とせずに (= source OP)、他の計算を行なう OP に出力を渡す OP から開始します。

Python ライブラリの OP コンストラクタは、コンストラクトされた OP の出力を指し示すオブジェクトを返します。これらを他の OP コンストラクタに入力として使用するために渡すことができます。

TensorFlow Python ライブラリはデフォルト・グラフを持ち、それに対して OP コンストラクタはノードを追加します。デフォルト・グラフは多くのアプリケーションにとって十分なものです。複数のグラフをどのように明示的に管理するかは Graph クラス の文書を参照してください。

import tensorflow as tf

# 1x2 行列を生成する constant(定数) OP を作成します。
# OP はノードとしてデフォルトグラフに追加されます。
#
# コンストラクタからの戻り値は constant OP の出力を表します。
matrix1 = tf.constant([[3., 3.]])

# 2x1 行列を生成するもう一つの constant を作成します。
matrix2 = tf.constant([[2.],[2.]])

# 'matrix1' と 'matrix2' を入力として取る Matmul OP を作成します。
# 戻り値 'product' は行列の乗算の結果を表します。
product = tf.matmul(matrix1, matrix2)

デフォルト・グラフは今や3つのノードを持ちます : 2つの constant() OP と一つの matmul() OP です。実際に行列を乗算して乗算の結果を得るためには、セッションでグラフを launch しなければなりません。

セッションでグラフを launch する

構築の次に launch します。グラフを launch するためには、セッション・オブジェクトを作成します。引数がない場合、セッション・コンストラクタはデフォルト・グラフを launch します。

完全な session API については Session クラス を参照してください。

# デフォルト・グラフを launch します。
sess = tf.Session()

# matmul OP を実行するために、matmul OP の出力を表す 'product' を
# 渡して sessioin 'run()' メソッドを呼び出します。これは呼び出しに対して
# matmul OP の出力を返してもらうことを望むことを指示しています。
#
# OP に必要な全ての入力はセッションにより自動的に動作します。
# これらは典型的には並行して動作します。
#
# こうして 'run(product)' の呼び出しは3つの OP の実行をグラフで
# 引き起こします : 2つの constant と matmul です。
#
# OP の出力は 'result' に numpy `ndarray` オブジェクトとして返されます。
#

result = sess.run(product)
print(result)

# ==> [[ 12.]]

# 終了したらセッションを閉じます。
sess.close()

セッションはリソースを開放するために閉じるべきです。
“with” ブロックでセッションに入ることもできます。セッションは with ブロックの最後に自動的に閉じます。

with tf.Session() as sess:
  result = sess.run([product])
  print(result)

TensorFlow の実装はグラフ定義を例えば CPU や GPU カードの一つのような、利用可能な計算資源に渡り分散された実行可能な処理に翻訳します。一般には CPU あるいは GPU を明示的に指定しなくてもかまいません。もし一つを有する場合、TensorFlow は最初の GPU をできる限り多くの処理で使用します。

もし貴方のマシン上で利用可能な1つ以上の GPU を持つ場合、最初のものを超えて GPU を利用するためには、それに OP を明示的に割り当てなければなりません。どの CPU あるいは GPU を処理のために使用するかを指定するためには with…Device ステートメントを使用します :

with tf.Session() as sess:
  with tf.device("/gpu:1"):
    matrix1 = tf.constant([[3., 3.]])
    matrix2 = tf.constant([[2.],[2.]])
    product = tf.matmul(matrix1, matrix2)
    ...

デバイスは文字列で指定されます。現在サポートされるデバイスは :

    "/cpu:0": 貴方のマシンの CPU。
    "/gpu:0": 貴方のマシンの GPU、もし一つを持つのであれば。
    "/gpu:1": 貴方のマシンの2つ目の GPU, etc.

GPU と TensorFlow についての詳細は GPU を利用する を参照してください。

分散セッションでグラフを launch する

TensorFlow クラスタを作成するためには、クラスタの各マシン上で TensorFlow サーバを起動します。クライアントで Session をインスタンス化する時、クラスタにおけるマシンの一つのネットワーク位置をそれに渡します :

with tf.Session("grpc://example.org:2222") as sess:
  # sess.run(...) 呼び出しはクラスタ上で実行されます。
  ...

マシンはセッションのためのマスターとなります。マスターは、ローカル実装がマシン内で利用可能な計算リソースに渡ってグラフを分散させるように、クラスタ(ワーカー)の他のマシン群に渡ってグラフを分散させます。

グラフの特定の部分についてワーカーを直接指定するためには “with tf.device():” ステートメントが使用できます :

with tf.device("/job:ps/task:0"):
  weights = tf.Variable(...)
  biases = tf.Variable(...)

分散セッションとクラスタについての更なる情報については Distributed TensorFlow How To を参照してください。

 

対話的な利用方法

文書内の Python 例題では セッション でグラフを launch し Session.run() メソッドで処理を実行します。

Ipython のような対話的な Python 環境での使い勝手のために、InteractiveSession クラス、そして Tensor.eval()Operation.run() メソッドを代わりに使うことができます。これは変数がセッションを保持し続けなければならないことを回避します。

# 対話的な TensorFlow セッションを入力します。
import tensorflow as tf
sess = tf.InteractiveSession()

x = tf.Variable([1.0, 2.0])
a = tf.constant([3.0, 3.0])

# initializer OP の run() メソッドを使って 'x' を初期化します。
x.initializer.run()

# 'x' から 'a' を減じる OP を追加します。それを動作させ結果を出力します。
sub = tf.sub(x, a)
print(sub.eval())
# ==> [-2. -1.]

# 終了したらセッションを閉じます。
sess.close()
 

テンソル

TensorFlow プログラムは全てのデータを表すためにテンソル・データ構造を用います。 — テンソルだけが計算グラフの処理間で渡されます。TensorFlow のテンソルは n-次元配列またはリストとして考えて良いです。テンソルは静的な型 (type)、階 (rank) と形状 (shape) を持ちます。TensorFlow がこれらの概念をどのように扱うかについて学ぶには、Rank, Shape, and Type リファレンスを参照してください。

変数 (Variables)

変数はグラフの実行を通じて状態 (state) を保持します。次の例題は単純なカウンターとして作用する変数の例です。詳細は Variables を参照してください。

# 変数を作成します。スカラー値 0 に初期化されます。 
state = tf.Variable(0, name="counter")

# `state` に one を加算する OP を作成します。

one = tf.constant(1)
new_value = tf.add(state, one)
update = tf.assign(state, new_value)

# 変数はグラフを launch した後で `init` OP を実行することで
# 初期化されなければなりません。最初にグラフに `init`  OP を
# 追加しなければなりません。
init_op = tf.initialize_all_variables()

# グラフを launch して OP を実行します。
with tf.Session() as sess:
  # 'init' OP を実行します。
  sess.run(init_op)
  # 'state' の初期値を表示します。
  print(sess.run(state))
  # 'state' を更新する OP を実行して 'state' を表示します。
  for _ in range(3):
    sess.run(update)
    print(sess.run(state))

# 出力:

# 0
# 1
# 2
# 3

このコードの assign() OP は add() OP のようにグラフ表現の一部ですから、実際には run() が式を実行するまで割り当ては遂行しません。

典型的には統計モデルのパラメータを変数のセットとして表現します。例えば、ニューラルネットワークの重みを変数中にテンソルとしてストアするでしょう。学習の間、学習グラフを繰り返し実行することでこのテンソルを更新します。

(テンソルの)取得 (Fetches)

処理の出力を取得する (fetch) には、セッション・オブジェクトにおいてグラフを run() 呼び出しで実行して取得したいテンソルを渡します。以前の例では一つのノードの状態を取得しましたが、複数のテンソルを取得できます :

input1 = tf.constant(3.0)
input2 = tf.constant(2.0)
input3 = tf.constant(5.0)
intermed = tf.add(input2, input3)
mul = tf.mul(input1, intermed)

with tf.Session() as sess:
  result = sess.run([mul, intermed])
  print(result)

# 出力:
# [array([ 21.], dtype=float32), array([ 7.], dtype=float32)]

要求されたテンソルの値を生成するに必要な全ての OP は一度だけ実行されます。(要求されたテンソル毎に一度ではなく。)

(テンソルの)供給 (Feeds)

上の例ではテンソルを定数や変数にストアすることによってテンソルを計算グラフに導入しました。TensorFlow はまた、グラフにおける任意の操作にテンソルを直接あてがうために feed(供給)機構を提供しています。

feed は演算の出力を一時的にテンソル値で置き換えます。feed data(供給データ)は run() 呼び出しの引数として供給します。feed は run 呼び出しに対してのみ渡されて使用されます。最も一般的なユースケースでは特定の操作を “feed” 操作に指定することを伴います。tf.placeholder() を使用してそれらを作成します :

input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.mul(input1, input2)

with tf.Session() as sess:
  print(sess.run([output], feed_dict={input1:[7.], input2:[2.]}))

# 出力:
# [array([ 14.], dtype=float32)]

placeholder() 操作は feed を供給しない場合にはエラーを生成します。
feed の大スケールな例は TensorFlow 技法 101 チュートリアルを参照してください。

 

以上

AI導入支援 #2 ウェビナー

スモールスタートを可能としたAI導入支援   Vol.2
[無料 WEB セミナー] [詳細]
「画像認識 AI PoC スターターパック」の紹介
既に AI 技術を実ビジネスで活用し、成果を上げている日本企業も多く存在しており、競争優位なビジネスを展開しております。
しかしながら AI を導入したくとも PoC (概念実証) だけでも高額な費用がかかり取組めていない企業も少なくないようです。A I導入時には欠かせない PoC を手軽にしかも短期間で認知度を確認可能とするサービの紹介と共に、AI 技術の特性と具体的な導入プロセスに加え運用時のポイントについても解説いたします。
日時:2021年10月13日(水)
会場:WEBセミナー
共催:クラスキャット、日本FLOW(株)
後援:働き方改革推進コンソーシアム
参加費: 無料 (事前登録制)
人工知能開発支援
◆ クラスキャットは 人工知能研究開発支援 サービスを提供しています :
  • テクニカルコンサルティングサービス
  • 実証実験 (プロトタイプ構築)
  • アプリケーションへの実装
  • 人工知能研修サービス
◆ お問合せ先 ◆
(株)クラスキャット
セールス・インフォメーション
E-Mail:sales-info@classcat.com