TensorFlow : Guide : 低位 API : グラフとセッション (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
更新日時 : 07/14/2018
作成日時 : 09/16/2017
* TensorFlow 1.9 でドキュメント構成が変わりましたので調整しました。
* 本ページは、TensorFlow 本家サイトの Guide – Low Level APIs – Graphs and Sessions を翻訳した上で
適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、適宜、追加改変している場合もあります。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
TensorFlow は個々の演算間の依存の視点から貴方の計算を表わすためにデータフロー・グラフを使用します。これは低位プログラミング・モデルにつながり、そこでは最初にデータフロー・グラフを定義してそれからローカルとリモート・デバイスのセットに渡るグラフの一部を実行するために TensorFlow セッションを作成します。
このガイドは、貴方が低位のプログラミング・モデルを直接的に使用することを意図する場合に最も有用です。tf.estimator.Estimator と Keras のようなより高位の API はグラフとセッションの詳細をエンドユーザから隠しますが、しかしこれらの API がどのように実装されているか理解することを望む場合にこのガイドはまた有用かもしれません。
何故データフロー・グラフか?
データフロー は並列計算のための一般的なプログラミング・モデルです。データフロー・グラフでは、ノードは計算ユニットを表わし、そしてエッジ (= edge, 辺) は計算により消費または生成されるデータを表わします。例えば、TensorFlow グラフでは、 tf.matmul 演算は2つの入ってくる (= incoming) エッジ (乗算される行列) と一つの出ていく (= outgoing) エッジ (乗算の結果) を持つ単一のノードに相当します。
データフローは貴方のプログラムを実行する時に TensorFlow が影響を与える幾つかの優位点があります :
- 並列性 (= Parallelism)。演算間の依存を表わすために明示的なエッジを使用することにより、システムにとって並列に実行可能な演算を識別することが容易です。
- 分散実行 (Distributed execution)。演算間で流れる値を表わす明示的なエッジを使用することにより、TensorFlow が異なるマシンにアタッチされた複数のデバイス (CPUs, GPUs, と TPUs) に渡り貴方のプログラムを分割することを可能にします。TensorFlow はデバイス間に必要な通信と調整を挿入します。
- コンパイル。TensorFlow の XLA コンパイラ はより速いコードを生成するためにデータフロー・グラフの情報を使用できます、例えば、隣接演算 (= adjacent operations) を一緒に融合することによってです。
- 可搬性。データフロー・グラフは貴方のモデルのコードの言語独立な表現です。データフロー・グラフを Python で構築して、それを SavedModel にストアして、そして遅延の少ない推論のためにそれを C++ プログラムでリストアできます。
tf.Graph とは何でしょう?
tf.Graph は2つの適切な情報のようなものを含みます :
- グラフ構造。グラフのノードとエッジは、個々の演算がどのように一緒に構成されているかを示しますが、しかしそれらがどのように使用されるかは規定しません。グラフ構造はアセンブリコードのようなものです : それの探索は何某かの有用な情報を伝えますが、ソースコードが伝える有用なコンテキストの総てを含むわけではありません。
- グラフ・コレクション。TensorFlow は tf.Graph にメタデータのコレクションをストアするための一般的なメカニズムを提供します。tf.add_to_collection 関数はオブジェクトのリストをキー (ここでは tf.GraphKeys が標準的なキーの幾つかを定義しています) と関連付けることを可能にし、そして tf.get_collection はキーに関連付けられた総てのオブジェクトを調べます。TensorFlow ライブラリの多くのパートはこの仕組み (= facility) を使用します : 例えば、tf.Variable を作成したとき、デフォルトでは “global variables” と “trainable variables” を表わすコレクションに追加されます。後で tf.train.Saver または tf.train.Optimizer を作成するようになったとき、これらのコレクションの変数がデフォルト引数として使用されます。
tf.Graph を構築する
多くの TensorFlow プログラムはデータグラフ構築フェーズから始まります。このフェーズでは、新しい tf.Operation (ノード) と tf.Tensor (エッジ) オブジェクトを構築してそれらを tf.Graph インスタンスに追加する TensorFlow API 関数を呼び出します。TensorFlow は、同じコンテキストの総ての API 関数への暗黙の引数であるデフォルト・グラフを提供します。例えば :
- tf.constant(42.0) の呼び出しは単一の tf.Operation を作成します、これは値 42.0 を生成し、それをデフォルト・グラフに追加し、そして constant の値を表わす tf.Tensor を返します。
- tf.matmul(x, y) の呼び出しは単一の tf.Operation を作成します、これは tf.Tensor オブジェクト x と y の値を乗算し、それをデフォルト・グラフに追加し、そして乗算の結果を表わす tf.Tensor を返します。
- v = tf.Variable(0) の実行はグラフに tf.Operation を追加します、これは tf.Session.run 呼び出し間に永続する書き込み可能なテンソル値をストアするでしょう。tf.Variable オブジェクトはこの演算をラップし、テンソルのように 使用可能で、これはストアされた値の現在値を読むでしょう。tf.Variable オブジェクトはまた assign と assign_add のようなメソッドを持ち、これは実行された時、ストアされた値を更新する tf.Operation オブジェクトを作成します。(変数についての更なる情報は 変数 (Variables) を見てください。)
- tf.train.Optimizer.minimize の呼び出しはデフォルトグラフに演算とテンソルを追加します、これは勾配を計算して実行された時、それらの勾配を変数セットに適用する tf.Operation を返します。
多くのプログラムはデフォルト・グラフのみに依存します。けれども、より進んだユースケースについては Dealing with multiple graphs (訳注: 正しくは Programming with multiple graphs) を見てください。tf.estimator.Estimator API のような高位レベル API は貴方のためにデフォルト・グラフを管理し、そして–例えば–訓練と評価のために異なるグラフを作成するかもしれません。
Note: TensorFlow API の多くの関数の呼び出しは単に演算とテンソルをデフォルト・グラフに追加します、しかし実際の計算は実行しません。代わりに、貴方はこれらの関数を、– 勾配降下の一つのステップを実行するような — 計算全体表わす tf.Tensor また tf.Operation を持つまで構成し、そしてそれからそのオブジェクトを計算を実行するために tf.Session に渡します。より詳細はセクション “Executing a graph in a tf.Session” を見てください。
命名演算 (Naming operations)
tf.Graph オブジェクトはそれが含む tf.Operation のために名前空間を定義します。TensorFlow は貴方のグラフ内の各演算に自動的に一意な名前を選択しますが、演算に記述的な名前をつけることは貴方のプログラムを読みデバッグすることをより容易にします :
- 新しい tf.Operation を作成するか新しい tf.Tensor を返す各 API 関数はオプションの name 引数を受けとります。例えば、tf.constant(42.0, name=”answer”) は “answer” と命名された新しい tf.Operation を作成して “answer:0” と命名された tf.Tensor を返します。デフォルト・グラフが既に “answer” と命名された演算を含む場合は、TensorFlow はそれを一意にするために “_1”, “_2”, 等々を名前に追加するでしょう。
- tf.name_scope 関数は特定のコンテキストで作成された総ての演算に名前スコープ prefix を追加することをを可能にします。現在の名前スコープ prefix は総てのアクティブな tf.name_scope コンテキスト・マネージャの名前の “/”-区切りのリストです。もし名前スコープが現在のコンテキストで既に使用されているのであれば、TensorFlow は “_1”, “_2”, 等々を追加します。例えば :
c_0 = tf.constant(0, name="c") # => operation named "c" # Already-used names will be "uniquified". c_1 = tf.constant(2, name="c") # => operation named "c_1" # Name scopes add a prefix to all operations created in the same context. with tf.name_scope("outer"): c_2 = tf.constant(2, name="c") # => operation named "outer/c" # Name scopes nest like paths in a hierarchical file system. with tf.name_scope("inner"): c_3 = tf.constant(3, name="c") # => operation named "outer/inner/c" # Exiting a name scope context will return to the previous prefix. c_4 = tf.constant(4, name="c") # => operation named "outer/c_1" # Already-used name scopes will be "uniquified". with tf.name_scope("inner"): c_5 = tf.constant(5, name="c") # => operation named "outer/inner_1/c"
グラフ・ビジュアライザはグループ演算に名前スコープを使用してグラフのビジュアル的な複雑さを軽減します。更なる情報については グラフを可視化する を見てください。
tf.Tensor オブジェクトはテンソルを出力として生成する tf.Operation の後に暗黙的に命名されます。テンソル名は “<OP_NAME>:<i>” という形式を持ち、そこでは :
- “<OP_NAME>” はそれを生成する演算の名前です。
- “<i>” は整数で、演算の出力の中でそのテンソルのインデックスを表わします。
異なるデバイス上に演算を置く
貴方の TensorFlow プログラムに複数の異なるデバイスを使用させることを望むのであれば、tf.device 関数は特定のコンテキストで作成された総ての演算が同じデバイス (またはデバイス型) に置かれることををリクエストする便利な方法を提供します。
デバイス仕様は次の形式を持ちます :
/job:<JOB_NAME>/task:<TASK_INDEX>/device:<DEVICE_TYPE>:<DEVICE_INDEX>
ここで :
- <JOB_NAME> 数字で始まらない英数字文字列。
- <DEVICE_TYPE> 登録されたデバイス型 (GPU または CPU のような)。
- <TASK_INDEX> 負でない整数で、<JOB_NAME> という名前のジョブのタスクのインデックスを表わします。ジョブとタスクの説明については tf.train.ClusterSpec を見てください。
- <DEVICE_INDEX> は負でない整数で、例えば、同じプロセスで使用される異なる GPU デバイスを識別する、デバイスのインデックスを表わします。
デバイス仕様の総てのパートを指定する必要はありません。例えば、単一の GPU で単一マシン configuration で実行している場合、幾つかの演算を CPU と GPU に固定する (= pin) ために tf.device を使用するかもしれません :
# Operations created outside either context will run on the "best possible" # device. For example, if you have a GPU and a CPU available, and the operation # has a GPU implementation, TensorFlow will choose the GPU. weights = tf.random_normal(...) with tf.device("/device:CPU:0"): # Operations created in this context will be pinned to the CPU. img = tf.decode_jpeg(tf.read_file("img.jpg")) with tf.device("/device:GPU:0"): # Operations created in this context will be pinned to the GPU. result = tf.matmul(weights, img)
典型的な分散 configuration で TensorFlow を配備しているとき、変数をパラメータ・サーバ・ジョブ (“/job:ps”) のタスク上におくか、他の演算をワーカー・ジョブ (“/job:worker”) のタスク上におくためにジョブ名とタスク ID を指定するかもしれません :
with tf.device("/job:ps/task:0"): weights_1 = tf.Variable(tf.truncated_normal([784, 100])) biases_1 = tf.Variable(tf.zeroes([100])) with tf.device("/job:ps/task:1"): weights_2 = tf.Variable(tf.truncated_normal([100, 10])) biases_2 = tf.Variable(tf.zeroes([10])) with tf.device("/job:worker"): layer_1 = tf.matmul(train_batch, weights_1) + biases_1 layer_2 = tf.matmul(train_batch, weights_2) + biases_2
tf.device は TensorFlow グラフの個々の演算や広範囲な領域に対して配置を選択するために多くの柔軟性を与えます。多くのケースで、うまく動作する単純な経験則があります。例えば、tf.train.replica_device_setter API はデータ並列性分散訓練のために演算を置くために tf.device と一緒に使用することができます。例えば、次のコード断片は tf.train.replica_device_setter が tf.Variable オブジェクトと他の演算への異なる配置ポリシーをどのように適用するかを示します :
with tf.device(tf.train.replica_device_setter(ps_tasks=3)): # tf.Variable objects are, by default, placed on tasks in "/job:ps" in a # round-robin fashion. w_0 = tf.Variable(...) # placed on "/job:ps/task:0" b_0 = tf.Variable(...) # placed on "/job:ps/task:1" w_1 = tf.Variable(...) # placed on "/job:ps/task:2" b_1 = tf.Variable(...) # placed on "/job:ps/task:0" input_data = tf.placeholder(tf.float32) # placed on "/job:worker" layer_0 = tf.matmul(input_data, w_0) + b_0 # placed on "/job:worker" layer_1 = tf.matmul(layer_0, w_1) + b_1 # placed on "/job:worker"
Tensor-like オブジェクト
多くの TensorFlow 演算は引数として一つまたはそれ以上の tf.Tensor オブジェクトを取ります。例えば、tf.matmul は2つの tf.Tensor オブジェクトを取り、そして tf.add_n は n tf.Tensor オブジェクトのリストを取ります。便宜上、これらの関数は tf.Tensor の代わりに tensor-like オブジェクトを受け取ります、そしてtf.convert_to_tensor メソッドを使用してそれを暗黙的に tf.Tensor に変換します。tensor-like オブジェクトは次の型の要素を含みます :
- tf.Tensor
- tf.Variable
- numpy.ndarray
- リスト (そして tensor-like オブジェクトのリスト(群))
- スカラー Python 型 : bool, float, int, str
追加の tensor-like 型は tf.register_tensor_conversion_function を使用して登録できます。
Note: デフォルトでは、TensorFlow は同じ tensor-like オブジェクトを使用するたびに新しい tf.Tensor を作成します。もし tensor-like オブジェクトが巨大 (e.g. 訓練サンプルのセットを含む numpy.ndarray) でそれを複数回使用する場合、メモリ不足になるかもしれません。これを避けるためには、tensor-like オブジェクト上で手動で tf.convert_to_tensor を一度呼び出して返された tf.Tensor を代わりに使いましょう。
tf.Session 内でグラフを実行する
TensorFlow はクライアント・プログラム — 典型的には Python プログラム間の接続を表わすために tf.Session クラスを使用します、同様のインターフェイスは他の言語 — そして C++ ランタイムでも利用可能ですけれども。tf.Session オブジェクトはローカルマシンのデバイス、そしてリモート・デバイスへのアクセスを提供します。それは貴方の tf.Graph についての情報もキャッシュしますので同じ計算を複数回効率的に実行できます。
tf.Session を作成する
低位 TensorFlow API を使用している場合、現在のデフォルト・グラフのために次のように tf.Session を作成することができます :
# Create a default in-process session. with tf.Session() as sess: # ... # Create a remote session. with tf.Session("grpc://example.org:2222"): # ...
tf.Session は (GPU とネットワーク接続のような) 物理的なリソースを所有するので、それは典型的には (with ブロックで)、ブロックを抜けるときにセッションを自動的にクローズするコンテキスト・マネージャとして使用されます。with ブロックなしでセッションを作成することも可能ですが、しかしそれで終了したときにリソースを解放するために tf.Session.close を明示的に呼び出すべきです。
Note: tf.train.MonitoredTrainingSession や tf.estimator.Estimator のような高位 API は貴方のために tf.Session を作成して管理します。これらの API は、以下で記述されるものと同じ意味でオプションの target と config 引数を (直接、または tf.estimator.RunConfig オブジェクトの一部として) 受け取ります。
tf.Session.__init__ は3つのオプションの引数を受け取ります :
- target。この引数が空のまま (デフォルト) であれば、セッションはローカルマシンのデバイスのみを使用するでしょう。けれども、TensorFlow サーバのアドレスを指定するために grpc:// URL を指定することも可能で、これはそのサーバが制御するマシン上の総てのデバイスへのセッション・アクセスを与えます。TensorFlow サーバをどのように作成するかの詳細については tf.train.Server を見てください。例えば、一般的なグラフ間レプリケーション configuration では、tf.Session は同じプロセスで tf.train.Server にクライアントとして接続します。分散 TensorFlow デプロイメント・ガイドは他の一般的なシナリオを記述しています。
- graph。デフォルトでは、新しい tf.Session は現在のデフォルト・グラフにバインドされます — そして (デフォルト・グラフ) 内の演算だけを実行できます。貴方のプログラムで (より詳細は Programming with multiple graphs を見てください (訳注: リンク切れ) ) 複数のグラフを使用している場合は、セッションを構築するときに明示的な tf.Graph で指定できます。
- config。この引数はセッションの挙動を制御する tf.ConfigProto を指定することを可能にします。例えば、configuration オプションの幾つかは以下を含みます :
- allow_soft_placement。これを True に設定すると “ソフト” デバイス配置アルゴリズムを有効にします、これは CPU-only 演算を GPU デバイスに配置することを試みる tf.device アノテーションを無視して、代わりにそれらを CPU 上に配置します。
- cluster_def。分散 TensorFlow を使用しているとき、このオプションは計算でどのマシンを使用するかを指定するすることを可能にして、ジョブ名、タスク・インデックス、そしてネットワークアドレス間のマッピングを提供します。詳細は tf.train.ClusterSpec.as_cluster_def を見てください。
- graph_options.optimizer_options。TensorFlow が貴方のグラフについて実行前に遂行する最適化に渡る制御を提供します。
- gpu_options.allow_growth。GPU メモリ・アロケータを変更するためにこれを True に設定します、その結果、それはスタートアップ時にメモリの殆どを割り当てるのではなく、割り当てられるメモリ総量を徐々に増やします。
演算を実行するために tf.Session.run を使用する
tf.Session.run メソッドは tf.Operation を実行したり tf.Tensor を評価するための主要なメカニズムです。一つまたはそれ以上の tf.Operation か tf.Tensor オブジェクトを tf.Session.run に渡すことができ、そして TensorFlow は結果を計算するために必要とされる演算を実行します。
tf.Session.run は fetches (取得) のリストを指定することを要求します、これは戻り値を決定するもので、tf.Operation, tf.Tensor, または tf.Variable のような tensor-like 型 です。 これらの fetches は結果を生成するために tf.Graph 全体のどのサブグラフが実行されなければならないかを決定します : サブグラフは fetch リストで命名された総ての演算を含み、加えて出力が fetches の値を計算するために使用される総ての演算です。例えば、次のコード断片は、tf.Session.run への異なる引数は異なるサブグラフが実行されることを引き起こすことを示します :
x = tf.constant([[37.0, -23.0], [1.0, 4.0]]) w = tf.Variable(tf.random_uniform([2, 2])) y = tf.matmul(x, w) output = tf.nn.softmax(y) init_op = w.initializer with tf.Session() as sess: # Run the initializer on `w`. sess.run(init_op) # Evaluate `output`. `sess.run(output)` will return a NumPy array containing # the result of the computation. print(sess.run(output)) # Evaluate `y` and `output`. Note that `y` will only be computed once, and its # result used both to return `y_val` and as an input to the `tf.nn.softmax()` # op. Both `y_val` and `output_val` will be NumPy arrays. y_val, output_val = sess.run([y, output])
tf.Session.run はまたオプションで feeds の辞書を取ります、これは tf.Tensor オブジェクト (典型的には tf.placeholder テンソル) から実行時にそっらのテンソルの代わりに用いられる値 (典型的には Python スカラ、リスト、または NumPy 配列) へのマッピングです。例えば :
# Define a placeholder that expects a vector of three floating-point values, # and a computation that depends on it. x = tf.placeholder(tf.float32, shape=[3]) y = tf.square(x) with tf.Session() as sess: # Feeding a value changes the result that is returned when you evaluate `y`. print(sess.run(y, {x: [1.0, 2.0, 3.0]}) # => "[1.0, 4.0, 9.0]" print(sess.run(y, {x: [0.0, 0.0, 5.0]}) # => "[0.0, 0.0, 25.0]" # Raises `tf.errors.InvalidArgumentError`, because you must feed a value for # a `tf.placeholder()` when evaluating a tensor that depends on it. sess.run(y) # Raises `ValueError`, because the shape of `37.0` does not match the shape # of placeholder `x`. sess.run(y, {x: 37.0})
tf.Session.run はまた、呼び出しについての options を指定することを可能にするオプションの options 引数と、実行についてのメタデータを収集することを可能にするオプションの run_metadata 引数を受け取ります。例えば、実行についての追跡情報を収集するためにこれらの options を一緒に使用できます :
y = tf.matmul([[37.0, -23.0], [1.0, 4.0]], tf.random_uniform([2, 2])) with tf.Session() as sess: # Define options for the `sess.run()` call. options = tf.RunOptions() options.output_partition_graphs = True options.trace_level = tf.RunOptions.FULL_TRACE # Define a container for the returned metadata. metadata = tf.RunMetadata() sess.run(y, options=options, run_metadata=metadata) # Print the subgraphs that executed on each device. print(metadata.partition_graphs) # Print the timings of each operation that executed. print(metadata.step_stats)
グラフを可視化する
TensorFlow はグラフのコードを理解する助けができるツールを含みます。グラフ・ビジュアライザは、貴方のグラフ構造をブラウザでビジュアルにレンダリングする TensorBoard のコンポーネントです。ビジュアリゼーションを作成する最も簡単な方法は tf.summary.FileWriter を作成するときに tf.Graph を渡すことです :
# Build your graph. x = tf.constant([[37.0, -23.0], [1.0, 4.0]]) w = tf.Variable(tf.random_uniform([2, 2])) y = tf.matmul(x, w) # ... loss = ... train_op = tf.train.AdagradOptimizer(0.01).minimize(loss) with tf.Session() as sess: # `sess.graph` provides access to the graph used in a `tf.Session`. writer = tf.summary.FileWriter("/tmp/log/...", sess.graph) # Perform your computation... for i in range(1000): sess.run(train_op) # ... writer.close()
Note: tf.estimator.Estimator を使用しているのであれば、グラフ (と任意の要約) は estimator を作成するときに指定した model_dir へ自動的にログ出力されるでしょう。
それから tensorboard でログを開いて、”Graph” タブにナビゲートして、貴方のグラフ構造の高位の可視化を見ることができます。典型的な TensorFlow グラフ — 特に自動的に勾配を計算する訓練グラフ — は一度に可視化するには多すぎるノードを持つことに注意してください。グラフ・ビジュアライザは関連する演算を “スーパー” ノードにグループ化するために名前スコープを利用します。これらのスーパー・ノードの任意の上で内側のサブグラフを広げるためにオレンジ色の “+” ボタンの上をクリックすることができます。
TensorBoard で貴方の TensorFlow アプリケーションを可視化することについての更なる情報については、TensorBoard チュートリアルを見てください (訳注: リンク切れ)。
複数のグラフでプログラミングする
Note: モデルを訓練するとき、貴方のコードを整理する一般的な方法はモデルを訓練するために一つのグラフを使い、そして訓練されたモデルで評価または推論を実行するために別のグラフを使うことです。多くのケースでは、推論グラフは訓練グラフとは異なるでしょう : 例えば、dropout とバッチ正規化のようなテクニックは各々の場合に異なる演算を使用します。更に、デフォルトでは tf.train.Saver のようなユティリティは 保存されたチェックポイントの各変数を識別するために tf.Variable オブジェクト (基本的な tf.Operation に基づく名前を持ちます) の名前を使用します。このようにプログラミングするとき、グラフを構築して実行するために完全に別の Python プロセスを使用することもできるし、同じプロセスで複数のグラフを使用することもできます。このセクションは同じプロセスで複数のグラフをどのように使用するかを記述します。
上で言及したように、TensorFlow は、同じコンテキストで総ての API 関数に暗黙的に渡される “デフォルト・グラフ” を提供します。多くのアプリケーションのためには、単一のグラフで十分です。けれども、TensorFlow はまたデフォルト・グラフを操作するためのメソッドをまた提供します、これはより進んだユースケースでは有用です。例えば :
- tf.Graph は tf.Operation オブジェクトのために名前空間を定義します : 単一のグラフの各演算は一意の名前を持たなければなりません。TensorFlow は、リクエストされた名前が既に取られていた場合には、演算の名前をそれらの名前に “_1”, “_2”, 等々を追加することで “一意にします (= uniquify)” 。複数の明示的に作成されたグラフを使用することはどのような名前が各演算に与えられるかについて更なる制御を与えます。
- デフォルト・グラフは、それにそれまでに追加された総ての tf.Operation と tf.Tensor についての情報をストアします。もし貴方のプログラムが巨大な数の接続されないサブグラフを作成するのであれば、各サブグラフを構築するために異なる tf.Graph を使用することがより効率的かもしれません、関係しない状態はガベージコレクションされます。
tf.Graph.as_default コンテキスト・マネージャを使用して、異なる tf.Graph を default Graph としてインストールできます :
g_1 = tf.Graph() with g_1.as_default(): # Operations created in this scope will be added to `g_1`. c = tf.constant("Node in g_1") # Sessions created in this scope will run operations from `g_1`. sess_1 = tf.Session() g_2 = tf.Graph() with g_2.as_default(): # Operations created in this scope will be added to `g_2`. d = tf.constant("Node in g_2") # Alternatively, you can pass a graph when constructing a `tf.Session`: # `sess_2` will run operations from `g_2`. sess_2 = tf.Session(graph=g_2) assert c.graph is g_1 assert sess_1.graph is g_1 assert d.graph is g_2 assert sess_2.graph is g_2
現在のデフォルト・グラフを調べるためには、tf.get_default_graph を呼び出します、これは tf.Graph オブジェクトを返します :
# Print all of the operations in the default graph. g = tf.get_default_graph() print(g.get_operations())
以上