오늘/오늘의 함수

[tensorflow] tf.math.add_n, tf.math.reduce_mean, tf.cinsum

hwijin97 2021. 12. 9. 21:39

tf.math.add_n

Params :

inputs : list of Tensor  or  tf.IndexedSlices

name : name for operation (optional)

Returns :

tensor_same_shape_with_input_element

 

설명 :

shape이 동일한 텐서 리스트를 받아서 원소별 덧셈을 수행한다. shape 이 동일하지 않거나 dtype이 다르면 ValueError

name은 에러발생시 쉽게 찾기위해서 이 특정 연산의 이름을 지정한다.

a = tf.constant([[3, 5], [4, 8]])
b = tf.constant([[1, 6], [2, 8]])
c = tf.math.add_n([a, b], name = "operation_name")
print(a)
print(b)
print(c)
'''
tf.Tensor(
[[3 5]
 [4 8]], shape=(2, 2), dtype=int32)
tf.Tensor(
[[1 6]
 [2 8]], shape=(2, 2), dtype=int32)
tf.Tensor(
[[ 4 11]
 [ 6 16]], shape=(2, 2), dtype=int32)
 '''

 

tf.math.reduce_mean

Params :

input_tensor : tensor to reduce, numeric type

axis = None : dimensions to reduce, [ - rank(input_tensor) , rank(input_tensor ] 

keepdims = False :  if True , retain dimention with length 1

name = None :  name for operation

Returns:

reduced_tensor

 

설명 :

입력으로 받은 input_tensor를 axis축을 기준으로 평균한다. 

axis=None 이면 모든 축에 관해서 평균해서 상수가된다.

keepdims는 평균하는 축을 놔둘지 말지를 결정한다 False이면 축이 삭제되고, True이면 1로 유지된다.

x = tf.constant([[[1., 2., 3., 4.],
                  [3., 4., 5., 6.],
                  [3., 4., 5., 6.]],
                 [[5., 2., 3., 4.],
                  [3., 2., 5., 6.],
                  [1., 0., 1., 2.]]])
print(tf.shape(x))
print(tf.reduce_mean(x))
print(tf.reduce_mean(x, axis=[0, 1]))
print(tf.reduce_mean(x, keepdims=True))
'''
tf.Tensor([2 3 4], shape=(3,), dtype=int32)
tf.Tensor(3.3333333, shape=(), dtype=float32)
tf.Tensor([2.6666667 2.3333333 3.6666667 4.6666665], shape=(4,), dtype=float32)
tf.Tensor([[[3.3333333]]], shape=(1, 1, 1), dtype=float32)
'''

 

 

tf.einsum, tf.linalg.einsum

Params :

equation : string, describing the contraction

*inputs : tensors to contract, shapes should be consistent with equation

**kwargs :  optimize : Optimization strategy , 'greedy', 'optimal', 'branch-2', 'branch-all', 'auto' (default : "greedy"),                            name : name for operation

 

Returns : 

contracted tensor, shape defined by equation

 

설명 :

einstein notaion을 참조함

equation에 묘사된 수식을 기반으로 행렬을 계산한다.

", " 는 곱을의미 -> 는 = 을 의미, 곱 사이의 sum이 생략되어있음, 출력 indices는 생략 가능하다. 

#ex 1
m0 = tf.random.normal(shape=[2, 3])
m1 = tf.random.normal(shape=[3, 5])
e = tf.einsum('ij,jk->ik', m0, m1)
#output[i, k] = sum_j m0[i, j] * m1[j, k]
print(e.shape)
#(2, 5)
e = tf.einsum('ij,jk', m0, m1)  # output[i,k] = sum_j m0[i,j] * m1[j, k]
print(e.shape)
#(2, 5)

위는 두 행렬의 곱을 표현한다.

 

#ex 2
u = tf.random.normal(shape=[3, 3])
v = tf.random.normal(shape=[3, 5])
e = tf.einsum('bi,bj->bij', u, v)  # output[b,i,j] = u[b,i]*v[b,j]
print(e.shape)
#(3, 3, 5)

두행렬의 외적을 의미한다.

 

활용 : 

Feature Map의 gram_matrix를 구하기위해, einsum을 활용하여 구할 수 있다.

gram_matrix : 각각의 특성맵들의 내적과 그들을 평균해서 구할 수 있다.

#ex 3
#filter_maps.shape = (batch_size, height, width, channel)
dot_product_with_filter_maps = tf.linalg.einsum('bijc,bijd->bcd', filter_maps, filter_maps)
filter_map_shape = tf.shape(filter_maps)
num_locations = tf.cast(height*width, tf.float32)
gram_matrix = result/(num_locations)

여기서 bijc, bijd -> bcd는 각 filter map의  height, width를 돌면서 곱의 합을 구한다.

for b in range(batch_size):
    for i in range(height):
        for j in range(width):
            for c in range(channel):
                for d in range(channel):
					results[b, c, d] += filter_maps[b, i, j, c] * filter_maps[b, j, j, d]

이런식으로 구현된다고 생각하면된다.