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 チュートリアルを参照してください。
以上