TensorFlow学習ノート2


TensorBoardの可視化
tensorflowは単なる計算図ソフトではなくtensorboardの可視化ツールも含む、tensorflowをインストールする際にデフォルトでインストールされ、使用方法は非常に簡単で、writer=tfを使用する.summary.FileWriter('./graph',sess.graph)では、ファイルライタを作成できます.graphはストレージディレクトリですgraphは読み込んだ図構造を表す.
簡単なプログラムを書くことができます
import tensorflow as tf
a = tf.constant(2)
b = tf.constant(3)
x = tf.add(a, b)
with tf.Session() as sess:
    writer = tf.summary.FileWriter('./graphs', sess.graph)
    print(sess.run(x))
writer.close()  # close the writer when you’re done using it

定数タイプ(Constant types)
次のように定数を作ることができます
tf.constant(value, dtype=None, shape=None, name='Const', verify_shape=False)

たとえば、1 Dベクトルとマトリクスを作成し、それらを乗算します.
a = tf.constant([2, 2], name='a')
b = tf.constant([[0, 1], [2, 3]], name='b')
x = tf.multiply(a, b, name='dot_production')
with tf.Session() as sess:
    print(sess.run(x))
>> [[0, 2]
    [4, 6]]

これはnumpyとあまり差がありませんが、特殊な値の定数も作成されています.
tf.zeros(shape, dtype=tf.float32, name=None)
tf.zeros_like(input_tensor, dtype=None, name=None, optimize=True)
tf.ones(shape, dtype=tf.float32, name=None)
tf.ones_like(input_tensor, dtype=None, name=None, optimize=True)
tf.fill(dims, value, name=None)
tf.fill([2, 3], 8)
>> [[8, 8, 8], [8, 8, 8]]

numpyに似たシーケンスの作成もあります
tf.linspace(start, stop, num, name=None)
tf.linspace(10.0, 13.0, 4)
>> [10.0, 11.0, 12.0, 13.0]
tf.range(start, limit=None, delta=1, dtype=None, name='range')
tf.range(3, limit=18, delta=3)
>> [3, 6, 9, 12, 15]

これとnumpyの最大の違いは、反復できないこと、すなわち
for _ in tf.range(4): # TypeError

それ以外にもいくつかの乱数を生成することができます
tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)
tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None,
name=None)
tf.random_uniform(shape, minval=0, maxval=None, dtype=tf.float32, seed=None,
name=None)
tf.random_shuffle(value, seed=None, name=None)
tf.random_crop(value, size, seed=None, name=None)
tf.multinomial(logits, num_samples, seed=None, name=None)
tf.random_gamma(shape, alpha, beta=None, dtype=tf.float32, seed=None, name=None)

またtensorflowとnumpyのデータ型は共通であり,すなわち
tf.ones([2, 2], np.float32)
>> [[1.0, 1.0], [1.0, 1.0]]

pythonが持参したデータ型は使用しないほうがいいです.numpyデータ型を使用するときは、将来tensorflowのデータ型とnumpyが互換性がない可能性があるので、注意してください.
変数(Variable)
定数の使用にはどのような問題がありますか?定数は計算図の定義に存在し,定数が多すぎると計算図のロードが非常に遅くなり,定数の値が変更できないため変数が導入される.
a = tf.Variable(2, name='scalar')
b = tf.Variable([2, 3], name='vector')
c = tf.Variable([[0, 1], [2, 3]], name='matrix')
w = tf.Variable(tf.zeros([784, 10]), name='weight')

変数には次の操作があります.
x = tf.Variable()
x.initializer #    
x.eval() #       
x.assign() #         

なお、変数を使用する前に初期化する必要があり、初期化は変数の割り当て値操作と見なすことができる.最も簡単な初期化方法は、すべての変数を一度に初期化することです.
init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)

一部の変数を初期化することもできます
init_ab = tf.variable_initializer([a, b], name='init_ab')
with tf.Session() as sess:
    sess.run(init_ab)

