post Image
Tensorflowにおける各種演算まとめ


はじめに

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の3×2行列を作成


要素がすべて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の1×5行列(要素数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までのランダムに生成された数を要素とする、1×3行列(要素数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]): 変数wtf.ones([3,2])(要素がすべて1の3×2行列を代入する.

この演算は行列だけに限らない。(スカラー変数にも可能)


シンボリック演算



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を用いて後から代入する。

参考: ポテチ製造から学ぶTensorflowの考え方


各種関数



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の四則演算を行うことができます。


『 Python 』Article List