파이토치를 사용하는 경우
1. Numpy를 대체하면서 GPU를 이용한 연산이 필요한경우
2. 최대한의 유연성과 속도를 제공하는 딥러닝 연구 플랫폼이 필요한 경우
Tensor
tensor는 numpy의 ndarray와 유사하며, GPU를 사용한 연산 가속도 가능하다.
%matplotlib inline #notebook을 실행한 브라우저에서 바로 그림을 볼 수 있게 해주는 것
from __future__ import print_function #print함수를 파이썬2든 3이든 상관없이 3문법으로 출력한다
import torch #torch라는 모듈을 쓸것이다.
x = torch.empty(5, 3) #초기화되지않은 5x3 matrix(tensor)를 생성해라.
print(x) #만든 matrix를 출력해라.
결과:
※초기화되지 않은 행렬이란 행렬이 생성되면 그 시점에 할당된 메모리에 존재하던 값들로 이루어진 행렬을 의미한다.
x = torch.rand(5, 3) #[0,1)값중에 무작위로 초기화된 행렬(tensor)을 생성해라.
print(x)
결과:
※초기화된 행렬은 행렬값들이 0이라는 것을 의미하는 것이 아니다.
x = torch.zeros(5, 3, dtype=torch.long) #0으로 채워진 dtype이 long인 tensor를 생성해라.
print(x)
결과:
x = torch.tensor([5.5, 3]) #입력데이터 그대로 tensor를 생성해라.
print(x)
결과:
x = x.new_ones(5, 3, dtype=torch.double) # 1로 5x3 matrix를 만들어라(숫자형은 double), new_* 메소드는 크기를 받는다.
print(x)
결과:
#torch.randn_like함수는 위의 x와 크기가 같고 변수형은 dtype인 랜덤인 수를 출력하는 함수이다.
x = torch.randn_like(x, dtype=torch.float) # 위에서는 double형이면 이번에는 float형으로 dtype을 재정의한다.
print(x)
결과:
print(x.size()) #행렬의 크기를 구한다.
결과:
연산(Operations)
연산을 위한 여러가지 문법들
#덧셈: 문법1
y = torch.rand(5, 3)
print(x) #x는 위에서 구한 값 그대로이다.
print(y)
print(x + y) #y값이 랜덤이기때문에 결과값도 계속 바뀐다.
결과:
#덧셈: 문법2
print(torch.add(x, y)) #결과는 위와 같다.
결과:
#덧셈: 결과 tensor를 인자로 제공한다. (인자: 괄호안에 들어있는 것)
result = torch.empty(5, 3)
torch.add(x, y, out=result) #x와 y를 더하는데 out은 위에서 초기화되지않은 x,y tensor를 사용한다.
print(result) #위에 있는 x,y tensor그대로 더하기때문에 이 또한 결과값은 같다.
결과:
#덧셈: 바꿔치기(in-place) 방식
# y에 x더하기
print(y) #원래 y값
y.add_(x) #원래의 y값과 x,y더한값을 바꿔치기한다는 뜻이다.
print(y) # y+x한 값. y에 x를 더한 것이기때문에 y를 출력하면 결과값이 나온다. y자체의 값이 변한다.
결과:
※바꿔치기(in-place) 방식으로 tensor의 값을 변경하는 연산 뒤에는 _``가 붙는다. 예: ``x.copy_(y), x.t_() 는 x 를 변경한다.
# NumPy스러운 인덱싱 표기 방법을 사용할수도 있다.
print(x[:, 1]) #x tensor에서 1열을 전체 다 출력한다. (행렬은 0부터 시작)
결과:
# 크기 변경(resize): tensor의 크기(size)나 모양(shape)을 변경하고 싶다면 torch.view(size)를 사용한다.
x = torch.randn(4, 4) #입력값 개수: 4x4=16
y = x.view(16) #입력값 개수: 16
z = x.view(-1, 8) # -1은 다른 차원이 정해지면 자동으로 계산되어 정해짐을 의미한다, 입력의 값이 총 16개 이므로 -1은 2가 된다. 그래야 z의 출력값이 16개가 된다.(2x8=16)
print(x.size(), y.size(), z.size())
결과:
# 만약 tensor에 1x1 size의 하나의 값만 존재한다면 .item() 을 사용하면 숫자 값을 얻을 수 있다.
x = torch.randn(1)
print(x)
print(x.item()) #랜덤이기 때문에 결과값이 계속 바뀐다.
결과:
※전치(transposing), 인덱싱(indexing), 슬라이싱(slicing), 수학 계산, 선형 대수, 난수(random number) 등, 100가지 이상의 Tensor 연산은 여기 에서 확인할 수 있다.
NumPy Bridge
Torch Tensor를 NumPy 배열(array)로 변환하거나, 그 반대로 하는 것은 매우 쉽다.
(Torch Tensor가 CPU 상에 있다면) Torch Tensor와 NumPy 배열은 메모리 공간을 공유하기 때문에, 하나를 변경하면 다른 하나도 변경된다.(import numpy as np)
●Torch Tensor를 NumPy 배열로 변환하기
a = torch.ones(5) # 1을 5열로 출력해라, tensor사용하기
print(a)
결과:
b = a.numpy() #numpy array사용하기 (torch를 numpy로 변환하기)
print(b) #위 출력과 달리 tensor가 앞에 붙지않는다.
결과:
a.add_(1) # 위에 a에 1을 더해라
print(a) #tensor로 출력해라
print(b) #numpy로 출력해라, tensor값을 변경하면 numpy값도 변한다.
결과:
●NumPy 배열을 Torch Tensor로 변환하기
import numpy as np #numpy를 쓰기위해서는 이거 써야한다.
a = np.ones(5)
print(a) #numpy가 출력된다.
b = torch.from_numpy(a) #numpy를 torch로 변환해라
np.add(a, 1, out=a) #a에 1을 더하고 out에 a가 저장된다.
print(a) #numpy가 출력된다.
print(b) #torch가 출력된다.
결과:
※CharTensor를 제외한 CPU 상의 모든 Tensor는 NumPy로 변환할 수 있고, (NumPy에서 Tensor로의) 반대 변환도 가능하다.
CUDA Tensors
.to 메소드를 사용하여 Tensor를 어떠한 장치로도 옮길 수 있다.
# 이 코드는 CUDA가 사용 가능한 환경에서만 실행가능하다(코랩에서 쓸때는 런타임을 GPU로 바꿔줘야한다.)
# ``torch.device`` 를 사용하여 tensor를 GPU 안팎으로 이동해보자
if torch.cuda.is_available(): #CUDA를 사용할수있으면
device = torch.device("cuda") # CUDA라는 장치를 이용해서
y = torch.ones_like(x, device=device) # GPU 상에 직접적으로 tensor를 생성해라, y를 x와같은 크기인 모두 1인 행렬을 만든다.
x = x.to(device) # 아니면 ``.to("cuda")`` 를 사용해 x를 GPU로 보내라
z = x + y
print(x) #1x1 matrix 가 출력된다.
print(y) #y도 x와 크기가 같기때문에 1x1 matrix가 출력된다.
print(z) #두 matrix를 더했기 때문에 이또한 1x1 matrix가 출력된다.
print(z.to("cpu", torch.double)) # ``.to`` 는 dtype도 함께 변경가능, CPU에서 torch.double로 변환
결과:
* 참고
생물정보학자의 블로그, 양갱로그