TensorFlow : Get Started : TensorFlow で始めましょう (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
再検証日時 : 04/13/2017
作成日時 : 03/18/2017
* TensorFlow の Get Started 文書が追加補充され、より分かりやすくなっています。tf.contrib.learn への言及もあります。
* 本ページは、TensorFlow の本家サイトの Get Started – Getting Started With TensorFlow を翻訳した上で適宜、補足説明したものです:
https://www.tensorflow.org/get_started/get_started
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
このガイドは貴方に TensorFlow によるプログラミングを開始して頂くためのものです。このガイドを使用する前に、TensorFlow をインストールしましょう。このガイドから多くを得るためには、次について知っておくべきです :
- Python でどのようにプログラムするか。
- 少なくとも配列について少々。
- 理想的には機械学習について何某か。けれども、機械学習について殆どあるいは全く知らないとしても、これは依然として読むべき最初のガイドとなるでしょう。
TensorFlow は複数の API を提供します。最も低いレベルの API — TensorFlow Core — は完全なプログラミング制御を貴方に提供します。 機械学習研究者とモデル上の優れた制御レベルを必要とする他の人たちのためには TensorFlow Core を推奨します。より高位の API は TensorFlow Core の上に構築されています。これらの高位 API は典型的には TensorFlow Core よりも学習して使用するのがより簡単です。更に、より高位の API は反復的なタスクをより簡単にして異なるユーザ間で一貫性を保持できます。tf.contrib.learn のような高位 API はデータセット、推定器 (estimator)、トレーニングそして推論を管理する手助けをします。高位 TensorFlow API の2、3 — これらのメソッド名は contrib を含むものです — は依然として開発中であることに注意してください。幾つかの contrib メソッドは後の TensorFlow リリースでは変更されるか廃止される可能性もあります。
このガイドは TensorFlow Core 上のチュートリアルから始めます。後で、同じモデルを tf.contrib.learn でどのように実装するかを示します。TensorFlow Core の原理を知ることは、よりコンパクトな高位 API を使用するときに、どのように物事が内部的に動作するかの偉大なメンタルモデルを与えてくれます。
テンソル (Tensors)
TensorFlow におけるデータの中心的なユニットはテンソルです。テンソルは、任意の次元数の配列に形状化されたプリミティブな値のセットから成ります。テンソルのランク (rank) はその次元の数です。テンソルの幾つかの例をここに示します :
3 # a rank 0 tensor; this is a scalar with shape [] [1. ,2., 3.] # a rank 1 tensor; this is a vector with shape [3] [[1., 2., 3.], [4., 5., 6.]] # a rank 2 tensor; a matrix with shape [2, 3] [[[1., 2., 3.]], [[7., 8., 9.]]] # a rank 3 tensor with shape [2, 1, 3]
TensorFlow Core チュートリアル
TensorFlow をインポートする
TensorFlow プログラムのための標準的な import ステートメントは次のようなものです :
import tensorflow as tf
これは Python に全ての TensorFlow のクラス、メソッド、そしてシンボルへのアクセスを与えます。殆どのドキュメントは貴方がこれを既に実行していることを仮定しています。
計算グラフ
TensorFlow Core プログラムを2つの個別のセクションから成るものと考えて良いです :
- 計算グラフを構築する。
- 計算グラフを実行する。
計算グラフはノードのグラフに配列されたTensorFlow 演算の系列です。単純な計算グラフを構築してみましょう。各ノードはゼロまたはそれ以上のテンソルを入力として取り、出力としてテンソルを生成します。ノードの一つの型は constant です。全ての TensorFlow constant のように、それは入力を取らずに、内部的に保持した値を出力します。浮動小数点テンソル node1 と node2 を次のように作成できます :
node1 = tf.constant(3.0, tf.float32) node2 = tf.constant(4.0) # also tf.float32 implicitly print(node1, node2)
最後の print ステートメントは以下を生成します :
Tensor("Const:0", shape=(), dtype=float32) Tensor("Const_1:0", shape=(), dtype=float32)
ノードのプリンティングは貴方が期待したような、値 3.0 と 4.0 を出力しないことに注目しましょう。その代わり、それらは評価されたときに 3.0 と 4.0 をそれぞれ生成するノードです。実際にノードを評価するためには、session の中で計算グラフを実行しなければなりません。session は TensorFlow ランタイムの制御と状態をカプセル化します。
次のコードは Session オブジェクトを作成してそして node1 と node2 を評価するために十分な計算グラフを実行するためにその run メソッドを呼び出します。次のように session で計算グラフを実行することにより :
sess = tf.Session() print(sess.run([node1, node2]))
3.0 と 4.0 の期待した値を見ます :
[3.0, 4.0]
テンソル・ノードを演算 (演算もまたノードです) と結合することでより複雑な計算を構築できます。例えば、2つの constant ノードを加算して新しいグラフを次のように生成できます :
node3 = tf.add(node1, node2) print("node3: ", node3) print("sess.run(node3): ",sess.run(node3))
最後の2つの print ステートメントは以下を生成します :
node3: Tensor("Add_2:0", shape=(), dtype=float32) sess.run(node3): 7.0
TensorFlow は TensorBoard と呼ばれるユティリティを提供しています、これは計算グラフの図を表示できます。以下は TensorBoard がグラフをどのように可視化するかを示すスクリーンショットです :
そのままでは、このグラフは特に面白くありません、何故ならばこれはいつも定数の結果を生成するからです。
グラフは外部入力を受け取るようにパラメータ化され、これはプレースホルダーとして知られます。プレースホルダーは後で値を提供するという約束 (= promise) です。
a = tf.placeholder(tf.float32) b = tf.placeholder(tf.float32) adder_node = a + b # + provides a shortcut for tf.add(a, b)
すぐ前の3行は幾分、関数か lambda のようでそこでは2つの入力パラメータ (a と b) とそしてそれらの上の演算を定義します。これらのプレースホルダーに具体的な値を提供するテンソルを指定するために feed_dict パラメータを使用して、複数の入力でこのグラフを評価できます :
print(sess.run(adder_node, {a: 3, b:4.5})) print(sess.run(adder_node, {a: [1,3], b: [2, 4]}))
出力は次の結果になります :
7.5 [ 3. 7.]
TensorBoard では、グラフはこのように見えます :
他の演算を追加することで計算グラフをより複雑にできます。例えば :
add_and_triple = adder_node * 3. print(sess.run(add_and_triple, {a: 3, b:4.5}))
は以下の出力を生成します :
22.5
前の計算グラフは TensorBoard では次のように見えるでしょう :
機械学習では典型的には上のように、任意の入力が取れるモデルが望まれます。モデルをトレーニング可能にするためには、同じ入力で新しい出力を得るためにグラフを変更できる必要があります。variable はグラフにトレーニング可能なパラメータを追加することを可能にします。それらは型と初期値で構築されます :
W = tf.Variable([.3], tf.float32) b = tf.Variable([-.3], tf.float32) x = tf.placeholder(tf.float32) linear_model = W * x + b
constant は tf.constant を呼び出したときに初期化されそれらの値は決して変わりません。variable は tf.Variable を呼び出したときに初期化されません。
TensorFlow プログラムで全ての variable を初期化するためには、次のように特殊な演算を明示的に呼び出さなければなりません :
init = tf.global_variables_initializer() sess.run(init)
init が、全てのグローバル variables を初期化する TensorFlow サブグラフへのハンドルであることを理解することは重要です。sess.run を呼び出すまでは、variables は初期化されないままです。
x はプレースホルダーなので、次のように幾つかの x の値に対して linear_model を同時に評価することができます :
print(sess.run(linear_model, {x:[1,2,3,4]}))
出力は次のように生成されます :
[ 0. 0.30000001 0.60000002 0.90000004]
モデルを作成しましたが、それがどの程度良いかはまだ分かっていません。トレーニング・データ上でモデルを評価するためには、望ましい値を提供する y プレースホルダーが必要で、損失関数を書く必要があります。
損失関数は現在のモデルが提供されたデータからどの程度遠く離れているのかを計測します。線形回帰のための標準的な損失モデルを使用します、これは現在のモデルと提供されたデータの間の delta (差分) の二乗の合計します。linear_model – y はベクトルを作成しこれは各要素が相当するサンプルのエラー delta です。それらのエラーを二乗するために tf.square を呼び出します。それから、tf.reduce_sum を使用して全ての二乗されたエラーを合計して単一のスカラを作成します、これは全てのサンプルのエラーを抽象化します :
y = tf.placeholder(tf.float32) squared_deltas = tf.square(linear_model - y) loss = tf.reduce_sum(squared_deltas) print(sess.run(loss, {x:[1,2,3,4], y:[0,-1,-2,-3]}))
損失値を生成します :
23.66
W と b の値を -1 と 1 という完全な値に再割り当てすることによりこれを手動で改善できるでしょう。variable は tf.Variable に提供された値に初期化されますが tf.assign のような演算子を使用して変更できます。例えば、W=-1 と b=1 はモデルに対しての最適なパラメータです。W と b をそれぞれ変更できます :
fixW = tf.assign(W, [-1.]) fixb = tf.assign(b, [1.]) sess.run([fixW, fixb]) print(sess.run(loss, {x:[1,2,3,4], y:[0,-1,-2,-3]}))
最後の print は今や損失がゼロであることを示します。
0.0
W と b の “完全な” 値を推測しましたが、機械学習の核心は正しいモデルパラメータを自動的に見つけることです。次のセクションでどのようにこれを成し遂げるかを示します。
tf.train API
機械学習の完全な議論はこのチュートリアルの範囲外です。けれども、TensorFlow は損失関数を最小化するために各変数をゆっくりと変更する optimizer を提供します。もっとも単純な optimizer は勾配降下です。それは変数に関する損失の導関数の大きさにしたがって各変数を変更します。一般的に、シンボル型の導関数を手動で計算することは退屈で誤りがちです。結果として、モデルの記述のみが与えられたときに TensorFlow は tf.gradients を使用して自動的に導関数を生成します。単純化のために、optimizer は典型的にはこれを貴方のために行ないます。例えば、
optimizer = tf.train.GradientDescentOptimizer(0.01) train = optimizer.minimize(loss)
sess.run(init) # reset values to incorrect defaults. for i in range(1000): sess.run(train, {x:[1,2,3,4], y:[0,-1,-2,-3]}) print(sess.run([W, b]))
最終的なモデル・パラメータは :
[array([-0.9999969], dtype=float32), array([ 0.99999082], dtype=float32)]
今や実際の機械学習を行ないました! この単純な線形回帰は TensorFlow core コードの多くを必要としませんが、モデルへデータを供給する、より複雑なモデルとメソッドは更なるコードを必要とします。このように TensorFlow は共通のパターン、構造、そして機能のためにより高位の抽象を提供します。次のセクションではこれらの抽象の幾つかをどのように使用するかを学びます。
完全なプログラム
完全なトレーニング可能な線形回帰モデルはこのように示されます :
import numpy as np import tensorflow as tf # Model parameters W = tf.Variable([.3], tf.float32) b = tf.Variable([-.3], tf.float32) # Model input and output x = tf.placeholder(tf.float32) linear_model = W * x + b y = tf.placeholder(tf.float32) # loss loss = tf.reduce_sum(tf.square(linear_model - y)) # sum of the squares # optimizer optimizer = tf.train.GradientDescentOptimizer(0.01) train = optimizer.minimize(loss) # training data x_train = [1,2,3,4] y_train = [0,-1,-2,-3] # training loop init = tf.global_variables_initializer() sess = tf.Session() sess.run(init) # reset values to wrong for i in range(1000): sess.run(train, {x:x_train, y:y_train}) # evaluate training accuracy curr_W, curr_b, curr_loss = sess.run([W, b, loss], {x:x_train, y:y_train}) print("W: %s b: %s loss: %s"%(curr_W, curr_b, curr_loss))
実行すると、以下を生成します :
W: [-0.9999969] b: [ 0.99999082] loss: 5.69997e-11
このより複雑なプログラムは依然として TensorBoard で可視化できます :
tf.contrib.learn
tf.contrib.learn は高位な TensorFlow ライブラリで機械学習の技巧を単純化し、次を含みます :
- トレーニング・ループを実行する
- 評価ループを実行する
- データセットを管理する
- 供給を管理する
tf.contrib.learn は多くの一般的なモデルを定義します。
基本的な使い方
線形回帰プログラムが tf.contrib.learn でどのくらい単純になるかに注目しましょう :
import tensorflow as tf # NumPy is often used to load, manipulate and preprocess data. import numpy as np # Declare list of features. We only have one real-valued feature. There are many # other types of columns that are more complicated and useful. features = [tf.contrib.layers.real_valued_column("x", dimension=1)] # An estimator is the front end to invoke training (fitting) and evaluation # (inference). There are many predefined types like linear regression, # logistic regression, linear classification, logistic classification, and # many neural network classifiers and regressors. The following code # provides an estimator that does linear regression. estimator = tf.contrib.learn.LinearRegressor(feature_columns=features) # TensorFlow provides many helper methods to read and set up data sets. # Here we use `numpy_input_fn`. We have to tell the function how many batches # of data (num_epochs) we want and how big each batch should be. x = np.array([1., 2., 3., 4.]) y = np.array([0., -1., -2., -3.]) input_fn = tf.contrib.learn.io.numpy_input_fn({"x":x}, y, batch_size=4, num_epochs=1000) # We can invoke 1000 training steps by invoking the `fit` method and passing the # training data set. estimator.fit(input_fn=input_fn, steps=1000) # Here we evaluate how well our model did. In a real example, we would want # to use a separate validation and testing data set to avoid overfitting. estimator.evaluate(input_fn=input_fn)
実行時、以下を生成します :
{'global_step': 1000, 'loss': 1.9650059e-11}
カスタム・モデル
tf.contrib.learn はその事前定義されたモデルに貴方をロックするわけではありません。TensorFlow に組み込まれていないカスタムモデルを作成したいとしましょう。tf.contrib.learn のデータセット、供給、トレーニング等の高位抽象を依然として保持可能です。例示のために、LinearRegressor と同値な私たち自身のモデルをより低位な TensorFlow API の知識を使用してどのように実装するかを示します。
tf.contrib.learn で動作するカスタムモデルを定義するためには、tf.contrib.learn.Estimator を使用する必要があります。tf.contrib.learn.LinearRegressor は実際には tf.contrib.learn.Estimator のサブクラスです。Estimator をサブクラス化する代わりに、tf.contrib.learn にどのように予測、トレーニングステップ、そして損失を評価可能であるかを知らせる関数 model_fn を単純に Estimator に提供します。コードは次のようなものです :
import numpy as np import tensorflow as tf # Declare list of features, we only have one real-valued feature def model(features, labels, mode): # Build a linear model and predict values W = tf.get_variable("W", [1], dtype=tf.float64) b = tf.get_variable("b", [1], dtype=tf.float64) y = W*features['x'] + b # Loss sub-graph loss = tf.reduce_sum(tf.square(y - labels)) # Training sub-graph global_step = tf.train.get_global_step() optimizer = tf.train.GradientDescentOptimizer(0.01) train = tf.group(optimizer.minimize(loss), tf.assign_add(global_step, 1)) # ModelFnOps connects subgraphs we built to the # appropriate functionality. return tf.contrib.learn.ModelFnOps( mode=mode, predictions=y, loss=loss, train_op=train) estimator = tf.contrib.learn.Estimator(model_fn=model) # define our data set x = np.array([1., 2., 3., 4.]) y = np.array([0., -1., -2., -3.]) input_fn = tf.contrib.learn.io.numpy_input_fn({"x": x}, y, 4, num_epochs=1000) # train estimator.fit(input_fn=input_fn, steps=1000) # evaluate our model print(estimator.evaluate(input_fn=input_fn, steps=10))
実行時、以下を生成します :
{'loss': 5.9819476e-11, 'global_step': 1000}
カスタム model() 関数の内容が、どのようにより低位な API からの手動モデルのトレーニング・ループに非常に類似しているかに注意してください。
次のステップ
さて今貴方は TensorFlow の基本の実際上の知識を持ちました。更に学ぶために見ることができる幾つかのチュートリアルがあります。もし貴方が機械学習の初心者であるならば ML 初心者向けの MNIST を見てください、そうでなければ 専門家のための深層 MNIST を見てください。
以上