tensorflowの初歩の初歩

tensorのshape/dimension

一般的には m行n列の行列は m×n行列 と表記すると思うけど

m = tf.Variable([2,3])

とかしたときは2行3列なのか??とかちゃんとわかってないので確認したい

constantで確認する

In [12]: c1 = tf.constant([[1,2,3], [2,3,4]])

In [13]: c2 = tf.constant([[2,2], [3,3], [4,4]])

In [14]: sess.run(tf.matmul(c1, c2))
Out[14]: 
array([[20, 20],
       [29, 29]], dtype=int32)

In [15]: sess.run(tf.matmul(c2, c1))
Out[15]: 
array([[ 6, 10, 14],
       [ 9, 15, 21],
       [12, 20, 28]], dtype=int32)

In [16]: c1.shape
Out[16]: TensorShape([Dimension(2), Dimension(3)])

In [17]: c2.shape
Out[17]: TensorShape([Dimension(3), Dimension(2)])

ということで、constantでは shape(2, 3) は 2行3列 の行列を表すっぽい

では、縦ベクトル、横ベクトルはどうか?

In [18]: v1 = tf.constant([1,2,3])

In [19]: v2 = tf.constant([[2],[2],[2]])

In [21]: sess.run(tf.matmul(v1, v2))

...(略)
~/dev/tf-train/tf-env/lib/python3.6/site-packages/tensorflow/python/framework/common_shapes.py in _call_cpp_shape_fn_impl(op, input_tensors_needed, input_tensors_as_shapes_needed, require_shape_fn)
    689       missing_shape_fn = True
    690     else:
--> 691       raise ValueError(err.message)
    692 
    693   if missing_shape_fn:

ValueError: Shape must be rank 2 but is rank 1 for 'MatMul_2' (op: 'MatMul') with input shapes: [3], [3,1].

... rank が 2じゃなきゃいけないらしい

In [23]: v1.shape
Out[23]: TensorShape([Dimension(3)])

In [24]: v2.shape
Out[24]: TensorShape([Dimension(3), Dimension(1)])

https://www.tensorflow.org/programmers_guide/tensors

rank は 0がscalar, 1がvector, 2がmatrix らしい

逆に、縦ベクトルも横ベクトルも[1,2,3]みたいに書くべきなのか?

In [25]: v1 = tf.constant([1,2,3])

In [26]: v2 = tf.constant([2,2,2])

In [27]: sess.run(tf.matmul(v1, v2))
...(略)

~/dev/tf-train/tf-env/lib/python3.6/site-packages/tensorflow/python/framework/common_shapes.py in _call_cpp_shape_fn_impl(op, input_tensors_needed, input_tensors_as_shapes_needed, require_shape_fn)
    689       missing_shape_fn = True
    690     else:
--> 691       raise ValueError(err.message)
    692 
    693   if missing_shape_fn:

ValueError: Shape must be rank 2 but is rank 1 for 'MatMul_6' (op: 'MatMul') with input shapes: [3], [3].

やっぱりだめ 内積を計算したければ、ベクトルであっても1×n と n×1 の行列で表さなければならないみたい

In [31]: v1 = tf.constant([[1,2,3]])

In [32]: v2 = tf.constant([[2],[2],[2]])

In [33]: sess.run(tf.matmul(v1, v2))
Out[33]: array([[12]], dtype=int32)

In [34]: v1.shape
Out[34]: TensorShape([Dimension(1), Dimension(3)])

In [35]: v2.shape
Out[35]: TensorShape([Dimension(3), Dimension(1)])
shape part2

触りだしたらやっぱり理解があやふやだったので、再確認

shape [1,2,3] と shape [3,2,1] はどう違うのか?

左からi番目は外側からi番目の[]に入ってる要素の数、みたいに考えれば良さそう

In [12]: tf.constant([  [ [1,1,1], [2,2,2] ] ])
Out[12]: <tf.Tensor 'Const_4:0' shape=(1, 2, 3) dtype=int32>

shape [1, ...] なので 一番外側のに入っている要素は1つ

-> [ [...] ]

shape [1, 2, ...] なので 次のに入っている要素は2つ

-> [ [ [...], [...] ] ]

shape [1, 2, 3] なので 次の[]に入っている要素は3つ

-> [ [ [1,1,1], [2,2,2] ] ]

みたいな

逆に shape [3,2,1] なら

[ [...], [...], [...] ]

  • > [ [ [...], [...] ], [ [...], [...] ], [ [...], [...] ] ]
  • > [ [ [1], [2] ], [ [5], [6] ], [ [9], [0] ] ]

みたいな


あと c[1, :, 1] みたいな ':' をつかった操作もあんまり自信がないので確認

In [26]: c1 = tf.constant([[ [1,3,5], [2,4,6] ]])

In [27]: c2 = tf.constant([ [[1], [2]], [[5], [6]], [[9], [0]] ])

c1[0, :, 1] だと [ [3], [4] ]

c2[:, 1, :] だと [ [2], [6], [0] ]

c2[:, 1, 0] だと [2, 6, 0]

となるみたい

In [28]: sess.run(c1[0,:,1])
Out[28]: array([3, 4], dtype=int32)

In [29]: sess.run(c2[:,1,:])
Out[29]: 
array([[2],
       [6],
       [0]], dtype=int32)

In [30]: sess.run(c2[:,1,0])
Out[30]: array([2, 6, 0], dtype=int32)
scope

サンプルとか見ると

with tf.variable_scope("conv1"):
    ....

とかあるけどこれは何???

https://www.tensorflow.org/programmers_guide/variables

を読むと、同じ名前でget_variableを複数回呼ぶと変数を再利用するのか新規に作るのか判別できないけど、variable_scopeで区切っておけば別のvariable_scope内の変数は再利用しない、みたいなことらしい

In [37]: v1 = tf.get_variable('the_var', [2,3])

In [38]: v2 = tf.get_variable('the_var', [2,3])
... 略
ValueError: Variable the_var already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope? Originally defined at:

  File "<ipython-input-37-ce1950cb36a3>", line 1, in <module>
    v1 = tf.get_variable('the_var', [2,3])
  File "/home/shuhei/dev/tf-train/tf-env/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 2910, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "/home/shuhei/dev/tf-train/tf-env/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 2850, in run_ast_nodes
    if self.run_code(code, result):

やはり同名の変数を get_value しようとすると "Variable the_var already exists,"のエラーが起こるらしい
(reuse=Trueとかすれば再利用できるらしい)

これを、variable_scopeで囲っておくと別のスコープで定義された変数は無視して新しく作ってくれるらしい

In [39]: with tf.variable_scope('scope1'):
    ...:     v1 = tf.get_variable('scoped_var', [1,2])
    ...:     

In [40]: with tf.variable_scope('scope2'):
    ...:     v2 = tf.get_variable('scoped_var', [1,2])
    ...:     

In [41]: v1.name
Out[41]: 'scope1/scoped_var:0'

In [42]: v2.name
Out[42]: 'scope2/scoped_var:0'