Tensor
텐서(Tensor)는 matrix을 표현하는 자료형으로, NumPy의 Array와 동일하게 multidimensional matrix를 표현하는 것이다. 다만, tensor는 array보다 gpu 사용, 자동 미분 등의 기능이 추가된 것이라고 생각하면 된다. 이때, Pandas의 dataframe과 동일하지 않나 생각을 할 수 있으나, pandas의 dataframe은 multidimensional matrix를 표현하는 것이 아닌, 2-dimensional table, 일종의 spreadsheet로 단순한 table 형태의 자료형이라고 생각하면 된다.
구분 |
Pytorch Tensor |
NumPy Array |
Pandas Dataframe |
Dimension |
Multidimension |
Multidimension |
2-dimension |
GPU 가속 |
O |
X |
X |
자동미분 |
O |
X |
X |
Data Type |
Number |
Number |
Number, Char etc. |
1
2
3
4
5
6
7
8
|
import numpy as np
import torch
a = [1, 2, 3]
B = [[1, 2, 3], [4, 5, 6]]
a_t = torch.tensor(a)
B_t = torch.tensor(B)
|
이 경우, a는 다음과 같이 출력이 되며, 행렬료 표현하면 (1)과 같다.
tensor([1, 2, 3])
\[\mathbf{a}_t=\begin{pmatrix}1&2&3\end{pmatrix}\tag{1}\]
2-dimensional matrix를 만들어보면 다음과 같이 할 수 있다.
tensor([[1, 2, 3],
[4, 5, 6]])
\[\mathbf{B}_t=\begin{pmatrix}1&2&3\\4&5&6\\\end{pmatrix}\tag{2}\]
Tensor 생성
영행렬 생성
직접 차원 설정해서 생성
1
2
|
O_t = torch.zeros(2, 3)
O_t
|
tensor([[0., 0., 0.],
[0., 0., 0.]])
\[\mathbf{O}_t=\begin{pmatrix}0&0&0\\0&0&0\\\end{pmatrix}\tag{3}\]
다른 tensor 속성 불러와서 생성
1
2
|
O_t = torch.zeros_like(B_t_T)
O_t
|
tensor([[0, 0],
[0, 0],
[0, 0]])
\[\mathbf{O}_t=\begin{pmatrix}0&0\\0&0\\0&0\\\end{pmatrix}\tag{4}\]
원소가 모두 1인 행렬 생성
직접 차원 설정해서 생성
1
2
|
J_t = torch.ones(2, 3)
J_t
|
tensor([[1., 1., 1.],
[1., 1., 1.]])
\[\mathbf{J}_t=\begin{pmatrix}1&1&1\\1&1&1\\\end{pmatrix}\tag{5}\]
다른 tensor 속성 불러와서 생성
1
2
|
J_t = torch.ones_like(B_t_T)
J_t
|
tensor([[1, 1],
[1, 1],
[1, 1]])
\(\mathbf{J}_t=\begin{pmatrix}1&1\\1&1\\1&1\\\end{pmatrix}\tag{6}\)
랜덤 상수 행렬 생성
직접 차원 설정해서 생성
1
2
|
C_t = torch.rand(2, 3)
C_t
|
tensor([[0.1483, 0.6737, 0.5585],
[0.4265, 0.9422, 0.9804]])
\[\mathbf{C}_t=\begin{pmatrix}0.1483&0.6737&0.5585\\0.4265&0.9422&0.9804\\\end{pmatrix}\tag{7}\]
다른 tensor 속성 불러와서 생성
아래와 같은 경우 에러가 발생하게 된다. _like method는 자료형을 따로 설정하지 않는다면 다른 tensor에서 속성(차원, 자료형)을 그대로 가져와서 만들게 되는데 불러온 다른 tensor는 자료형이 long, 즉 정수형이다. 그런데 앞에서 봤듯이 .rand() method는 float 형태로 만들기에 자료형이 달라 생성을 할 수 없다. 이러한 경우, 별도로 자료형을 설정해줘야 한다.
1
2
|
C_t = torch.rand_like(B_t_T)
C_t
|
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
Cell In[28], line 1
----> 1 C_t = torch.rand_like(B_t_T)
RuntimeError: "check_uniform_bounds" not implemented for 'Long'
아래와 같이 명시적으로 자료형을 설정해준 경우, 제대로 출력된다.
1
2
|
C_t = torch.rand_like(B_t_T, dtype=torch.float)
C_t
|
tensor([[0.1342, 0.1410],
[0.5062, 0.1640],
[0.8247, 0.4431]])
\[\mathbf{C}_t=\begin{pmatrix}0.1342&0.1410\\0.5062&0.1640\\0.8247&0.4431\\\end{pmatrix}\tag{8}\]
Tensor 차원 변수 설정 후 생성하기
Tensor는 multidimenion을 지원하기에, 단순 2 dimension (1, 2)와 같이 생성할 수도 있으나, 더 많은 dimension (1, 2, 3, 4, …)을 생성할 수도 있다.
1
2
3
|
shape = (3, 2, 1)
O_t = torch.zeros(shape)
O_t
|
tensor([[[0.],
[0.]],
[[0.],
[0.]],
[[0.],
[0.]]])
\[\mathbf{O}_{t}=\begin{pmatrix}\begin{pmatrix}0\\0\\\end{pmatrix}&\begin{pmatrix}0\\0\\\end{pmatrix}&\begin{pmatrix}0\\0\\\end{pmatrix}\end{pmatrix}\tag{9}\]
전치 행렬
tensor([[1, 4],
[2, 5],
[3, 6]])
\[\mathbf{B}_t^T=\begin{pmatrix}1&2&3\\4&5&6\\\end{pmatrix}^T=\begin{pmatrix}1&4\\2&5\\3&6\\\end{pmatrix}\tag{2}\]
Tensor 기본 연산
행렬의 합
tensor([[ 2, 4, 6],
[ 8, 10, 12]])
1
2
|
C_t = B_t.add(B_t)
C_t
|
tensor([[ 2, 4, 6],
[ 8, 10, 12]])
1
2
|
torch.add(B_t, B_t, out=C_t)
C_t
|
tensor([[ 2, 4, 6],
[ 8, 10, 12]])
\[\mathbf{B}_t+\mathbf{B}_t=\begin{pmatrix}1&2&3\\4&5&6\\\end{pmatrix}+\begin{pmatrix}1&2&3\\4&5&6\\\end{pmatrix}=\begin{pmatrix}2&4&6\\8&10&12\\\end{pmatrix}\]
행렬의 차
1
2
3
|
J_t = torch.ones_like(B_t)
C_t = B_t-J_t
C_t
|
tensor([[0, 1, 2],
[3, 4, 5]])
\[\mathbf{B}_t-\mathbf{J}_t=\begin{pmatrix}1&2&3\\4&5&6\\\end{pmatrix}-\begin{pmatrix}1&1&1\\1&1&1\\\end{pmatrix}=\begin{pmatrix}0&1&2\\3&4&5\\\end{pmatrix}\]
행렬의 곱
1
2
|
B_t_2 = B_t @ B_t.T
B_t_2
|
tensor([[14, 32],
[32, 77]])
1
2
|
torch.matmul(B_t, B_t.T, out=B_t_2)
B_t_2
|
tensor([[14, 32],
[32, 77]])
1
2
|
B_t_2 = B_t.matmul(B_t.T)
B_t_2
|
tensor([[14, 32],
[32, 77]])
\[\begin{align} \mathbf{B}_t^2 &= \begin{pmatrix}1&2&3\\4&5&6\\\end{pmatrix}\begin{pmatrix}1&2&3\\4&5&6\\\end{pmatrix}^T \tag{10}\\ &= \begin{pmatrix}1&2&3\\4&5&6\\\end{pmatrix}\begin{pmatrix}1&4\\2&5\\3&6\\\end{pmatrix} \tag{11}\\ &= \begin{pmatrix}14&32\\32&77\\\end{pmatrix} \tag{12} \end{align}\]
모든 elements의 합
하나의 tensor 안에 있는 모든 element의 합은 다음과 같이 구할 수 있다.
tensor(21) \(\mathbf{B}_t=\begin{pmatrix}1&2&3\\4&5&6\\\end{pmatrix}\tag{13}\) \(1+2+3+4+5+6=21\tag{14}\)
Tensor 합치기
기존 차원으로 합치기
torch.cat()는 tenser를 기존 차원을 바탕으로 합치는 것이다. 행렬로 예를 들면 아래와 같이 행렬이 있을 때, 행을 추가하거나 열을 추가하는 것이다. \(\mathbf{A}_t=\begin{pmatrix}1&2&3\end{pmatrix}\tag{13}\) \(\mathbf{B}_t=\begin{pmatrix}1&2&3\\4&5&6\\\end{pmatrix}\tag{14}\) \(\mathbf{C}_t=\begin{pmatrix}1&2&3\\1&2&3\\4&5&6\\\end{pmatrix}\tag{15}\)
그런데 아래의 코드를 보면, 위와 같이 되지 않고, 오류가 나는 것을 확인할 수 있다. 그 이유는 기존에 정의한 a_t가 1차원의 vector이기 때문이다. torch.cat()를 사용하기 위해서는 tensor의 dimension이 동일해야 한다. 따라서 1행만 있는 matrix 형태의 tensor를 만들어주어야 한다.
1
|
C_t = torch.cat([a_t, B_t], dim=0)
|
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
Cell In[90], line 1
----> 1 C_t = torch.cat([a_t, B_t])
RuntimeError: Tensors must have same number of dimensions: got 1 and 2
1행만 있는 matrix 형태의 tensor를 새롭게 정의하여 torch.cat()를 사용하니 의도한 대로 잘 되는 것을 확인할 수 있다. 당연하겠지만, 두 tensor를 합칠 때, 합치는 부분의 dimension, 즉 행 또는 열의 수는 동일해야 한다.
1
2
3
|
A = [[1, 2, 3]]
A_t = torch.tensor(A)
C_t = torch.cat([A_t, B_t], dim=0)
|
tensor([[1, 2, 3],
[1, 2, 3],
[4, 5, 6]])
새로운 차원으로 합치기
torch.stack()은 방금 살펴본 torch.cat()와는 달리, 새로운 차원으로 합치게 된다. 이떄, 새로운 dimension으로 합치게 되기에 합치는 tensor들의 dimension이 동일해야 한다.
1
2
|
C_t = torch.stack([B_t, B_t], dim=0)
C_t
|
tensor([[[1, 2, 3],
[4, 5, 6]],
[[1, 2, 3],
[4, 5, 6]]])
Tensor 나누기
Tensor dimension 바꾸기
Tensor dimension 축소하기
기타
Tensor 속성 확인
Dimension 확인
torch.Size([2, 3])
자료형 확인
torch.int64
저장 위치 확인
device(type=’cpu’)
Tensor 저장 위치 변경
GPU(CUDA)로 변경
1
2
|
B_t = B_t.cuda()
B_t.device
|
device(type=’cuda’, index=0)
CPU로 변경
1
2
|
B_t = B_t.cpu()
B_t.device
|
device(type=’cpu’)