Pytorch Basics : Tensor 알아보기
Category: Deep Learning
Tags: pytorch deeplearning
Tensors
파이토치에서 텐서(tensor)는 numpy에 있는 ndarray와 매우 유사하며, 한 마디로 정리하면 다차원 배열을 통칭하는 말이다.
두 가지의 차이점은 numpy는 CPU에서만 돌아가는 반면, tensor는 GPU와 같은 연산 가속을 위한 하드웨어에서 실행할 수 있다는 장점이 있다. 따라서, 많은 양의 연산이 반복되는 딥러닝에서 사용하기 효과적이다.
scalar | vector | matrix | matrix sequence |
---|---|---|---|
13 | (13, 42, 2011) | ((8, 1, 6), (3, 5, 7), (4, 9, 2)) | … |
텐서는 여러 차원을 가질 수 있는 데이터를 의미하기 때문에 우리가 접한 위와 같은 형태의 데이터들을 모두 포괄하는 개념이라고 볼 수 있다.
Tensor 배열 선언하기
.empty(r, c)
: 쓰레기 값으로 초기화.zeros(r, c)
: 모두 $0$으로 초기화.rand(r, c)
: $0$ ~ $1$ 사이의 무작위 실수 값으로 초기화.randn(r, c)
: $mean : 0, var : 1$로 정규화된 실수 값으로 초기화.randint(a, b, size=(r, c))
: $a$부터 $b$ 사이의 랜덤 정수 값으로 초기화
import torch
x = torch.empty(1, 3) # tensor([4.2039e-45, 0.0000e+00, 4.2039e-45])
x1 = torch.rand(1, 3) # tensor([0.7720, 0.2139, 0.0912])
x2 = torch.randn(1 ,3) # tensor([0.5197, -0.7889, 0.0773])
x3 = torch.randint(0, 10, size = (1, 3)) # tensor([9, 4, 9])
x4 = torch.zeros(1,3) # tensor([0., 0., 0.])
Tensor 데이터 타입 설정
dtype = torch.half
: 16bit floating point으로 설정dtype = torch.float
: 32bit floating point으로 설정dtype = torch.double
: 64bit floating point로 초기화
import torch
x = torch.zeros(1, 3).cuda()
# tensor([0., 0., 0.]], device='cuda:0')
y = torch.zeros(1, 3, dtype=torch.half).cuda()
# tensor([0., 0., 0.]], device='cuda:0', dtype=torch.float16)
z = torch.zeros(1, 3, dtype=torch.double).cuda()
# tensor([0., 0., 0.]], device='cuda:0', dtype=torch.float64)
아래는 Torch가 정의하고 있는 CPU와 GPU 텐서의 타입들을 나타낸다.
Tensor 배열의 크기 확인하기
받아온 데이터나 결과 데이터의 출력 형태를 확인해볼 때 주로 사용한다.
.size()
: 배열의 shape을 출력하는 함수.shape
: size와 동일한 기능을 하며,()
없이 출력 가능
x = torch.rand(5,3)
print(x.size()) # torch.Size([5, 3])
print(x.shape) # torch.Size([5, 3])
Tensor Addition 연산하기
numpy와 유사한 연산 과정을 지원하고 있다.
x+y
: 단순한 덧셈 기호를 통해서도 내부 원소를 더할 수 있다.torch.add(x, y)
: 더하기 함수를 사용하는 방법
x = torch.rand(5, 3)
y = torch.rand(5, 3)
# Addition
print(x + y)
print(torch.add(x, y))
print(y.add_(x))
Tensor Resizing
.view()
: 전체 원소의 갯수는 유지하면서 배열의 모양을 바꿔주는 함수
x = torch.randn(4, 4)
y = x.view(-1) # tensor를 (?) 사이즈로 변경
z = x.view(-1, 8) # tensor를 (?, 8) 사이즈로 변경 -> (2, 8)
여기서 -1은 사용자가 잘 모르겠으니 파이토치에게 알아서 맡기겠다는 의미를 가지고 있다. 따라서 랜덤으로 조정되고, 사용자가 직접 지정한 부분만 고정해서 바꾸어준다.
Tensor 배열의 값 꺼내기
.item()
: tensor 배열 인덱스에 있는 값을 추출
x = torch.tensor([1,2,3,4])
print(x[0].item()) # 1
print(x[0]) # tensor(1)
기존처럼 배열의 인덱싱을 사용해서 값을 가져오는 경우, tensor에 감싸진 결과가 출력된다. 따라서 안에 있는 배열의 값을 추출하기 위해서는 item 함수를 사용해서 불러와야 한다.
Tensor <-> Numpy 변환
numpy는 CPU, torch는 GPU를 사용해서 연산을 한다는 점을 제외하고는 매우 비슷한 원리를 가지고 있어서 상호 변환이 가능하다.
.numpy()
: tensor -> numpy 배열로 변환torch.from_numpy()
: numpy 배열 -> tensor로 변환
# tensor -> numpy
a = torch.ones(5) # tensor([1., 1., 1., 1., 1.])
b = a.numpy() # [1. 1. 1. 1. 1.]
# numpy -> tensor
a2 = np.ones(5) # [1. 1. 1. 1. 1.]
b2 = torch.from_numpy(a) # tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
여기서 tensor와 numpy를 연결하는 경우, 둘 사이의 어떤 bridge가 형성되기 때문에 하나의 값을 바꾸면 다른 하나의 값도 자동적으로 바뀌게 된다.
a.add_(1)
# a : tensor([2., 2., 2., 2., 2.])
# b : [2. 2. 2. 2. 2.]
CUDA랑 연결하기
torch.cuda.is_available()
: 사용 가능 하면 True, 불가하면 False 출력device = torch.device(”cuda:0”)
: 사용할 디바이스 종류 지정.to(’cuda:0’)
: 0번째 cuda기기에 지정된 GPU에 데이터를 할당하겠다는 의미
x = torch.rand(1)
if torch.cuda.is_available():
device = torch.device("cuda")
y = torch.ones_like(x, device=device) # directly create a tensor on GPU
x = x.to(device) # or just use strings ``.to("cuda")``
z = x + y
이를 통해 파이토치에서는 특정 GPU를 사용하도록 설정할 수 있고, 모델이나 데이터에 원하는 GPU를 직접 할당할 수 있다는 장점이 있다.
Tensor 차원 추가/축소하기
데이터를 학습시키기 전에 전처리하는 과정에서 주로 사용된다.
.unsqueeze(n)
: 기존의 배열에서 $n$번째에 차원을 추가.squeeze(n)
: 기존의 배열에서 $n$번째 차원을 삭제/축소
d = torch.rand(4,4)
print(d.shape) # torch.Size([4, 4])
print(d.unsqueeze(0).shape) # torch.Size([1, 4, 4])
print(d.unsqueeze(1).shape) # torch.Size([4, 1, 4])
print(d.unsqueeze(2).shape) # torch.Size([4, 4, 1])
print(e.squeeze(0).shape) # torch.Size([4])
Tensor Pooling
간단하게 pooling은 텐서 내부의 데이터의 차원을 줄이거나 축소시킬 때 사용한다.
MaxPool1d(n, stride = 1)
: n개씩 데이터를 묶어서 가장 큰 값 하나를 반환-
AvgPool1d(n, stride = 1)
: n개씩 데이터를 묶어서 계산한 평균값을 반환-> stride는 몇 칸씩 건너뛰면서 pooling을 진행할 것인지를 의미
a = torch.rand(1,4) # tensor([0.7646, 0.3953, 0.5796, 0.8444])
max_p = torch.nn.MaxPool1d(3, stride = 1)
avg_p = torch.nn.AvgPool1d(2, stride = 1)
c = max_p(a) # tensor([0.7646, 0.8444])
d = avg_p(a) # tensor([0.5799, 0.4875, 0.7120])