예전에 텐서플로우 라이브러리를 공부하면서 '텐서란 무엇인가?'에 대한 글을 썼던 적이 있다. 

그때는 1차는 스칼라, 2차는 벡터, 3차부터 텐서라고 설명했는데 1,2차의 경우 행렬이라는 개념으로 중,고등학교에서 배우기 때문에 쉽게 이해할 수 있지만 3차 이상인 텐서의 경우 솔직히 개념적인 설명만으로 알기 힘들다고 생각한다.

오늘 우연찮게 numpy구조와 axis 파라미터에 대해서 공부하던 중, 텐서를 설명할 좋은 자료가 생겨서 이렇게 포스팅을 하게 되었다.


위에도 적어놨지만 텐서란 데이터가 3차 이상으로 들어있는 것을 말한다. 2차 행렬까지는 쉽게 이해했을지라도 3차는 어떻게 생겼는지 알기 힘든 게 사실이다. 이걸 이해하기 위해서는 3차 데이터 구조를 알아야 하는데 3차 데이터 구조 또한 이해하기 힘들다.

그럼 알기 쉽게 시각화를 해보자.



================================ Python ================================

import numpy as np


arr = np.arange(0, 32)

print(len(arr))  # 결과는 32.

print(arr)

'''

'결과'

array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,

       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31])

'''

v = arr.reshape([4,2,4])

================================ Python ================================


위의 데이터는 numpy의 reshape 메서드를 이용한 텐서 만들기이다.

자 저 마지막에 나와있는 v는 (4, 2, 4)의 3차원 행렬인 텐서이다.

저게 어떻게 생겼냐면 아래 처럼 생겼다.


fig 1. (4, 2, 4) 텐서



 텐서는 3차원 리스트이다. 저게 3차원인 이유를 직관적으로 생각해보자면 텐서의 원소가 [[[ 세번을 지나 처음으로 등장하기 때문이다. 

이론적으로 설명하자면 
row라는 x축  /  column이라는 y축  /  depth라는 z축
으로 데이터가 표현되었기 때문이다.

그럼 각각의 축을 어떻게 이해 해야 하는지 알아보자.



fig 2. 3차원 텐서를 설명하는 축



fig 1에서 각 row, column, depth를 fig 2에 맞춰서 놓는다면 이제 대충 어떻게 생겼는지 알 수 있을 것이다.

4개의 row가 존재하고 그 row는 2개의 column을 갖고 뒤로 4개의 depth를 갖는 형태를 상상해보자.

상상하기 어려운 사람은 아래 그림을 보자.


fig 3. (4, 2, 4) 텐서의 형태


이것도 이해하기 난해하다면 아래를 보자.

일단 depth는 고려하지 말고 각 depth의 제일 앞의 값인 0,4,8,12,16,20,24,28만 생각해보자.



=========================== Tensor ===========================

[

    [

        [0],[4]

    ],

    [

        [8],[12]

    ],

    [

        [16],[20]

    ],

    [

        [24],[28]

    ]

]

=========================== Tensor ===========================


각 원소는 1개의 row에 2개의 column을 형성해야 한다. 그리고 앞에 나온 것은 뒤에 나온 것보다 더 작은 column값을 가져야 한다. 즉 1번 row에 0,4가 들어가고 2번 row에 8,12, 3번 row에 16,20, 4번 row에 24,28이 들어가야 한다는 말이다. 거기에 0이 4보다 먼저, 8이 12보다 먼저, 16이 20보다 먼저, 24가 28보다 먼저 등장해야 한다.

이는 (4, 2, 1)텐서라고 할 수 있다. 그런데 z = 1이므로 2차원으로만 보자면 (4, 2) 행렬이라고도 볼 수 있다.


fig 4. (4, 2, 1) 텐서 = (4, 2) 행렬


 

 1번 column

2번 column

 1번 row

0

 2번 row

8

12 

 3번 row

 16

20 

 4번 row

 24

28 


위의 표는 fig 4를 표로 바꿔본 것이다. 통상의 경우 가로를 행 또는 row, 세로를 열 또는 column이라고 부르기 때문에 위와 같이 썼다.


자 그럼 다시 fig 1로 돌아가 column과 depth만 선택해보자.


================================ Tensor ================================

[    

    [

        [0, 1, 2, 3], [4, 5, 6, 7]

    ]

]

================================ Tensor ================================


이게 왜 이렇게 선택되었는지 잘 모를수도 있다. 이는 fig 3을 좌측면에서 살펴본 형태를 표현한 것이다.

이건 (1, 2, 4)의 텐서이므로 x를 생략하면 (2, 4) 행렬이 된다.

이걸 2차원 그래프로 표현해보면 아래와 같다.


fig 5. (1, 2, 4)텐서 = (2, 4) 행렬


 

 1번 depth

2번 depth 

3번 depth

4번 depth

 1번 column

 0

 2번 column

 4



fig3은 fig 4와 fig 5를 하나로 표현한 형태이다. 자 이제 fig 3의 형태가 눈에 들어올 것이다. fig 3은 정면에서 보면 xy축만 보이고 좌측에서 보면 yz축만 보인다. 만약 위에서 본 시점을 상상할 수 있다면 xz축으로 이루어진 데이터를 볼 수 있을 것이다. 이제 입체 구조를 생각하면서 fig 1을 보면 이해가 쉽게 될 것이다. 텐서를 담고있는 첫번째 대괄호는 row, 두번째 대괄호는 column, 마지막으로 각 원소들이 줄지어진 모습이 depth이다.

텐서는 3차원 이상의 데이터 구조이다. 때문에 많은 정보를 담을 수 있다는 장점이 있다. 하지만 데이터를 해석하는데 있어 많은 상상력이 필요하기 때문에 이해하기가 어렵다. 하지만 자유자재로 데이터 구조를 가공하여 필요한 정보를 손쉽게 얻기 위해 꼭 이해해보도록 하자.


ref.
TAEWON.KIM 블로그 / Numpy에서 np.sum 함수의 axis 이해
http://taewan.kim/post/numpy_sum_axis/











+ Recent posts