뉴비에욤

PyTorch 튜토리얼 6 - 텐서 본문

Machine Learning/PyTorch

PyTorch 튜토리얼 6 - 텐서

초보에욤 2018. 5. 1. 22:58

2017/07/13 - [Machine Learning/PyTorch] - 윈도우 10 PyTorch 환경 구성 - 설치

2018/04/30 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 1 - PyTorch란?

2018/04/30 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 2 - Autograd : 자동 미분

2018/05/01 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 3 - 뉴럴 네트워크(신경망)

2018/05/01 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 4 - Classifier 학습

2018/05/01 - [Machine Learning/PyTorch] - PyTorch 튜토리얼 5 - 데이터 병렬 처리


원문 : http://pytorch.org/tutorials/beginner/former_torchies/tensor_tutorial.html


* 17년도 07월에 초번 번역 후, 파이토치 최신 버전인 0.4.0에 맞추어 갱신 된 번역본

* 최근 갱신일 : 2018-05-01



목 차 ( 초보자 튜토리얼 )

B. Torch 사용자를 위한 PyTorch

6. 텐서

- 인-플레이스 / 아웃-플레이스

0-인덱싱

카멜 표기법 없음

NumPy 변환

torch 텐서 -> numpy 배열로 변환

numpy 배열 -> torch 텐서로 변환

CUDA 텐서






텐서(Tensors)


파이토치에서의 텐서는 토치에서의 텐서와 거의 동일하게 동작한다.


초기화 되지 않은 5*7 크기의 텐서를 만든다.

- 소스

import torch
a = torch.empty(5, 7, dtype=torch.float)


mean(평균) = 0, var(분산) = 1을 가지는 정규 분포로 랜덤화 된 이중 텐서를 초기화 한다.

- 소스

a = torch.randn(5, 7, dtype=torch.double)
print(a)
print(a.size()) 

- 결과

tensor([[ 0.2095, -1.5431, -0.1285, -0.3743, -0.4776, -0.4502,  0.6279],
        [ 0.9514, -1.7334, -0.6382, -0.3209, -0.2505, -1.1160, -1.0959],
        [-0.3199,  1.7155,  1.3164, -0.3394, -0.2693, -1.9001,  0.6337],
        [-0.2756, -1.3569, -0.2064,  2.4318, -1.1204, -0.8584,  0.1493],
        [-0.5671,  0.9556,  0.5539,  0.0953,  0.6315, -1.2639,  0.3836]], dtype=torch.float64)
torch.Size([5, 7])


torch.Size는 파이썬의 튜플 자료형이기 때문에 튜플 연산을 그대로 사용할 수 있다.




인-플레이스(Inplace) / 아웃-플레이스(Out-of-place)


첫 번째 차이점은 텐서의 모든 인-플레이스 연산은 _를 postfix 방식으로 표시한다는 점이다. 예를 들어, add는 아웃-플레이스 연산을 하고, add_는 인-플레이스 연산을 한다.


- 소스

a.fill_(3.5)
# a has now been filled with the value 3.5

b = a.add(4.0)
# a is still filled with 3.5
# new tensor b is returned with values 3.5 + 4.0 = 7.5

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-인덱싱[각주:1](Zero Indexing)


또 다른 차이점은 텐서는 0-인덱스라는 것이다. lua에서 텐서는 1-인덱스[각주:2]이다.

- 소스

b = a[0, 3]  # select 1st row, 4th column from a


또한 텐서는 파이썬의 슬라이싱을 이용하여 인덱스가 가능하다.

- 소스

b = a[:, 3:5]  # selects all rows, 4th column and  5th column from a




카멜 표기법 없음(No camel casing)


이 외에도 카멜 표기법을 사용하지 않는다는 소소한 차이점도 있다. 예를 들어 indexAdd index_add_가 된다.


카멜표기법이란?

  • 단봉 낙타 표기법이라고도 함
  • 각 단어의 첫 문자를 대문자로 표기하고 붙여쓰되, 맨처음 문자는 소문자로 표기
  • 띄어쓰기 대신 대문자로 단어를 구분
  • 예시: backgroundColor, typeName, iPhone
출처 : https://goo.gl/2D5sgN

- 소스

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 변환 (Numpy Bridge)


torch 텐서를 numpy 배열로, 혹은 반대로 변환하는 것은 꽤 쉬운 작업이다. torch 텐서와 numpy 배열은 기본적인 저장 공간(메모리 공간)를 공유하기 때문에 하나를 변경하면 다른 하나도 자동으로 변경 된다.



torch 텐서 -> numpy 배열로 변환 ( Converting torch Tensor to numpy Array)


- 소스

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)    # see how the numpy array changed in value 

- 결과

tensor([ 2.,  2.,  2.,  2.,  2.])
[2. 2. 2. 2. 2.]




numpy 배열 -> torch 텐서로 변환 ( Converting numpy Array to 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)  # see how changing the np array changed the torch Tensor automatically 

- 결과

[2. 2. 2. 2. 2.]
tensor([ 2.,  2.,  2.,  2.,  2.], dtype=torch.float64)


CharTensor를 제외한 CPU의 모든 텐서는 NumPy로 변환할 수 있고, 그 반대의 경우(numpy->텐서)도 가능하다.




CUDA 텐서 ( CUDA Tensors )


CUDA 텐서는 pytorch에서 손쉽게 사용할 수 있으며, CUDA 텐서를 CPU에서 GPU로 옮겨도 기본 형태(underlying type)는 유지 된다.

- 소스

# let us run this cell only if CUDA is available
if torch.cuda.is_available():

    # creates a LongTensor and transfers it
    # to GPU as torch.cuda.LongTensor
    a = torch.full((10,), 3, device=torch.device("cuda"))
    print(type(a))
    b = a.to(torch.device("cpu"))
    # transfers it to CPU, back to
    # being a torch.LongTensor 

- 결과

< class 'torch.Tensor'>


  1. C 언어의 배열처럼 시작 오프셋이 '0' 이라는 의미. 0-based Numbering 이라고도 한다. [본문으로]
  2. 우리가 일상 생활에서는 사용하는 방식으로, 뭔가 시작 숫자가 '1' [본문으로]
Comments