본문 바로가기
딥러닝/딥러닝

[PyTorch] Tensor Manipulation

by DUSTIN KANG 2020. 10. 7.

🌱 Tensor

Tensor(텐서)Ndarray와 유사하게 행렬이나 배열로 나타낼 수 있는 데이터의 표현 방법입니다. 

Tensor(텐서)에서 차원(Dimension, D)의 개수를 랭크(Rank)라고 합니다.

벡터의 차원과 텐서의 차원은 다릅니다. [1,2,3,4,5]가 5차원 벡터일지라도 1차원 텐서입니다.

import torch
import numpy as np

data = [[1,2,4],[3,5,9]]
x_data = torch.tensor(data, dtype=torch.int64)
print(x_data.dim(), x_data.shape, x_data.size())

# 2 torch.Size([2, 3]) torch.Size([2, 3]) torch.LongTensor
  • Tensor는 기본적으로 데이터 타입과 크기를 지정할 수 있습니다. 여기서는 `LongTypeTensor`입니다.
  • 위 그림과 같이 Tensor는 BatchSize끼리나 Dimension끼리 서로 틀리면 안됩니다.
  • 데이터 타입은 가변길이의 문자열이나 NoneType은 지원하지 않으며 `float32/64`, `int32/64` `unit8`이 될 수 있습니다.
  • 텐서의 속성은 이외에도 `shape`, `dtype`(자료형), `device`(저장위치)를 설정할 수 있습니다.
이런식으로,  텐서는 고차원 텐서까지 만들 수 있습니다. 보통 0D(Scalar)부터 4D까지 다루게 됩니다.

 

텐서 조작하기

1. Numpy로 텐서 조작하기

np_array = np.array(data)
x_np = torch.from_numpy(np_array) # numpy to tensor
x = x_np.numpy() # tensor to numpy

 

여기서 중요한 것은 Tensor와 Numpy는 메모리 공간을 서로 공유하기 때문에 텐서를 변경하게되면 변환한 넘파이도 같이 변경됩니다.

2.  Shape과 datatype만 유지한채 데이터 덮어쓰기

x_ones = torch.ones_like(x_data)
x_rand = torch.rand_like(x_data, dtype=torch.float) # 0 ~ 1 까지의 무작위 수

shape = (2, 3,)
zeros_tensor = torch.zeros(shape)
rand_tensor = torch.rand(shape)

x_ones.fill(5)

3.  인덱싱, 슬라이싱, 합치기

tensor = torch.ones(4,4)
tensor[:, 1] = 0 # 행, 열
print(tensor)

"""
tensor([[1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.]])
"""

t1 = torch.cat([tensor, tensor, tensor], dim=1)
# dim이 아니라 stack의 경우 행에 이어붙이기 됩니다.


'''
tensor([[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],
        [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],
        [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],
        [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.]])
'''

 

더보기
  • `x.view(shape)` : 데이터를 공유하는 새로운 텐서를 만들어 shape만 변경합니다.
  • `torch.arange(N)` : 0부터 N-1까지의 1차원 텐서를 만듭니다.
  • `torch.transpose(tensor, 0, 1)` : 텐서를 transpose(T)합니다. 

관련 공식 문서 참조↗


🍀 Tensor Multiplication

torch는 일반적인 연산(`.add(), .sum()`) 뿐만 아니라 행렬곱도 나타낼 수 있습니다.

m1 = torch.FloatTensor([[1,2], [3,4]])
m2 = torch.FloatTensor([[1],[2]])

print(m1.matmul(m2)) # matrix multiplication (행렬 곱)

print(m1 * m2) # element-wise product (요소별 곱)
print(m1.mul(m2))

tensor = torch.FloatTensor([[1,2],[3,4]])
tensor.mean(dim=0)
tensor.sum(dim=1) # 
tensor.max(dim=0)[0] # max : 최대값
tensor.max(dim=1)[1] # argmax : 최대값의 인덱스

`mul`과 `mul_`의 차이는 메모리에 새로 선언하지 않고 기존의 텐서에 바로 적용하려면 `_`를 반드시 붙여야 합니다.

