Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

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]): 変数wtf.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を用いて後から代入する。

参考: ポテチ製造から学ぶ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の四則演算を行うことができます。

hiroyuki827
SDET 興味ある言語: Python, JavaScript その他興味: メインフレーム, Zowe, VSCode Plugin Development Certified Jenkins Engineer取得 *おことわり* Qiitaでの投稿内容は私自身の見解であり、所属会社の立場、戦略、意見を代表するものではありません。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした