참고
Go to the end to download the full example code.
Tensor#
PyTorch에서의 Tensor는 Torch에서와 거의 동일하게 동작합니다.
초기화되지 않은 (5 x 7) 크기의 Tensor를 생성합니다:
import torch
a = torch.empty(5, 7, dtype=torch.float)
평균 0, 분산 1의 정규분포를 따르는 무작위 숫자로 double Tensor를 초기화합니다:
a = torch.randn(5, 7, dtype=torch.double)
print(a)
print(a.size())
tensor([[-0.0797, 0.1061, 0.0917, -0.8147, 0.1001, 1.6140, -0.3369],
[ 0.6229, 1.1146, 1.6724, -0.4753, -0.0863, 1.0825, 1.2855],
[ 0.8723, 0.9935, -1.3918, 0.0536, -1.1909, 0.3864, -0.9657],
[-1.4137, 1.3417, 1.2953, 0.9742, -0.0253, -0.7997, -0.3155],
[ 0.5933, -0.1500, -1.5197, -1.2851, 0.6470, 0.7818, 0.9545]],
dtype=torch.float64)
torch.Size([5, 7])
참고
torch.Size
는 튜플(tuple)과 같으며, 모든 튜플 연산에 사용할 수 있습니다.
바꿔치기(In-place) / 반환하기(Out-of-place)#
모든 바꿔치기 연산은 _
접미사를 갖고 있다는 것이 첫번째 차이점입니다.
예를 들어, add
는 연산 결과를 돌려주는 반환하기 버전이고, add_
는
(호출한 Tensor의 값이 바뀌는) 바꿔치기 버전입니다.
a.fill_(3.5)
# a의 값이 3.5로 바꿔치기 됩니다.
b = a.add(4.0)
# a는 여전히 3.5입니다.
# 3.5 + 4.0 = 7.5의 값이 반환되어 새로운 tensor b가 됩니다.
print(a, b)
tensor([[3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000],
[3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000],
[3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000],
[3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000],
[3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000, 3.5000]],
dtype=torch.float64) tensor([[7.5000, 7.5000, 7.5000, 7.5000, 7.5000, 7.5000, 7.5000],
[7.5000, 7.5000, 7.5000, 7.5000, 7.5000, 7.5000, 7.5000],
[7.5000, 7.5000, 7.5000, 7.5000, 7.5000, 7.5000, 7.5000],
[7.5000, 7.5000, 7.5000, 7.5000, 7.5000, 7.5000, 7.5000],
[7.5000, 7.5000, 7.5000, 7.5000, 7.5000, 7.5000, 7.5000]],
dtype=torch.float64)
narrow
와 같은 일부 연산들은 바꿔치기 버전을 갖지 않기 때문에 .narrow_
는
존재하지 않습니다. 또한, fill_
은 반환하기 버전을 갖지 않기 때문에 역시
.fill
도 존재하지 않습니다.
0-인덱스(Zero Indexing)#
또 다른 차이점은 Tensor의 인덱스는 0부터 시작(0-인덱스)한다는 점입니다. (Lua에서 tensor는 1-인덱스를 갖습니다.)
b = a[0, 3] # a의 첫번째 행, 4번째 열을 선택합니다
Python의 슬라이싱으로도 Tensor를 인덱스 할 수 있습니다.
b = a[:, 3:5] # a의 모든 행과 4번째와 5번째 열을 선택합니다
카멜표기법(Camel case) 없음#
그 외에도 카멜표기법을 사용하지 않는 사소한 차이가 있습니다.
일례로 indexAdd
는 index_add_
라고 표기합니다.
x = torch.ones(5, 5)
print(x)
tensor([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
z = torch.empty(5, 2)
z[:, 0] = 10
z[:, 1] = 100
print(z)
tensor([[ 10., 100.],
[ 10., 100.],
[ 10., 100.],
[ 10., 100.],
[ 10., 100.]])
x.index_add_(1, torch.tensor([4, 0], dtype=torch.long), z)
print(x)
tensor([[101., 1., 1., 1., 11.],
[101., 1., 1., 1., 11.],
[101., 1., 1., 1., 11.],
[101., 1., 1., 1., 11.],
[101., 1., 1., 1., 11.]])
NumPy 변환(bridge)#
Torch Tensor를 NumPy 배열로 변환하거나, 그 반대로 하는 것은 매우 쉽습니다. Torch Tensor와 NumPy 배열은 저장 공간을 공유하기 때문에, 하나를 변경하면 다른 하나도 변경됩니다.
Torch Tensor를 NumPy 배열로 변환하기#
a = torch.ones(5)
print(a)
tensor([1., 1., 1., 1., 1.])
b = a.numpy()
print(b)
[1. 1. 1. 1. 1.]
a.add_(1)
print(a)
print(b) # NumPy 배열의 값이 어떻게 바뀌었는지 확인하세요
tensor([2., 2., 2., 2., 2.])
[2. 2. 2. 2. 2.]
NumPy 배열을 Torch Tensor로 변환하기#
import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b) # NumPy 배열이 Torch Tensor 값을 자동으로 바꾼 것을 확인하세요
[2. 2. 2. 2. 2.]
tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
CharTensor를 제외한 CPU 상의 모든 Tensor는 NumPy로의 변환을 지원하며, (NumPy에서 Tensor로의) 반대 변환도 지원합니다.
CUDA Tensor#
PyTorch에서 CUDA Tensor는 멋지고 쉽습니다. 그리고 CUDA Tensor를 CPU에서 GPU로 옮겨도 기본 형식(underlying type)은 유지됩니다.
# 이 코드는 CUDA가 사용 가능한 환경에서만 실행됩니다.
if torch.cuda.is_available():
# LongTensor를 생성하고 이를 GPU 상의 torch.cuda.LongTensor로 옮깁니다.
a = torch.full((10,), 3, device=torch.device("cuda"))
print(type(a))
b = a.to(torch.device("cpu"))
# CPU로 다시 전송을 하면, torch.LongTensor로 되돌아옵니다.
<class 'torch.Tensor'>
Total running time of the script: (0 minutes 4.461 seconds)