TensorFlowの解りにくいところ、Session()の挙動、VariableとPlaceholderの使い分け
———————————————————————–
まずは、Session()の挙動:変数はsessionの繰り返しで更新される!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import tensorflow as tf a = tf.Variable(0) b = tf.constant(1) c = tf.add(a, b) update_a = tf.assign(a, c) d = tf.multiply(c, update_a) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print(sess.run([d])) print(sess.run([d])) print(sess.run([d])) |
と、変数a=0と、定数b=1を和して、結果cをaの更新に使い、cとa更新値を乗してdを得る。
dを求めるsess.run()を3連続で繰り返すと、
1 2 3 |
[1] [4] [9] |
というように、値が更新されていく。ses.runは繰り返されると変数の更新に対応して、結果も更新されていくわけだ。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print(sess.run([d])) print(sess.run([d, d])) print(sess.run([d, d])) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print(sess.run([d])) print(sess.run([d, d])) print(sess.run([d, d])) |
とすると、
1 2 3 4 5 6 |
[1] [4, 4] [9, 9] [1] [4, 4] [9, 9] |
となる。つまり、sess.run()の中での繰り返しでは、変数は更新されていないが、次のsess.runの繰り返しでは、アップデートされた変数が用いられて、結果も更新された。
では、placeholderでどうなるか見てみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
x = tf.Variable(0) y = tf.placeholder(tf.int32) z = tf.add(x, y) update_x = tf.assign(x, z) w = tf.multiply(z, update_x) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) result = sess.run(w, feed_dict={ y: 5 }) result2 = sess.run(w, feed_dict={ y: 5 }) result3 = sess.run(w, feed_dict={ y: 5 }) print(result) print(result2) print(result3) |
1 2 3 |
25 100 225 |
と、sessionごとに変数xが更新されて、結果も更新されてく。
ーーーーーーーーーーーーーーーーー
VariableとPlaceholderの違いは?
ーーーーーーーーーーーーーーーーー
変数:
多くは学習パラメータであり、値はトレーニングから得られる
初期値が必要(しばしばランダム)
プレースホルダ:
データのための割り当てられた記憶域
初期値は必須ではない(tf.placeholder_with_defaultで設定可能)。
ーーーーーーーーーーーーーーーーー
1 2 3 4 5 6 7 8 9 |
x2 = tf.Variable(1, name="x") y2 = tf.Variable(2, name="y") z2 = x2*y2 with tf.Session() as sess: x2.initializer.run() y2.initializer.run() result = z2.eval() print(result) |
に対して、出力は、
1 |
2 |
Placeholderでは、変数と異なり、初期値設定も、初期化も不要で、Shapeも適当でOKで、session内で値をfeedすればよい。
1 2 3 4 5 6 7 8 9 |
a3 = tf.placeholder(tf.float32, shape=(None, 3)) b3 = a3 + 1 with tf.Session() as sess: c3 = b3.eval(feed_dict={a3: [[1, 2, 3]]}) d3 = b3.eval(feed_dict={a3: [[4, 5, 6], [7, 8, 9]]}) print(c3) print(d3) |
出力結果は、
1 2 3 |
[[2. 3. 4.]] [[ 5. 6. 7.] [ 8. 9. 10.]] |
プレースホルダーとVariableをうまく使い分ける例は、以下の通り:
つまり、y=ax+bの直線回帰において、xやyへのデータはplaceholderを設定し、aやbの
パラメータにはvariableを使う。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import numpy as np import tensorflow as tf #モデルパラメータ a4 = tf.Variable([.6], tf.float32) b4 = tf.Variable([-.6], tf.float32) #入力とモデル x = tf.placeholder(tf.float32) linear_model = a4 * x + b4 y = tf.placeholder(tf.float32) #損失関数 loss = tf.reduce_sum(tf.square(linear_model - y)) # sum of the squares #最適化 optimizer = tf.train.GradientDescentOptimizer(0.01) train = optimizer.minimize(loss) #訓練データ x_train = [1,2,3,4,5,6] y_train = [0,3,5,6,9,12] #訓練ループ init = tf.global_variables_initializer() sess = tf.Session() sess.run(init) # reset values to wrong for i in range(500): sess.run(train, {x:x_train, y:y_train}) a4_op, b4_op = sess.run([a4, b4]) print('a4_op:', a4_op) print('b4_op:', b4_op) |
出力結果は、
1 2 |
a4_op: [2.2571368] b4_op: [-2.066639] |