[tensorflow] tf.math.add_n, tf.math.reduce_mean, tf.cinsum
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]
이런식으로 구현된다고 생각하면된다.