티스토리 뷰

3차원 이상의 텐서 사이의 행렬 곱 - 텐서플로우

3차원 텐서 사이의 행렬 곱

텐서플로우를 처음 접하고 텐서플로우 코드를 보다가 아래 예시 코드처럼 3차원 텐서 사이에서 행렬 곱(tf.matmul)을 하는 코드를 만났습니다. 행렬 곱은 2차원에서만 정의되는 줄 알고 있었는데 3차원 텐서에서도 어떻게 행렬 곱(tf.matmul)함수가 사용 가능한 건지 의문이 들었습니다.

A = tf.Variable(tf.random_normal([2, 2, 3]))
B = tf.Variable(tf.random_normal([2, 3, 7]))
C = tf.matmul(A, B)

텐서플로우에서 텐서는 다차원 행렬, 코드상에서는 다차원 배열을 나타냅니다. 1차원 텐서는 벡터이고 코드 상에서 [1, 2, 3]과 같은 1차원 배열입니다. 2차원 텐서는 우리가 잘 알고 있는 행렬이며 코드상에서 [[1, 2 ,3], [4, 5, 6]]과 같은 2차원 배열입니다. 3차원 텐서는 행렬을 여러 층 쌓은 것이고 코드상에서 [[[1, 2] ,[3, 4]], [[4, 5], [6, 7]]]와 같은 3차원 배열입니다.

위 코드를 아래와 같이 실행해보니 오류 없이 잘 실행됐고 C의 차원으로 2x2x7을 얻었습니다.

sess = tf.Session()
sess.run(tf.global_variables_initializer())
C = sess.run(C)
print(C.shape) # C의 차원 출력

어떻게 작동하는걸까?

행렬 곱은 2차원에서만 정의되는데 어떻게 3차원 텐서에서 행렬 곱(tf.matmul)을 사용할 수 있을까요?

알아보니 두 개의 3차원 텐서 사이의 행렬 곱(tf.matmul)은 단순히 아래 그림1처럼 2차원 행렬을 여러 층으로 쌓은 3차원 텐서에서 각 층 사이의 2차원 행렬 간의 곱을 리턴합니다.

@그림1. 3차원 텐서 사이의 행렬 곱 예시 |center|500x0

그림1. 3차원 텐서 사이의 행렬 곱 예시

따라서 3차원 텐서 사이의 행렬 곱(tf.matmul)을 이용하면 아래 코드와 같이 2차원 행렬 곱 두 개를 더 간편하게 나타낼 수 있습니다.

A0 = tf.Variable(tf.random_normal([2, 3]))
A1 = tf.Variable(tf.random_normal([2, 3]))
B0 = tf.Variable(tf.random_normal([3, 7]))
B1 = tf.Variable(tf.random_normal([3, 7]))
# 2차원 행렬 곱
C0 = tf.matmul(A0, B0)
C1 = tf.matmul(A1, B1)
# 3차원 텐서의 행렬 곱으로 나타내면
A = tf.stack([A0, A1]) # shape: 2x2x3
B = tf.stack([B0, B1]) # shape: 2x3x7
C = tf.matmul(A, B) # shape: 2x2x7

텐서플로우를 돌릴 때 보통 N개의 입력으로 구성된 배치(Batch)를 만들어서 런합니다. 이 때 N개의 행렬을 곱하는 상황이 빈번한데 이를 한 줄로 간편하게 하기 위해 3차원 텐서 사이의 행렬 곱 함수(tf.matmul)가 이렇게 작동하는 것입니다.


5차원 텐서 사이의 행렬 곱

그러면 아래와 같이 5차원 텐서 사이의 행렬 곱(tf.matmul)도 작동할까요?

A = tf.Variable(tf.random_normal([5, 4, 10, 2, 3]))
B = tf.Variable(tf.random_normal([5, 4, 10, 3, 7]))
C = tf.matmul(A, B)

가능합니다! 위 코드를 아래와 같이 실행해보면 오류 없이 잘 실행되고 C의 차원으로 5x4x10x2x7을 얻었습니다.

이를 통해 3차원 이상의 텐서 사이의 행렬 곱은 행렬의 차원을 나타내는 마지막 두 개의 차원(2x3, 3x7) 사이에 행렬 곱이 가능하고 행렬 앞에 있는 차원(5x4x10)이 같으면 가능한 것을 알 수 있습니다.

댓글
댓글쓰기 폼