파이토치를 사용하는 경우

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 TensorNumPy 배열(array)로 변환하거나, 그 반대로 하는 것은 매우 쉽다.

(Torch TensorCPU 상에 있다면) Torch TensorNumPy 배열은 메모리 공간을 공유하기 때문에, 하나를 변경하면 다른 하나도 변경된다.(import numpy as np)

 

●Torch TensorNumPy 배열로 변환하기

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 상의 모든 TensorNumPy로 변환할 수 있고, (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로 변환

결과:

 

* 참고

생물정보학자의 블로그, 양갱로그

+ Recent posts