2018년 7월 1일 일요일

PyTorch 예제 시작해 보기



설치는 앞에서 해보았고, 여기에서 예제를 따라가면서 해보도록 한다. 이것은 완전 초짜의 따라가기이며 나의 생각입니다.

공부전 나의 상태

Python : 공부한적은 있지만 아주 아주 초급 문법만 사용함...
TensorFlow : 공부한적은 있지만 아주 초급 문법도 사용할줄 모르는 상태
PyTorch : 쌩판 모름

공부 대상

https://pytorch.org/tutorials/beginner/blitz/tensor_tutorial.html#sphx-glr-beginner-blitz-tensor-tutorial-py

Getting Started

텐서(Tensors)

Tensors are similar to NumPy’s ndarrays, with the addition being that Tensors can also be used on a GPU to accelerate computing.
텐서는 NumPy의 ndarrays와 같다고 하는데, NumPy를 사용안해봐서 뭔진 모르겠고, 검색해보니 다차원 배열을 다루는것이라고 이해하면 되는데 사용법이 NumPy와 비슷하다는 얘기인데, GPU가속 계산까지 할 수 있다니... 엄청 좋은가 보다!! 그러나 현실은 아무것도 모르는 상태인데....

계속해서 사용법은 아래와 같이 하면 된다고 한다. 그런데 예제를 두개로 분리해놓은걸 보니 순수하게 실행코드와 주변 코드를 분리해놓은것 같다.

from __future__ import print_function
import torch

x = torch.empty(5, 3)
print(x)

import는 java에서 많이 나오는것이라 python도 비슷할것 같고 from은 import하는데 필요한 함수만 가져올때 사용한다고 하네요.

이것을 실행시키면 아래와 같다고 하는데 실제 해보면, 할때마다 값이 다른걸 알 수 있다.
초기화를 한적이 없으니...
Out:
tensor([[ 3.2401e+18,  0.0000e+00,  1.3474e-08],
        [ 4.5586e-41,  1.3476e-08,  4.5586e-41],
        [ 1.3476e-08,  4.5586e-41,  1.3474e-08],
        [ 4.5586e-41,  1.3475e-08,  4.5586e-41],
        [ 1.3476e-08,  4.5586e-41,  1.3476e-08]])
Java에서는 에러가 났을텐데 친절히 초기화 되지 않은 값을 보여주는데... 간혹 에러가 나는경우가 있다. 들어있는값이 string 출력하는데 문제가 있어서 그런것 같은데, 이런 에러는 그냥 무시하자.

에러 나는 경우)
(base) E:>python example1.py
Traceback (most recent call last):
  File "example1.py", line 5, in <module>
    print(x)
  File "E:\ProgramData\Anaconda3\lib\site-packages\torch\tensor.py", line 57, in __repr__
    return torch._tensor_str._str(self)
  File "E:\ProgramData\Anaconda3\lib\site-packages\torch\_tensor_str.py", line 218, in _str
    fmt, scale, sz = _number_format(self)
  File "E:\ProgramData\Anaconda3\lib\site-packages\torch\_tensor_str.py", line 96, in _number_format
    if value != math.ceil(value.item()):
RuntimeError: Overflow when unpacking long

torch.empty(행, 열) <= 초기화 안된 배열을 만듭니다.

차원이 커진다면 다음과 같은 형태를 가집니다. torch.empty(ND, ... , 3D ,2D, 1D)

아래는 함수 이름만 봐도 이해가 갈것 같다.
랜덤한 값을 가지도록
x = torch.rand(5, 3)
print(x)
이건 초기값을 0을 가지도록, 그런데 뒤에 dtype이란게 있네 이건 배열의 초기값을 long형태를 취한다고 보면 되네...호호호 껌이네...
x = torch.zeros(5, 3, dtype=torch.long)
print(x)
직접 값을 넣고 싶을땐아래처럼 tensor라고 해주면 되네...  차원 설정도 정의된대로 되는것 같네 이거 완전 꿀인데...
x = torch.tensor([5.5, 3])
print(x)

그 다음 아래 예제는 뭔가 복잡하고 이해가 안되는데
x = x.new_ones(5, 3, dtype=torch.double)      # new_* methods take in sizes
print(x)
new_ones는 뒤쪽 크기로 텐서를 만들고 해당값을 1=one 값을 넣는것 이다.
tensor([[ 1.,  1.,  1.],
        [ 1.,  1.,  1.],
        [ 1.,  1.,  1.],
        [ 1.,  1.,  1.],
        [ 1.,  1.,  1.]], dtype=torch.float64)
아래는 기존에 들어있는 텐서 크기를 사용해서 새로운 텐서를 만든다. 여기서는 랜덤..
x = torch.randn_like(x, dtype=torch.float)    # override dtype!
print(x)                                      # result has the same size
끝으로 텐서 크기를 알고자 한다면 size라는 메소드가 있다. 이건 어딜가나 비슷한것 같은데 다차원 배열이다보니 넘어오는 형태가 튜플 형태라고 하는데.. "[ 값, 값 ]" 으로 표기되지만 튜플이라고 하네요. 튜플은 ( ) 형태인데 좀 이상하긴합니다.
print(x.size())

torch.Size([5, 3])

연산(Operations)

There are multiple syntaxes for operations. In the following example, we will take a look at the addition operation.
앞에서 텐서를 정의하고 초기화 하는 방법들에 대해서 알아봤는데 여기에서는 연산 하는 방법에 대해서 나옵니다.

y = torch.rand(5, 3)

직접 더해도 되고,
print(x + y)

함수를 호출 해도 되는데
print(torch.add(x, y))