あるいは変数を初期化します
w = tf.Variable(tf.zeros([784, 10]))
with tf.Session() as sess:
    sess.run(w.initializer)

変数の値を取り出すには2つの方法があります
w = tf.Variable(tf.truncated_normal([10, 10], name='normal'))
with tf.Session() as sess:
    sess.run(w.initializer)
    print(w.eval()) #    
    print(sess.run(w)) #    

次はこのウィジェットを見てみましょう
w = tf.Variable(10)
w.assign(100)
with tf.Session() as sess:
    sess.run(w.initializer)
    print(w.eval())
>> 10

この程度で10が得られるのは、assign操作を定義しているがtensorflowはsessionで操作を実行しているため、assign操作を実行する必要があるからである.
w = tf.Variable(10)
assign_op = w.assign(100)
with tf.Session() as sess:
    sess.run(w.initializer)
    sess.run(assign_op)
    print(w.eval())
>> 100

さらにtensorflowの各セッションは互いに独立しており,次の例を見ることができる.
W = tf.Variable(10)
sess1 = tf.Session()
sess2 = tf.Session()
sess1.run(W.initializer)
sess2.run(W.initializer)
print(sess1.run(W.assign_add(10))) # >> 20
print(sess2.run(W.assign_sub(2))) # >> 8
print(sess1.run(W.assign_add(100))) # >> 120
print(sess2.run(W.assign_sub(50))) # >> -42
sess1.close()
sess2.close()

変数に基づいて変数を定義することもできます
w = tf.Variable(tf.truncated_normal([700, 10]))
u = tf.Variable(w * 2)

プレースホルダ(Placeholders)
tensorflowには一般的に2つのステップがあり、第1のステップは定義図であり、第2のステップはsessionで図中の計算を行う.図の中で私たちがしばらく値を知らない量については、プレースホルダとして定義してから`feed_を使うことができます.dict`は値を割り当てます.
プレースホルダを定義する方法は簡単です
tf.placeholder(dtype, shape=None, name=None)

dtypeは指定しなければならないパラメータですが、shapeがNoneであれば、どんなサイズのtensorでも納得できることを説明し、shape=Noneを使うと簡単に良い図を定義できますが、debugの時には悪夢になるので、shapeを指定したほうがいいです.
以下の小さな例を示すことができます.
a = tf.placeholder(tf.float32, shape=[3])
b = tf.constant([5, 5, 5], tf.float32)
c = a + b
with tf.Session() as sess:
    print(sess.run(c, feed_dict={a: [1, 2, 3]}))

このほかtensorflowでの演算に対してfeed操作を行うこともでき、以下のようにする.
a = tf.add(2, 3)
b = tf.multiply(a, 3)
with tf.Session() as sess:
    print(sess.run(b, feed_dict={a: 2}))
>> 6

lazy loading
Lazy loadingとは、彼を使用しなければならないまで変数の作成を延期することです.一般的なloadingとlazy loadingの違いを見てみましょう.
# normal loading
x = tf.Variable(10, name='x')
y = tf.Variable(20, name='y')
z = tf.add(x, y)
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for _ in range(10):
        sess.run(z)

# lazy loading
x = tf.Variable(10, name='x')
y = tf.Variable(20, name='y')
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for _ in range(10):
        sess.run(tf.add(x, y))

normal loadingでは、xとyの変数が図に作成され、x+yの演算が作成されますが、lazy loadingではxとyの2つの変数しか作成されません.これはバグではありませんが、問題はどこにありますか?
normal loadingはsessionで何度x+yをしてもz定義の加算操作を実行するだけでよいが、lazy loadingはsessionでx+yを1回行うたびに図に加算操作を作成し、1000回x+yの演算を行うとnormal loadingの計算図には何の変化もなく、lazy loadingの計算図には1000ノード以上、各ノードはx+yの動作を表す.
見ましたか.これがlazy loadingによる問題で、図の読み込み速度に深刻な影響を及ぼします.