はじめに
Tensorflowではテンソルと呼ばれる量を扱うので、Numpyのメソッド等は使えません。そのためTensorflowに用意されているメソッドを用いる必要があります。
ここでは基本的な四則演算と行列演算についてまとめています。特にPythonで定義されている各種演算(+
, -
, /
, //
, %
)と比べています。
注意
- すべての演算をまとめているわけではないので、その他の演算については公式ドキュメントを参照ください。
- Tensorflowでは全てテンソルを扱うので、データの種類に言及するときは、テンソルを飛ばして「リストは〜」「ベクトルは〜」などと書いています。その点注意していただければと思います。
- 2018/01/31: 1月26日にTensorflow v1.5.0がリリースされました。このバージョンからeager executionというメソッドが実装され、Sesssion.run()
を実行しなくても計算が行えるようになりました。これについてのメモを記事の最後に追加したので、ご参照ください。
動作環境
Tensorflow 1.4.1
四則演算
足し算 tf.add
import tensorflow as tf
const1 = tf.constant(2)
const2 = tf.constant(3)
add_op = tf.add(const1, const2) # 2 + 3
with tf.Session() as sess:
result = sess.run(add_op)
print(result)
5
Python3の加算+
に相当する。
引き算 tf.subtract
import tensorflow as tf
const1 = tf.constant(2)
const2 = tf.constant(3)
subt_op = tf.subtract(const1, const2) # 2 - 3
with tf.Session() as sess:
result = sess.run(subt_op)
print(result)
-1
これは-
と同じもの。
割り算 - Python2 ver - tf.div
import tensorflow as tf
const1 = tf.constant(2)
const2 = tf.constant(3)
div2_op = tf.div(const1, const2) # 2 / 3 in Python2
with tf.Session() as sess:
result = sess.run(div_op)
print(result)
0
Python2での割り算/
に相当する。公式では、次のtf.divide
が推奨されている。
割り算 - Python3 ver - tf.divide
import tensorflow as tf
const1 = tf.constant(2)
const2 = tf.constant(3)
div_op = tf.divide(const1, const2) # 2 / 3 in Python3
with tf.Session() as sess:
result = sess.run(div_op)
print(result)
0.666666666667
Python3での/
に相当
整数除算 tf.floordiv
import tensorflow as tf
const1 = tf.constant(2)
const2 = tf.constant(3)
fdiv_op = tf.floordiv(const1, const2) # 2 // 3
with tf.Session() as sess:
result = sess.run(fdiv_op)
print(result)
0
Python3の//
に相当する。(小数点以下切り捨て)
剰余演算 tf.mod
import tensorflow as tf
const1 = tf.constant(2)
const2 = tf.constant(4)
mod_op = tf.mod(const1, const2) # 2 % 3
with tf.Session() as sess:
result = sess.run(mod_op)
print(result)
2
Python3の%
に相当する。
スカラー積 tf.scalar_mul
import tensorflow as tf
const1 = tf.constant(2) #定数を宣言(値は2)
const2 = tf.constant(3)
smul_op = tf.scalar_mul(const1, const2) # 2 * 3
with tf.Session() as sess:
result = sess.run(smul_op)
print(result)
6
定数同士の積。
ベクトル外積 tf.cross
import tensorflow as tf
const1 = tf.constant([1, 2, 3])
const2 = tf.constant([4, 5, 6])
cross_op = tf.cross(const1, const2) # [1, 2, 3] x [4, 5, 6]
with tf.Session() as sess:
result = sess.run(cross_op)
print(result)
[-3 6 -3]
ベクトル積(外積)についてはググれば定義が出てくるのでここでは省略します。
行列演算
要素が全て1の行列 tf.ones
import numpy as np
import tensorflow as tf
t = tf.ones([3, 2])
with tf.Session() as sess:
print("tf.ones([3, 2]) = %s" % sess.run(t))
tf.ones([3, 2]) = [[ 1. 1.]
[ 1. 1.]
[ 1. 1.]]
tf.ones([3,2])
: すべての要素が1の3x2行列を作成
要素がすべて0の行列 tf.zeros
import numpy as np
import tensorflow as tf
t = tf.zeros([5])
with tf.Session() as sess:
print("tf.zeros([5]) = %s" % sess.run(t))
tf.zeros([5]) = [ 0. 0. 0. 0. 0.]
tf.zeros([5])
: すべての要素が0の1x5行列(要素数5のベクトル)を作成
乱数を要素とする行列 tf.random_uniform
import numpy as np
import tensorflow as tf
t = tf.random_uniform([1, 3])
with tf.Session() as sess:
print("tf.random_uniform([1, 3]) = %s" % sess.run(t))
tf.random_uniform([1, 3]) = [[ 0.16699052 0.04628575 0.38685966]]
tf.random_uniform([1,3])
: 0から1までのランダムに生成された数を要素とする、1x3行列(要素数3のベクトル)を作成する。
指定された区間の要素数をリストとして出力 tf.linspace
import numpy as np
import tensorflow as tf
t = tf.linspace(1.0, 7.0, 4)
with tf.Session() as sess:
print("tf.linspace(1.0, 7.0, 4) = %s" % sess.run(t))
tf.linspace(1.0, 7.0, 4) = [ 1. 3. 5. 7.]
tf.linspace(1.0,7.0,4)
:1.0から4.0までを4つに区切って数を昇順に生成し、リスト(ベクトル)として出力する。
行列積
import tensorflow as tf
const1 = tf.random_uniform([3,2])
const2 = tf.random_uniform([2,3])
mul_op = tf.matmul(const1, const2)
with tf.Session() as sess:
print("const1: %s" % sess.run(const1))
print("const2: %s" % sess.run(const2))
print("tf.matmul(const1, const2) = %s" % sess.run(mul_op))
const1: [[ 0.22310185 0.76020801]
[ 0.04765964 0.81115341]
[ 0.15238702 0.24294829]]
const2: [[ 0.89871132 0.3882308 0.54530931]
[ 0.60662949 0.27270687 0.20178115]]
tf.matmul(const1, const2) = [[ 0.55778277 0.5268842 0.72335124]
[ 0.42495638 0.3350077 0.66840851]
[ 0.45947441 0.2069075 0.99706292]]
考える行列を$A_{ij}$, $B_{ij}$とする。AはNxM行列. BはKxL行列とする。このとき、積を行うには、
-
tf.matmul(A,B)
が可能であるためには M=K -
tf.matmul(B,A)
が可能であるためには L=N
が成り立つ必要がある。(つまり一つ目の行列の列と、2つめの行列の行の要素数が一致しないといけない。) これを疎かにするとエラーが多発するので注意する。特に行列を転地するにはtf.transpose
を使うか、tf.matmul
のオプションで転置をTrue
にすればいい。このあたりは公式ドキュメントを参照すること。
Numpyリストをテンソルに変換 tf.convert_to_tensor
import numpy as np
import tensorflow as tf
t = tf.convert_to_tensor(np.linspace(1, 7, 4))
with tf.Session() as sess:
print("tf.convert_to_tensor( np.linspace(1, 7, 4) ) = %s" % sess.run(t))
tf.convert_to_tensor( np.linspace(1, 7, 4) ) = [ 1. 3. 5. 7.]
tf.convert_to_tensor
: 生成されたNumpyリストをテンソルに変換する。
その他
値の代入
import tensorflow as tf
# see https://www.tensorflow.org/api_guides/python/state_ops
print("\n変数\n=====================")
w = tf.Variable(tf.zeros([3, 2])) #変数(行列)wの宣言. 初期値はゼロ行列
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print("w = %s" % sess.run(w))
sess.run(tf.assign(w, tf.ones([3, 2])))
wn = sess.run(w)
print("w = %s" % wn)
変数
=====================
w = [[ 0. 0.]
[ 0. 0.]
[ 0. 0.]]
w = [[ 1. 1.]
[ 1. 1.]
[ 1. 1.]]
-
tf.assign(w, tf.ones([3, 2])
: 変数w
にtf.ones([3,2])
(要素がすべて1の3x2行列を代入する.
この演算は行列だけに限らない。(スカラー変数にも可能)
シンボリック演算
import tensorflow as tf
print("\nシンボリック変数\n=====================")
a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
a_times_b1 = tf.multiply(a, b) # multiplication of a and b
a_times_b2 = a * b
with tf.Session() as sess:
# where "name" is the python symbol
print("%f should equal 2.0" % sess.run(a_times_b1, feed_dict={a: 1, b: 2}))
print("%f should equal 9.0" % sess.run(a_times_b1, feed_dict={a: 3, b: 3}))
print("%f should equal 9.0" % sess.run(a_times_b2, feed_dict={a: 3, b: 3}))
シンボリック変数
=====================
2.000000 should equal 2.0
9.000000 should equal 9.0
9.000000 should equal 9.0
一つだけの値を固定せずに、いくつかの値をfeed_dict
を用いて後から代入する。
各種関数
import tensorflow as tf
print("\n数学関数\n=====================")
x = tf.linspace(0., 4., 5)
with tf.Session() as sess:
print("x = %s" % sess.run(x))
print("(x+1)**2 - 2) = %s" % sess.run( (x+1)**2 - 2))
print("sin(x) = %s" % sess.run( tf.sin(x) ))
print("sum(x) = %s" % sess.run( tf.reduce_sum(x) ))
数学関数
=====================
x = [ 0. 1. 2. 3. 4.]
(x+1)**2 - 2) = [ -1. 2. 7. 14. 23.]
sin(x) = [ 0. 0.84147096 0.90929741 0.14112 -0.7568025 ]
sum(x) = 10.0
詳しくは公式ドキュメント参照
変数としてリストを取る
これらの関数は変数としてリストを取れる:
print("\n引数にベクトル(シーケンス, リスト)を取れる。 (Numpyライク)\n=====================")
tf.sin(3.)
tf.sin([1., 2., 3.])
tf.sin(tf.linspace(0., 10., 20))
tf.sin(np.linspace(0, 10, 20)) # equivalent
tf.sin(tf.ones(shape=(2, 3, 4))) # 2x3x4 tensor
# Operators (+, -, /, *)
a = tf.zeros(shape=(2, 3))
b = tf.ones(shape=(2, 3))
c = tf.ones(shape=(3, 2))
with tf.Session() as sess:
print('a + b: %s'% sess.run(a + b)) # same as tf.add(a, b)
print('a - b: %s' % sess.run(a - b)) # same as tf.subtract(a, b)
print('a * b: %s' % sess.run(a * b)) # same as tf.mul(a, b)
print('a / b: %s' % sess.run(a / b)) # same as tf.division(a, b)
# a + c # doesn't work; tensors need to be of same shape
引数にベクトル(シーケンス, リスト)を取れる。 (Numpyライク)
=====================
a + b: [[ 1. 1. 1.]
[ 1. 1. 1.]]
a - b: [[-1. -1. -1.]
[-1. -1. -1.]]
a * b: [[ 0. 0. 0.]
[ 0. 0. 0.]]
a / b: [[ 0. 0. 0.]
[ 0. 0. 0.]]
Eager executionについて
上で扱った内容のいくつかを例として、Eager executionの実行例を与えてみます。
例1: 加算
加算のコードを書き換えてみると、
import tensorflow as tf
import tensorflow.contrib.eager as tfe
tfe.enable_eager_execution()
const1 = tf.constant(2)
const2 = tf.constant(3)
add_op = tf.add(const1, const2) # 2 + 3
print(add_op)
# tf.Tensor(5, shape=(), dtype=int32)
となります。注意点としてはまず、tfe.enable_eager_execution()
は必ずプログラムの最初に書くようにします。 (Jupyter上で実行する際は、カーネルにメモリーが残っていると
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-2-a35e1dbe978d> in <module>()
2 import tensorflow.contrib.eager as tfe
3
----> 4 tfe.enable_eager_execution()
5
6 const1 = tf.constant(2)
/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/ops.py in enable_eager_execution(config, device_policy)
4892 else:
4893 raise ValueError(
-> 4894 "tfe.enable_eager_execution has to be called at program startup.")
4895
4896
ValueError: tfe.enable_eager_execution has to be called at program startup.
というエラーが出るので(例)、カーネル再起動は必須です。ちなみに出力結果の型は
type(add_op)
# EagerTensor
となっています。ためしにこの値に3
をたしてみると、
add_op + 3
# <tf.Tensor: id=5, shape=(), dtype=int32, numpy=8>
となり、numpyの値としては正しく計算されています。この値を取り出すにはnumpy()
メソッドを使います。つまり
add_op2 = add_op + 3
print(add_op2.numpy())
# 8
とすることで、値を取り出せます。この値の型は
type(add_op2)
# numpy.int32
となっているので、通常の四則演算が可能になっています。
例2: 値の代入
同様にして、値の代入のコードを書き換えてみると
import tensorflow as tf
import tensorflow.contrib.eager as tfe
tfe.enable_eager_execution()
# see https://www.tensorflow.org/api_guides/python/state_ops
print("\n変数\n=====================")
w = tfe.Variable(tf.zeros([3, 2])) #変数(行列)wの宣言. 初期値はゼロ行列
tf.global_variables_initializer()
print("w = %s" % w)
tf.assign(w, tf.ones([3, 2]))
wn = w
print("w = %s" % wn)
# 変数
# =====================
# w = <tf.Variable 'Variable:0' shape=(3, 2) dtype=float32, numpy=
# array([[0., 0.],
# [0., 0.],
# [0., 0.]], dtype=float32)>
# w = <tf.Variable 'Variable:0' shape=(3, 2) dtype=float32, numpy=
# array([[1., 1.],
# [1., 1.],
# [1., 1.]], dtype=float32)>
となります。ここで変数を宣言するときにtfe.Variable
を使うことに注意します。(余談ですが、eager executionを使うときはtf.Placeholderは使えません。) それ以外はwith
文を全部取り除くことで、同様に書き換えることができます。値を取り出すにはさきほどしたように
print(w.numpy()
# array([[1., 1.],
# [1., 1.],
# [1., 1.]], dtype=float32)
(wn
も同様)とすれば、値を取り出すことができます。先程の例1でやったように、numpy()
メソッドを使えば、Numpy arraytとして取り出し、Numpyの四則演算を行うことができます。