특정 위치에 저장하고 싶다면 아래 처럼 out을 미리 설정할 수 있다네....
result = torch.empty(5, 3)
torch.add(x, y, out=result)
print(result)
y=y+x 인것 같은데 이런형태 자주 쓸라나 모르겠네요.
# adds x to y
y.add_(x)
print(y)
그러면서 "_" 가 붙어있으면 위의 예처럼 y값이 변화되는 연산이라고 하네요
x.copy_(y) 여기에서는 x가 결과로 변화됨

그 다음 예제가 NumPy 에 있는것과 비슷하다고 하는데 NumPy와 비슷한지는 모르겠고, 좀더 많은 예제를 만들어서 테스트 했습니다.
print(x[:, 1])

:, N 예제)
from __future__ import print_function
import torch

x = torch.rand(5, 3)
print(x)

print(x[:,0])
print(x[:,1])
print(x[:,2])

print(x[0,:])
print(x[1,:])
결과)
(base) E:\>python example1.py
tensor([[ 0.0254,  0.6270,  0.4110],
        [ 0.7731,  0.2483,  0.6898],
        [ 0.7789,  0.8019,  0.0666],
        [ 0.5805,  0.8569,  0.9948],
        [ 0.1684,  0.8373,  0.2113]])
tensor([ 0.0254,  0.7731,  0.7789,  0.5805,  0.1684])
tensor([ 0.6270,  0.2483,  0.8019,  0.8569,  0.8373])
tensor([ 0.4110,  0.6898,  0.0666,  0.9948,  0.2113])
tensor([ 0.0254,  0.6270,  0.4110])
tensor([ 0.7731,  0.2483,  0.6898])

하나만 놓고 생각해보면 배열의 고정된 위치의 값들을 하나의 tensor 형태로 돌려줍니다.
tensor([[ 0.0254,  0.6270,  0.4110],
        [ 0.7731,  0.2483,  0.6898],
        [ 0.7789,  0.8019,  0.0666],
        [ 0.5805,  0.8569,  0.9948],
        [ 0.1684,  0.8373,  0.2113]])
print(x[:,2])

형태를 변형하고 싶을때 torch.view 를 사용한다고 합니다.
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8)  # the size -1 is inferred from other dimensions
print(x.size(), y.size(), z.size())
특이점은 -1 이 들어가는 부분인데 크기가 안맞으면 알아서 나오는 부분이라고 하네요
Out:
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])
하나짜리 텐서에 값을 item이란 함수를 호출하면 값형태로 얻을 수 있습니다.
꼭 크기가 1자리 텐서여야 합니다.
x = torch.randn(1)
print(x)
print(x.item())
Out:
tensor([ 1.3159])
1.3159412145614624
다음과 같이는 동작하지 않습니다. (print(x.[0,0].item()))


NumPy 연결 (NumPy Bridge)

이게 뭔말인고 하니, Torch 텐서와 연결된 NumPy 변수는 Torch 텐서 변수가 변경되면 같이 변경된다고하네요.

ones는 1을 의미하고 5는 5개짜리 배열을 의미합니다.

a = torch.ones(5)
print(a)
Out:
tensor([ 1.,  1.,  1.,  1.,  1.])
연결할때는 numpy() 함수를 사용해서 아래와 같이 해놓으면 a값이 변하면 b도 자동으로 변경됩니다.

b = a.numpy()
print(b)
Out:
[1. 1. 1. 1. 1.]
a에 1을 더하기
a.add_(1)
print(a)
print(b)

결과 a도 변하고 b도 변하고.... 반대로 b를 변경해도 a가 변합니다.
Out:
tensor([ 2.,  2.,  2.,  2.,  2.])
[2. 2. 2. 2. 2.]
from __future__ import print_function
import torch

a = torch.ones(5)
print(a)

b = a.numpy()
print(b)

a.add_(1)
print(a)
print(b)

b[0]=b[0]+1
print(a)
print(b)

a[0]=a[0]+1
print(a)
print(b)
결과)
(base) E:\>python example1.py
tensor([ 1.,  1.,  1.,  1.,  1.])
[1. 1. 1. 1. 1.]
tensor([ 2.,  2.,  2.,  2.,  2.])
[2. 2. 2. 2. 2.]
tensor([ 3.,  2.,  2.,  2.,  2.])
[3. 2. 2. 2. 2.]
tensor([ 4.,  2.,  2.,  2.,  2.])
[4. 2. 2. 2. 2.]


NumPy배열을 Torch텐서로 변경(Converting NumPy Array to Torch Tensor)

b = torch.form_numpy(a)함수를 사용하면 numpy 배열을 사용할 수 있다고하는데 이렇게 되면 a, b가 연결이 됩니다.

import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)
Out:
[2. 2. 2. 2. 2.]
tensor([ 2.,  2.,  2.,  2.,  2.], dtype=torch.float64)
예제)
from __future__ import print_function
import torch

import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)

b[0]=b[0]+1
print(a)
print(b)

a[0]=a[0]+1
print(a)
print(b)
결과)
(base) E:\>python example1.py
[2. 2. 2. 2. 2.]
tensor([ 2.,  2.,  2.,  2.,  2.], dtype=torch.float64)
[3. 2. 2. 2. 2.]
tensor([ 3.,  2.,  2.,  2.,  2.], dtype=torch.float64)
[4. 2. 2. 2. 2.]
tensor([ 4.,  2.,  2.,  2.,  2.], dtype=torch.float64)

All the Tensors on the CPU except a CharTensor support converting to NumPy and back.
끝으로 CPU 텐서들이 NumPy 컨버팅을 제공 한다고 하는데, GPU는 되는지 자세한 설명은 없습니다. GPU가 없어서 테스트는 못해봤습니다.




댓글 없음:

댓글 쓰기