🍀 Tensor Reshape

`.view()`

 

 


🍀 신경망을 위한 데이터 표현

텐서의 실제 사례

  • 벡터의 데이터 : (samples, features ) 크기의 2D 텐서    [n,n,n,n,n] → sample 1개
  • 시계열(시퀀스)데이터_시간의 영향을 받는 데이터 : (samples, timesteps, features) 크기의 3D 텐서
  • 이미지 : (samples, height, width, channels) or (samples, channels, height, width) 크기의 4D 텐서, channels : 삼원색 (channel = 3)
  • 동영상 : (samples, frames, height, width, channels) 또는 (samples, frames, channels, height, width)

벡터 데이터

  • 대부분의 경우 해당하며, 이런 데이터셋에서는 하나의 데이터 포인트가 벡터로 인코딩 될 수 있으므로 배치 데이터는 2D 텐서로 인코딩 될 것. (즉 벡터의 배열), (샘플축, 특성 축)
  • 사람의나이, 우편번호, 소득으로 구성된 인구 통계 데이터  (각 사람마다 3개의 값을 가진 벡터로 구성되고 10만명이 포함한 데이터셋은 (1000000, 3)

시계열 데이터 또는 시퀀스 데이터

  • 시간이 중요할 때는 시간 축을 포함하여 3D텐서로 저장됨. 
  • 주식 가격 데이터 셋 : 1분마다 현재 주식 가격, 지난 1분 동안에 최고,최저 가격을 저장
    • 1분마다 데이터 : 3D 벡터로 인코팅 된다.
    • 하루 동안의 거래는 (390,3)일경우 하루의 거래 시간은 390분
    • 250일치의 데이터는 (250,390,3)로 저장됨.
  • 트윗 데이터 셋 : 각 트윗은 128개의 알파벳으로 구성된 280개의 문자 시퀀스 (각 문자가 128개의 크기인 이진벡터로 인코딩 될 수 있음)
    • 각 트윗은 (280, 128) 크기의 2D 데이터
    • 10000개의 트윗으로 구성된 데이터셋은  (10000, 280, 128)크기의 텐서로 저장

시계열 데이터 또는 시퀀스 데이터

  • 시간이 중요할 때는 시간 축을 포함하여 3D텐서로 저장됨. 
  • 주식 가격 데이터 셋 : 1분마다 현재 주식 가격, 지난 1분 동안에 최고/최저 가격을 저장
    • 1분마다 데이터 : 3D 벡터로 인코팅 된다.
    • 하루 거래는 (390,3)일경우 하루의 거래 시간은 390분
    • 250일치의 데이터는 (250,390,3)로 저장됨.
  • 트윗 데이터 셋 : 각 트윗은 128개의 알파벳으로 구성된 280개의 문자 시퀀스,
    • 각 트윗은 (280, 128) 크기의 2D 데이터
    • 10000개의 트윗을 보낼 경우 (10000, 280, 128)

이미지 데이터

  • 이미지는 높이, 너비 컬러 채널의 3차원으로 이루어짐
  • 흑백 이미지는 하나의 컬러 채널을 갖고 관례상 이미지 텐서는 3D로 저장
  • 흑백 이미지의 경우, 컬러 채널의 차원 크기는 1이고 256x256 크기의 흑백 이미지에 대한 128개의 배치는 (128, 256, 256, 1) 크기로 저장
  • 컬러 이미지에 대한 128개의 배치라면 (128, 256, 256, 3)
  • 이미지 텐서의 크기를 지정하는 방식
    • 텐서플로는 채널 마지막 방식을 사용, (samples, height, width, channels,depth)

그림 첨부..

 

비디오 데이터

  •  5차원으로 이루어짐  
  • 하나의 비디오는 프레임의 연속이기 때문에 각 프레임은 하나의 컬러 이미지를 갖는다. (3D텐서로 저장)
  • 60초 짜리 144X256 유투브 비디오 클립을 초당 4프레임을 샘플링 하면 240 프레임이 되고 이런 비디오 클립을 4개 가진 배치는
  • (4,240,144,256,3)  == (samples, frames, height, width, channels)