필자인 저 또한 배운 것들을 정리 하면서 쓰는 글이기 때문에, 틀린 부분이 있을 수도 있습니다. 또한, 이 글은 Numpy
에 대한 기본 적인 배경 지식을 필요로 합니다. 오타, 지적사항 발생 시, 댓글 혹은 이메일로 남겨 주시면 감사하겠습니다!
Pytorch는 두 가지 목표를 달성하기 위해 만들어진 오픈 소스 라이브러리이자, Python Package입니다. 두 가지 목표는 다음과 같습니다.
Facebook 인공지능 연구 팀이 개발 하였으며, 러닝 커브가 낮고, 코드 가독성 또한 좋은 편입니다. 실시간 결과 값을 시각화도 가능할 뿐더러, 기계 학습 과정을 보며, 수학적으로 이해하는 데 상당히 유용하죠. 자, 한번 Pytorch의 기본 문법을 알아 볼까요?
Python3, pip이 설치된 상태에서 터미널에 해당 명령어를 입력 해 주세요.
pip install torch===1.4.0 torchvision===0.5.0 -f https://download.pytorch.org/whl/torch_stable.html
Tensor
객체는 Numpy
의 ndarray
와 상당히 유사한 구조를 가집니다. 애초에 Pytorch
가 Numpy
를 대체하기 위해서 나왔기 때문이죠, 일단 torch
모듈을 import
해 볼까요?
import torch
그 다음, Tensor
객체를 만드는 여러 가지 방법들을 알려 드리겠습니다.
torch.empty(x, y)
: x * y 사이즈의 요소들의 값이 초기화 되지 않은 행렬 반환.torch.rand(x, y)
: x * y 사이즈의 요소들이 0 ~ 1 사이의 랜덤한 값으로 초기화 된 행렬 반환.torch.randn(x, y)
: x * y 사이즈의 요소들이 정규분포 그래프 상의 랜덤한 값으로 초기화 된 행렬 반환.torch.zeros(x, y, dtype=type)
: x * y 사이즈의 요소들이 0으로 초기화 된 행렬 반환, 요소들은 type에 맞게 초기화 된다.torch.ones(x, y, dtype=type)
: x * y 사이즈의 요소들이 1으로 초기화 된 행렬 반환, 요소들은 type에 맞게 초기화 된다.torch.tensor(iterable)
: iterable
한 객체를 Tensor
객체로 변환한다.torch.zeros_like(tensor, dtype=type)
: 파라미터로 들어 간 Tensor
객체의 사이즈과 똑같은 행렬을 반환하며, 요소들은 0으로 초기화 되어 있다.torch.ones_like(tensor, dtype=type)
: 파라미터로 들어 간 Tensor
객체의 사이즈과 똑같은 행렬을 반환하며, 요소들은 1으로 초기화 되어 있다.torch.randn_like(tensor, dtype=type)
: 파라미터로 들어 간 Tensor
객체의 사이즈과 똑같은 행렬을 반환하며, 요소들은 정규분포 그래프 상의 랜덤한 값으로 초기화 되어 있다.empty_tensor = torch.empty(3, 3) # 3 * 3의 빈 행렬 생성
rand_tensor = torch.rand(3, 3) # 3 * 3의 요소들이 0 ~ 1의 랜덤 값으로 초기화된 행렬 생성
randn_tensor = torch.randn(3, 3, dtype=torch.double) # 3 * 3의 요소들이 정규분포 그래프 값으로 초기화된 행렬 생성
zero_tensor = torch.zeros(3, 3, dtype=torch.long) # 3 * 3의 요소들이 0으로 초기화된 행렬 생성
one_tensor = torch.ones(3, 3, dtype=torch.double) # 3 * 3의 요소들이 1으로 초기화된 행렬 생성
iterable_tensor = torch.tensor([1, 2, 3]) # list 객체를 Tensor 객체로 변환
zeros_like_tensor = torch.zeros_like(iterable_tensor, dtype=torch.double) # iterable_tensor와 사이즈가 같은, 요소들이 0으로 초기화된 행렬 생성
ones_like_tensor = torch.ones_like(iterable_tensor, dtype=torch.double) # iterable_tensor와 사이즈가 같은, 요소들이 1으로 초기화된 행렬 생성
randn_like_tensor = torch.randn_like(iterable_tensor, dtype=torch.double) # iterable_tensor와 사이즈가 같은, 요소들이 정규분포 그래프 값으로 초기화된 행렬 생성
print(empty_tensor)
print(rand_tensor)
print(randn_tensor)
print(zero_tensor)
print(one_tensor)
print(iterable_tensor)
print(zeros_like_tensor)
print(ones_like_tensor)
print(randn_like_tensor)
tensor([[1.2045e-35, 0.0000e+00, 4.4842e-44],
[0.0000e+00, nan, 6.1657e-44],
[4.3722e-05, 5.2475e-08, 1.7662e-04]])
tensor([[0.8250, 0.8530, 0.6120],
[0.4726, 0.9426, 0.7616],
[0.5276, 0.1977, 0.1966]])
tensor([[-0.1279, -0.9227, 0.0434],
[-0.2085, 0.1541, -1.8450],
[-0.7687, 0.0956, -0.6723]], dtype=torch.float64)
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)
tensor([1, 2, 3])
tensor([0., 0., 0.], dtype=torch.float64)
tensor([1., 1., 1.], dtype=torch.float64)
tensor([ 0.5920, -0.2960, -0.2184], dtype=torch.float64)
당연히, Tensor
객체의 연산을 위한 연산자, 인덱싱 또한 준비 되어 있습니다.
일단 기본적인 연산자는 다음과 같이 사용 할 수 있습니다. 또한, Numpy
에서 사용 했던, 차원별 인덱싱과 브로드캐스팅이 가능합니다.
x_tensor = torch.tensor([[1, 2], [3, 4]]) # 2 * 2 행렬 생성
y_tensor = torch.tensor([[5, 6], [7, 8]])
z_tensor = torch.tensor([[[1, 2], [3, 4]], [[1, 2], [3, 4]]])
print(x_tensor)
print(y_tensor)
print(x_tensor + y_tensor) # Index가 일치하는 요소 끼리 덧셈
print(x_tensor - y_tensor) # Index가 일치하는 요소 끼리 뺄셈
print(x_tensor * y_tensor) # Index가 일치하는 요소 끼리 곱셈
print(x_tensor @ y_tensor) # 행렬 곱
print(x_tensor * 3) # x_tensor 각 요소에 3을 곱해줌
print(x_tensor + z_tensor) # 일치하는 요소에 브로드캐스팅
a_tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
b_tensor = torch.tensor([[1, 2], [3, 4], [5, 6]])
print(a_tensor)
print(b_tensor)
print(a_tensor @ b_tensor) # 2 * 3 행렬과 3 * 2 행렬 곱셈
print(a_tensor[:, 1]) # 각 행의 1번째 열 추출
print(b_tensor[1, :]) # 1번째 행의 모든 열 추출
tensor([[1, 2],
[3, 4]])
tensor([[5, 6],
[7, 8]])
tensor([[ 6, 8],
[10, 12]])
tensor([[-4, -4],
[-4, -4]])
tensor([[ 5, 12],
[21, 32]])
tensor([[19, 22],
[43, 50]])
tensor([[ 3, 6],
[ 9, 12]])
tensor([[[2, 4],
[6, 8]],
[[2, 4],
[6, 8]]])
tensor([[1, 2, 3],
[4, 5, 6]])
tensor([[1, 2],
[3, 4],
[5, 6]])
tensor([[22, 28],
[49, 64]])
tensor([2, 5])
tensor([3, 4])
딥러닝 모델을 설계하다 보면 행렬 사이즈를 재조정 해야 하는 경우가 상당히 많습니다. 이를 위한 몇 가지 함수를 소개 시켜 드리겠습니다.
Tensor.size()
: Tensor
객체의 사이즈를 반환 한다.Tensor.view(size)
: 파라미터로 들어간 사이즈로 Tensor
객체의 사이즈를 변환 시켜 주며, 파라미터로 -1이 들어갈 시, 행렬의 차원 수를 낮춰 리사이징 하며, (-1, n)이 들어가면 가장 하위 차원에서 n개씩 끊어 넣는 방식으로 리사이징 한다. numpy
의 resize
와 방법이 유사하다.a_tensor = torch.tensor([[1, 2, 3, 4], # 4 * 4 행렬
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]])
print(a_tensor)
print(a_tensor.size())
b_tensor = a_tensor.view(16) # 사이즈가 16 array
print(b_tensor)
print(b_tensor.size())
c_tensor = a_tensor.view(-1, 8) # 4 * 4 => 2 * 8
print(c_tensor) # 6 * 4 일시 3 * 8 으로 리사이징 된다.
print(c_tensor.size())
d_tensor = a_tensor.view(-1) # 4 * 4 => 16
print(d_tensor) # 6 * 4 일시 24로 리사이징 된다.
print(d_tensor.size())
e_tensor = a_tensor.view(8, 2) # 8 * 2 행렬로 사이즈 변환
print(e_tensor)
print(e_tensor.size())
tensor([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16]])
torch.Size([4, 4])
tensor([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
torch.Size([16])
tensor([[ 1, 2, 3, 4, 5, 6, 7, 8],
[ 9, 10, 11, 12, 13, 14, 15, 16]])
torch.Size([2, 8])
tensor([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
torch.Size([16])
tensor([[ 1, 2],
[ 3, 4],
[ 5, 6],
[ 7, 8],
[ 9, 10],
[11, 12],
[13, 14],
[15, 16]])
torch.Size([8, 2])
Pytorch
는 Numpy
연산을 GPU를 이용하여, 더욱 빠르게 하기 위해 탄생했습니다. 그렇기 때문에 Numpy
와 Pytorch
를 연동할 수 있도록, Pytorch
에서는 API
를 제공합니다.
Tensor.numpy()
: Tensor
객체를 numpy.ndarray
객체로 변환 하여 반환합니다.torch.from_numpy(ndarray)
: numpy.ndarray
를 Tensor
객체로 변환 하여 반환합니다.import numpy as np
import torch
a_matrix = np.array([[1, 2], [3, 4]]) # np.ndarray 객체 할당
b_matrix = torch.from_numpy(a_matrix) # np.ndarray 객체를 이용하여 Tensor 객체 할당
c_matrix = b_matrix.numpy() # Tensor 객체를 이용하여 np.ndarray 객체 할당
print(a_matrix) # np.ndarray
print(b_matrix) # Tensor
print(c_matrix) # np.ndarray
[[1 2]
[3 4]]
tensor([[1, 2],
[3, 4]])
[[1 2]
[3 4]]
Pytorch
는 Numpy
와 API
형태가 상당히 유사합니다. 하지만, Numpy
와 다른 점이 있다면, Backpropagation
을 쉽게 구현할 수 있고, loss function
, optimizer
등 많은 고수준 API
를 제공합니다. 다음 시간에는 Pytorch로 미분하기, autograd에 대해서 알아 보겠습니다.