TensorFlow : Guide : 高位 API : Eager Execution (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
更新日時 : 04/11/2019 (1.13.1); 07/14/2018 (1.9.0)
作成日時 : 04/08/2018
* TensorFlow 1.9 でドキュメント構成が変わりましたので調整しました。また本ページは改訂されましたので再翻訳しました。
* 本ページは、TensorFlow 本家サイトの Guide – Hight Level APIs – Eager Execution を翻訳した上で
適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、適宜、追加改変している場合もあります。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
TensorFlow の eager execution は命令型プログラミング環境で、グラフを構築することなく演算を直ちに評価します : 演算は後で実行する計算グラフを構築する代わりに具体的な値を返します。これは TensorFlow を始めてモデルをデバッグすることを容易にして、そしてまたそれはボイラープレートを削減します。このガイドに沿ってフォローするためには、対話的 python インタープリタで下のコード・サンプルを実行してください。
Eager execution は研究や実験のための柔軟な機械学習プラットフォームで、以下を提供します :
- 直感的なインターフェイス — 貴方のコードを自然に構造化して Python データ構造を使用します。小さなモデルと小さなデータ上で迅速に反復します。
- より簡単なデバッギング — 実行中のモデルを調査して変更をテストするために ops を直接的に呼び出します。即時のエラー報告のために標準的な Python デバッギング・ツールを使用します。
- 自然な制御フロー — グラフ制御フローの代わりに Python 制御フローを使用し、動的モデルの仕様を単純化します。
Eager execution は殆どの TensorFlow 演算と GPU アクセラレーションをサポートします。eager execution で動作するサンプルのコレクションについては: tensorflow/contrib/eager/python/examples を見てください。
Note: 幾つかのモデルでは eager execution が有効であると増大したオーバーヘッドを経験するかもしれません。パフォーマンス改善は進行中ですが、問題が見つかる場合にはバグをファイルしてベンチマークを共有してください。
セットアップと基本的な使用方法
TensorFlow の最新版にアップグレードします :
$ pip install --upgrade tensorflow
eager execution を開始するには、プログラムかコンソール・セッションの最初で tf.enable_eager_execution() を追加します。この演算をプログラムが呼び出す他のモジュールには追加しないでください。
from __future__ import absolute_import, division, print_function import tensorflow as tf tf.enable_eager_execution()
今では貴方は TensorFlow 演算を実行できて結果は直ちに返ります :
tf.executing_eagerly() # => True x = [[2.]] m = tf.matmul(x, x) print("hello, {}".format(m)) # => "hello, [[4.]]"
eager execution を有効にすると TensorFlow 演算がどのように挙動するかを変更します — 今ではそれらは即時に評価して値を Python に返します。tf.Tensor オブジェクトは計算グラフのノードへのシンボリックなハンドルの代わりに具体的な値を参照します。セッション内で構築して後で実行する計算グラフはありませんので、print() やデバッガーを使用して結果を調査することは容易です。tensor 値の評価、プリンティング、そしてチェックは勾配を計算するためのフローを壊しません。
Eager execution は NumPy と共に素晴らしく動作します。NumPy 演算は tf.Tensor 引数を受け取ります。TensorFlow 数学演算 は Python オブジェクトと NumPy 配列を tf.Tensor オブジェクトに変換します。tf.Tensor.numpy メソッドはオブジェクトの値を NumPy ndarray として返します。
a = tf.constant([[1, 2], [3, 4]]) print(a) # => tf.Tensor([[1 2] # [3 4]], shape=(2, 2), dtype=int32) # Broadcasting support b = tf.add(a, 1) print(b) # => tf.Tensor([[2 3] # [4 5]], shape=(2, 2), dtype=int32) # Operator overloading is supported print(a * b) # => tf.Tensor([[ 2 6] # [12 20]], shape=(2, 2), dtype=int32) # Use NumPy values import numpy as np c = np.multiply(a, b) print(c) # => [[ 2 6] # [12 20]] # Obtain numpy value from a tensor: print(a.numpy()) # => [[1 2] # [3 4]]
tf.contrib.eager モジュールは eager とグラフ実行環境の両者で利用可能なシンボルを含みそしてグラフと一緒に動作するコードを書く (訳注: 後述) ために有用です :
tfe = tf.contrib.eager
動的制御フロー
eager execution の主なメリットはモデルが実行されているときにホスト言語の総ての機能が利用可能であることです。そのため例えば、fizzbuzz を書くことも容易です :
def fizzbuzz(max_num): counter = tf.constant(0) max_num = tf.convert_to_tensor(max_num) for num in range(max_num.numpy()): num = tf.constant(num) if int(num % 3) == 0 and int(num % 5) == 0: print('FizzBuzz') elif int(num % 3) == 0: print('Fizz') elif int(num % 5) == 0: print('Buzz') else: print(num) counter += 1 return counter
これは tensor 値に依拠する条件節を持ちこれらの値を実行時にプリントします。
モデルを構築する
多くの機械学習モデルは構成する層により表わされます。TensorFlow を eager execution とともに使用するとき貴方自身の層を書くか tf.keras.layers パッケージで提供される層を使用することができます。
層を表わすために任意の Python オブジェクトを使用できる一方で、TensorFlow は便利な基底クラスとして tf.keras.layers.Layer を持ちます。貴方自身の層を実装するためにそれから継承してください :
class MySimpleLayer(tf.keras.layers.Layer): def __init__(self, output_units): super(MySimpleLayer, self).__init__() self.output_units = output_units def build(self, input_shape): # The build method gets called the first time your layer is used. # Creating variables on build() allows you to make their shape depend # on the input shape and hence removes the need for the user to specify # full shapes. It is possible to create variables during __init__() if # you already know their full shapes. self.kernel = self.add_variable( "kernel", [input_shape[-1], self.output_units]) def call(self, input): # Override call() instead of __call__ so we can perform some bookkeeping. return tf.matmul(input, self.kernel)
上の MySimpleLayer の代わりに tf.keras.layers.Dense 層を使用します、何故ならばそれはその機能のスーパーセットを持つからです (それはまたバイアスを加算します)。
層をモデルに構成するときモデルを表わすために層の線形スタックである tf.keras.Sequential を使用することができます。基本モデルのために使用することは容易です :
model = tf.keras.Sequential([ tf.keras.layers.Dense(10, input_shape=(784,)), # must declare input shape tf.keras.layers.Dense(10) ])
他の方法として、tf.keras.Model から継承することによりクラスでモデルを体系化します。これは層のためのコンテナでそれ自身が層で、tf.keras.Model オブジェクトが他の tf.keras.Model オブジェクトを含むことを可能にします。
次のサンプルは標準的な MNIST 手書き数字を分類する多層モデルを作成します。それは eager execution 環境で訓練可能なグラフを構築する optimizer と層 API を示します。
class MNISTModel(tf.keras.Model): def __init__(self): super(MNISTModel, self).__init__() self.dense1 = tf.keras.layers.Dense(units=10) self.dense2 = tf.keras.layers.Dense(units=10) def call(self, input): """Run the model.""" result = self.dense1(input) result = self.dense2(result) result = self.dense2(result) # reuse variables from dense2 layer return result model = MNISTModel()
tf.keras.Model クラスのために入力 shape を設定する必要はありません、何故ならば最初に入力が層に渡されるときにパラメータが設定されるからです。
tf.keras.layers クラスはそれら自身のモデル変数を作成して含み、それらは層オブジェクトのライフタイムに結び付けられます。層変数を共有するためには、それらのオブジェクトを共有します。
Eager 訓練
勾配を計算する
自動微分 はニューラルネットワークを訓練するための バックプロパゲーション のような機械学習アルゴリズムを実装するために有用です。eager execution の間は、後で勾配を計算するための演算を追跡するために tf.GradientTape を使用します。
tfe.GradientTape は追跡しないとき最大限のパフォーマンスを提供するためのオプトインな機能です。異なる演算が各呼び出しの間に発生しますので、総ての forward パス演算は「テープ」に記録されます。勾配を計算するために、テープを反対に再生してから破棄します。特定の一つの tf.GradientTape は 1 つの勾配を計算するだけです ; 続く呼び出しはランタイム・エラーを投げます。
w = tf.Variable([[1.0]]) with tf.GradientTape() as tape: loss = w * w grad = tape.gradient(loss, w) print(grad) # => tf.Tensor([[ 2.]], shape=(1, 1), dtype=float32)
tf.Tensor([[2.]], shape=(1, 1), dtype=float32)
モデルを訓練する
次のサンプルは標準的な MNIST 手書き数字を分類する多層モデルを作成します。それは eager execution 環境で訓練可能なグラフを構築するために optimizer と層 API を実演します。
# Fetch and format the mnist data (mnist_images, mnist_labels), _ = tf.keras.datasets.mnist.load_data() dataset = tf.data.Dataset.from_tensor_slices( (tf.cast(mnist_images[...,tf.newaxis]/255, tf.float32), tf.cast(mnist_labels,tf.int64))) dataset = dataset.shuffle(1000).batch(32)
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz 11493376/11490434 [==============================] - 0s 0us/step
# Build the model mnist_model = tf.keras.Sequential([ tf.keras.layers.Conv2D(16,[3,3], activation='relu'), tf.keras.layers.Conv2D(16,[3,3], activation='relu'), tf.keras.layers.GlobalAveragePooling2D(), tf.keras.layers.Dense(10) ])
訓練なしでさえも、eager executeion でモデルを呼び出して出力を調査してください :
for images,labels in dataset.take(1): print("Logits: ", mnist_model(images[0:1]).numpy())
Logits: [[-0.00147692 -0.02905408 0.04325635 0.03817059 -0.02543205 -0.01521162 0.02900162 -0.03181015 0.05013638 0.07374214]]
keras モデルが (fit メソッドを使用する) 訓練ループを持つ一方で、貴方は時には更なるカスタマイズを必要とします。ここに、eager で実装された訓練ループのサンプルがあります :
optimizer = tf.train.AdamOptimizer() loss_history = []
for (batch, (images, labels)) in enumerate(dataset.take(400)): if batch % 10 == 0: print('.', end='') with tf.GradientTape() as tape: logits = mnist_model(images, training=True) loss_value = tf.losses.sparse_softmax_cross_entropy(labels, logits) loss_history.append(loss_value.numpy()) grads = tape.gradient(loss_value, mnist_model.trainable_variables) optimizer.apply_gradients(zip(grads, mnist_model.trainable_variables), global_step=tf.train.get_or_create_global_step())
........................................
import matplotlib.pyplot as plt plt.plot(loss_history) plt.xlabel('Batch #') plt.ylabel('Loss [entropy]')
Variable と optimizer
tf.Variable オブジェクトは、自動微分をより容易にするために訓練の間にアクセスされるミュータブルな tf.Tensor 値をストアします。モデルのパラメータはクラス内に変数としてカプセル化できます。
モデル・パラメータは tf.Variable を tf.GradientTape と共に使用することでより良くカプセル化できます。例えば、上の自動微分サンプルは次のように書き換えることができます :
class Model(tf.keras.Model): def __init__(self): super(Model, self).__init__() self.W = tf.Variable(5., name='weight') self.B = tf.Variable(10., name='bias') def call(self, inputs): return inputs * self.W + self.B # A toy dataset of points around 3 * x + 2 NUM_EXAMPLES = 2000 training_inputs = tf.random_normal([NUM_EXAMPLES]) noise = tf.random_normal([NUM_EXAMPLES]) training_outputs = training_inputs * 3 + 2 + noise # The loss function to be optimized def loss(model, inputs, targets): error = model(inputs) - targets return tf.reduce_mean(tf.square(error)) def grad(model, inputs, targets): with tf.GradientTape() as tape: loss_value = loss(model, inputs, targets) return tape.gradient(loss_value, [model.W, model.B]) # Define: # 1. A model. # 2. Derivatives of a loss function with respect to model parameters. # 3. A strategy for updating the variables based on the derivatives. model = Model() optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01) print("Initial loss: {:.3f}".format(loss(model, training_inputs, training_outputs))) # Training loop for i in range(300): grads = grad(model, training_inputs, training_outputs) optimizer.apply_gradients(zip(grads, [model.W, model.B]), global_step=tf.train.get_or_create_global_step()) if i % 20 == 0: print("Loss at step {:03d}: {:.3f}".format(i, loss(model, training_inputs, training_outputs))) print("Final loss: {:.3f}".format(loss(model, training_inputs, training_outputs))) print("W = {}, B = {}".format(model.W.numpy(), model.B.numpy()))
Initial loss: 68.132 Loss at step 000: 65.523 Loss at step 020: 30.228 Loss at step 040: 14.266 Loss at step 060: 7.039 Loss at step 080: 3.763 Loss at step 100: 2.276 Loss at step 120: 1.600 Loss at step 140: 1.293 Loss at step 160: 1.153 Loss at step 180: 1.089 Loss at step 200: 1.060 Loss at step 220: 1.047 Loss at step 240: 1.041 Loss at step 260: 1.038 Loss at step 280: 1.037 Final loss: 1.036 W = 3.0057950019836426, B = 1.9924943447113037
eager execution の間に状態のためにオブジェクトを使用する
グラフ実行では、(変数のような) プログラム状態はグローバルなコレクションにストアされてそれらのライフタイムは tf.Session オブジェクトで管理されます。対照的に、eager execuction の間は状態オブジェクトのライフタイムはそれらの対応する Python オブジェクトのライフタイムにより決定されます。
Variables はオブジェクト
eager execution の間、variable はオブジェクトへの最後の参照が除去されるまで存続し、それから削除されます。
if tf.test.is_gpu_available(): with tf.device("gpu:0"): v = tf.Variable(tf.random_normal([1000, 1000])) v = None # v no longer takes up GPU memory
オブジェクト・ベースのセービング
tf.train.Checkpoint は tf.Variable をチェックポイントへ/からセーブしてリストアできます :
x = tf.Variable(10.) checkpoint = tf.train.Checkpoint(x=x)
x.assign(2.) # Assign a new value to the variables and save. checkpoint_path = './ckpt/' checkpoint.save('./ckpt/')
'./ckpt/-1'
x.assign(11.) # Change the variable after saving. # Restore values from the checkpoint checkpoint.restore(tf.train.latest_checkpoint(checkpoint_path)) print(x) # => 2.0
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=2.0>
モデルをセーブしてロードするためには、隠れ変数を必要とすることなく、tf.train.Checkpoint がオブジェクトの内部状態をストアします、モデル、optimizer, そしてグローバルステップの状態を記録するためには、それらを tf.train.Checkpoint に渡します :
import os import tempfile model = tf.keras.Sequential([ tf.keras.layers.Conv2D(16,[3,3], activation='relu'), tf.keras.layers.GlobalAveragePooling2D(), tf.keras.layers.Dense(10) ]) optimizer = tf.train.AdamOptimizer(learning_rate=0.001) checkpoint_dir = tempfile.mkdtemp() checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt") root = tf.train.Checkpoint(optimizer=optimizer, model=model, optimizer_step=tf.train.get_or_create_global_step()) root.save(checkpoint_prefix) root.restore(tf.train.latest_checkpoint(checkpoint_dir))
<tensorflow.python.training.checkpointable.util.CheckpointLoadStatus at 0x7fe652194198>
オブジェクト指向メトリクス
tfe.metrics はオブジェクトとしてストアされます。新しいデータを callable に渡すことでメトリクスを更新して、そして tfe.metrics.result メソッドを使用して結果を取得します、例えば :
m = tfe.metrics.Mean("loss") m(0) m(5) m.result() # => 2.5 m([8, 9]) m.result() # => 5.5
<tf.Tensor: id=68185, shape=(), dtype=float64, numpy=5.5>
Summaries と TensorBoard
TensorBoard はモデル訓練プロセスを理解し、デバッグして最適化するための可視化ツールです。それはプログラムを実行する間に書かれる要約イベントを使用します。
tf.contrib.summary は eager とグラフ実行環境の両者で互換です。tf.contrib.summary.scalar のような要約演算はモデル構築の間に挿入されます。例えば、 100 グローバル・ステップ毎に一度要約を記録するためには :
writer = tf.contrib.summary.create_file_writer(logdir) global_step=tf.train.get_or_create_global_step() # return global step var writer.set_as_default() for _ in range(iterations): global_step.assign_add(1) # Must include a record_summaries method with tf.contrib.summary.record_summaries_every_n_global_steps(100): # your model code goes here tf.contrib.summary.scalar('loss', loss) ...
上級者のための自動微分トピック
動的モデル
tfe.GradientTape はまた動的モデルでも利用できます。バックトラックする直線探索 (= line search) アルゴリズムのこのサンプルは、複雑な制御フローにもかかわらず、普通の NumPy コードのように見えます。勾配があり微分可能であることを除けばです :
def line_search_step(fn, init_x, rate=1.0): with tf.GradientTape() as tape: # Variables are automatically recorded, but manually watch a tensor tape.watch(init_x) value = fn(init_x) grad = tape.gradient(value, init_x) grad_norm = tf.reduce_sum(grad * grad) init_value = value while value > init_value - rate * grad_norm: x = init_x - rate * grad value = fn(x) rate /= 2.0 return x, value
勾配を計算するための追加の関数
tfe.GradientTape は勾配を計算するためのパワフルなインターフェイスですが、自動微分のために利用可能なもう一つの Autograd-スタイル API があります。これらの関数は tfe.Variable なしで tensor と勾配関数だけで、数学コードを書く場合に有用です :
- tfe.gradients_function — 入力関数パラメータのその引数に関する導関数を計算する関数を返します。入力関数パラメータはスカラー値を返さなければなりません。返された関数が呼び起こされたとき、それは tf.Tensor オブジェクトのリストを返します : 入力関数の各引数のために一つの要素です。興味のある任意のものは関数パラメータとして渡されなければなりませんので、これはもし多くの訓練可能なパラメータへの依存がある場合にはこれは扱いにくくなります。
- tfe.value_and_gradients_function — tfe.gradients_function と同様ですが、返された関数が呼び起こされるとき、それは入力関数のその引数に関する導関数のリストに加えて入力関数からの値を返します。
次のサンプルでは、tfe.gradients_function は引数として square 関数を取り square のその入力に関する偏微分を計算する関数を返します。square の 3 における導関数を計算するために、grad(3.0) は 6 を返します。
def square(x): return tf.multiply(x, x) grad = tfe.gradients_function(square) square(3.) # => 9.0 grad(3.) # => [6.0] # The second-order derivative of square: gradgrad = tfe.gradients_function(lambda x: grad(x)[0]) gradgrad(3.) # => [2.0] # The third-order derivative is None: gradgradgrad = tfe.gradients_function(lambda x: gradgrad(x)[0]) gradgradgrad(3.) # => [None] # With flow control: def abs(x): return x if x > 0. else -x grad = tfe.gradients_function(abs) grad(3.) # => [1.0] grad(-3.) # => [-1.0]
カスタム勾配
カスタム勾配は eager とグラフ実行で勾配を override するための簡単な方法です。forward 関数内では、勾配は入力、出力、または中間結果に関する勾配を定義します。例えば、backward パスで勾配のノルムをクリップするための簡単な方法がここにあります :
@tf.custom_gradient def clip_gradient_by_norm(x, norm): y = tf.identity(x) def grad_fn(dresult): return [tf.clip_by_norm(dresult, norm), None] return y, grad_fn
カスタム勾配は演算のシークエンスのための数値的安定な勾配を提供するために一般に使用されます :
def log1pexp(x): return tf.log(1 + tf.exp(x)) grad_log1pexp = tfe.gradients_function(log1pexp) # The gradient computation works fine at x = 0. grad_log1pexp(0.) # => [0.5] # However, x = 100 fails because of numerical instability. grad_log1pexp(100.) # => [nan]
ここで、log1pexp 関数はカスタム勾配で解析的に単純化できます。下の実装は forward パスで計算された tf.exp(x) のための値を再利用しています — 冗長な計算を除去することでそれをより効率的にしています :
@tf.custom_gradient def log1pexp(x): e = tf.exp(x) def grad(dy): return dy * (1 - 1 / (1 + e)) return tf.log(1 + e), grad grad_log1pexp = tfe.gradients_function(log1pexp) # As before, the gradient computation works fine at x = 0. grad_log1pexp(0.) # => [0.5] # And the gradient computation also works at x = 100. grad_log1pexp(100.) # => [1.0]
パフォーマンス
eager execution の間は計算は GPU へと自動的にはオフロードされません。計算が動作する位置について制御することを望む場合にはそれを tf.device(‘/gpu:0’) ブロックで囲むことができます (または CPU の同等のもの) :
import time def measure(x, steps): # TensorFlow initializes a GPU the first time it's used, exclude from timing. tf.matmul(x, x) start = time.time() for i in range(steps): x = tf.matmul(x, x) _ = x.numpy() # Make sure to execute op and not just enqueue it end = time.time() return end - start shape = (1000, 1000) steps = 200 print("Time to multiply a {} matrix by itself {} times:".format(shape, steps)) # Run on CPU: with tf.device("/cpu:0"): print("CPU: {} secs".format(measure(tf.random_normal(shape), steps))) # Run on GPU, if available: if tfe.num_gpus() > 0: with tf.device("/gpu:0"): print("GPU: {} secs".format(measure(tf.random_normal(shape), steps))) else: print("GPU: not found")
出力 (正確な数はハードウェアに依存します) :
Time to multiply a (1000, 1000) matrix by itself 200 times: CPU: 4.614904403686523 secs GPU: 0.5581181049346924 secs
tf.Tensor オブジェクトはその演算を実行するために異なるデバイスへとコピーできます :
x = tf.random_normal([10, 10]) x_gpu0 = x.gpu() x_cpu = x.cpu() _ = tf.matmul(x_cpu, x_cpu) # Runs on CPU _ = tf.matmul(x_gpu0, x_gpu0) # Runs on GPU:0 if tfe.num_gpus() > 1: x_gpu1 = x.gpu(1) _ = tf.matmul(x_gpu1, x_gpu1) # Runs on GPU:1
ベンチマーク
GPU 上の ResNet50 訓練のような計算が重いモデルについては、eager execution パフォーマンスはグラフ実行に匹敵します。しかしこのギャップはより少ない計算を持つモデルのためにはより大きくなって多くの小さい演算を持つモデルのためにホットコード・パスを最適化するために行われなければならないワークがあります。
グラフで作業する
eager execution は開発とデバッギングをより対話的にする一方で、TensorFlow グラフ実行は分散訓練、パフォーマンス最適化、そしてプロダクション配備のための優位点があります。けれども、グラフコードを書くことは標準的な Python コードを書くこととは異なり、デバッグすることがより困難に感じるかもしれません。
グラフ構築モデルをビルドして訓練するためには、Python プログラムは最初に計算を表わすグラフをビルドして、それから C++ ベースのランタイム上で実行のためのグラフを送るために Session.run を呼び起こします。これは以下を提供します :
- 静的 autodiff を使用する自動微分。
- プラットフォーム独立なサーバへの単純な配備。
- グラフ・ベースの最適化 (共通部分式除去, 定数畳み込み, etc.)。
- コンパイルとカーネル・フュージョン。
- 自動的な分散とレプリケーション (ノードを分散システム上に配置)。
eager execution のために書かれるコードの配備はより困難です : モデルからグラフを生成するにせよ、あるいは Python ランタイムとコードをサーバ上で直接的に実行するにせよです。
互換コードを書く
eager execution のために書かれた同じコードはまたグラフ実行の間にはグラフを構築するでしょう。単純に同じコードを新しい Python セッションで実行することでこれを遂行します、そこでは eager execution は有効ではありません。
殆どの TensorFlow 演算は eager execution の間に動作しますが、しかし留意すべき幾つかのことはあります :
- 入力前処理のために queue の代わりに tf.data を使用します。それはより高速で簡単です。
- オブジェクト指向層 API を使用します — tf.keras.layers と tf.keras.Model のような — 何故ならばそれらは変数のためのストレージを明示的に持つからです。
- 殆どのモデル・コードは eager とグラフ実行の間で同じに動作しますが、例外があります。(例えば、入力に基づく計算を変更する Python 制御フローを使用する動的モデル。)
- ひとたび tf.enable_eager_execution で eager execution が有効にされれば、それは無効にはできません。グラフ実行に戻るためには新しい Python セッションを開始します。
eager execution とグラフ実行の両者のためにコードを書くのが最善です。これは、グラフ実行の分散パフォーマンスの恩恵とともに eager の対話的実験とデバッグしやすさを貴方に与えます。
eager execution で書き、デバッグし、そして反復し、それからプロダクション配備のためにモデルグラフをインポートします。モデル変数をセーブしてリストアするためには tfe.Checkpoint を使用します、これは eager とグラフ実行環境の間での移動を可能にします。tensorflow/contrib/eager/python/examples のサンプルを見てください。
グラフ環境で eager execution を使用する
選択的に TensorFlow グラフ環境で tfe.py_func を使用して eager execution を有効にします。これは tf.enable_eager_execution() が呼び出されていないときに使用されます。
def my_py_func(x): x = tf.matmul(x, x) # You can use tf ops print(x) # but it's eager! return x with tf.Session() as sess: x = tf.placeholder(dtype=tf.float32) # Call eager function in graph! pf = tfe.py_func(my_py_func, [x], tf.float32) sess.run(pf, feed_dict={x: [[2.0]]}) # [[4.0]]
以上