Pytorch 기초 1탄!


이번 게시글은 파이토치(Pytorch) 2. autograd 와 Variable영상과 PyTorch로 딥러닝하기: 60분만에 끝장내기 블로그를 참고했습니다.

아래의 코드를 주피터랩이나 터미널에 코드를 입력해준다. (주피터랩에서 작성하려면 맨앞에 ‘!’를 붙여줘야한다.)

pip3 install torch torchvision


파이토치(Pytorch)란?

파이썬 기반의 오픈소스 머신러닝 라이브러리로 딥러닝 연구 플랫폼으로 사용되기도 하며 GPU를 제대로 이용하기 위한 Numpy의 대체로도 사용된다.(Numpy스러운 Tensor연산)

간결하고 구현이 빨리되어 텐서플로우보다 익히기 쉽다는 특징이 있다.


파이토치 주요 패키지

패키지 내용
torch 강력한 GPU 지원 기능을 갖춘 Numpy 같은 Tensor 라이브러리
torch.nn 딥러닝 모델에 필요한 모듈이 모아져있음(nn.Linear, nn.ReLU)
torch.autograd Tensor의 모든 연산에 대해 자동 미분을 제공
torch.optim 학습에 관련된 optimizing method가 있는 패키지(SGA, RMSProp, Adam 등)
torch.utils.data batch generator 등 학습 데이터에 관련된 패키지


Pytorch

Tensors

Tensor는 Numpy ndarray와 유사할 뿐만 아니라 GPU를 사용한 연산 가속도 지원한다.

  • 아래의 코드처럼 import를 해준다.
from __future__ import print_function
import numpy as np
import torch
  • numpy처럼 torch도 arange함수를 사용할 수 있다.
>> nums = torch.arange(6)
tensor([0, 1, 2, 3, 4, 5])
  • nums의 shape를 확인
>> nums.shape
torch.Size([6])
  • Torch 타입을 Numpy로 변환
>> nums.numpy()
array([0, 1, 2, 3, 4, 5])
  • Shape를 바꿔줄 수 있음
>> nums.reshape(3,2)
tensor([[0, 1],
        [2, 3],
        [4, 5]])
  • random하게 생성도 가능
>> random = torch.rand((3,3))
>> random
tensor([[0.0608, 0.6244, 0.2717],
        [0.1841, 0.8706, 0.7808],
        [0.9785, 0.3192, 0.0319]])
  • view는 reshape와 같은 역할
>> num_arange = torch.arange(9)
>> num_arange
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8])
>> num_arange.view(3,3)
tensor([[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]])


Autograd : 자동 미분

파이토치의 모든 신경망 중심에는 autograd 패키지가 있다. autograd는 backprop를 위한 Tensor의 모든 연산에 대해 자동 미분을 제공한다. 실행-기반-정의(define-by-run) 프레임워크로 코드를 어떻게 작성해서 실행하느냐에 따라 역전파가 정의된다는 뜻이며 역전파는 학습과정의 매 단계마다 달라진다.

Autograd를 사용할 때, 신경망의 순전파 단계는 연산 그래프 를 정의한다. (그래프의 노드(Node)는 Tensor이며, 엣지(Edge)는 입력 Tensor로부터 출력 Tensor를 만들어내는 함수)


변수(Variable)

autograd.Variable : Tensor를 감싸고 있으며, Tensor 기반으로 정의된 거의 대부분의 연산을 지원한다.(자동계산을 위해 사용)

연산 후 .backward()를 호출하여 모든 변화도(gradient)을 자동으로 계산할 수 있다.

autograd.Variable 안에 data, grad, grad_fn이 존재한다.

1) data : Tensor형태의 데이터가 담김
2) grad : Data가 거쳐온 layer에 대한 미분값이 축적됨
3) grad_fn : 미분 값을 계산한 함수에 대한 정보

.data 속성을 사용하여 tensor자체에 접근할 수 있으며, 이 변수와 관련된 변화도는 .grad에 누적된다.

Pytorch tensor를 Variable 객체로 감싸게 되면, 이 Variable이 연산 그래프에서 노드로 표현된다. 예를 들어 x가 Variable 일 때 x.data는 그 값을 가지는 Tensor이며 x.grad는 어떤 스칼라 값에 대해 x에 대한 변화도를 갖는 또 다른 Variable이다.


코드 설명

import torch
from torch.autograd import Variable


  • 1의 값을 가진 2행 2열의 tensor생성
>> a = torch.ones(2,2)
>> print(a)
tensor([[1., 1.],
        [1., 1.]])


  • a 값이 gradient가 필요하다 라는 뜻
>> a = Variable(a, requires_grad=True) 
>> print(a)
tensor([[1., 1.],
        [1., 1.]], requires_grad=True)


  • Variable은 3가지를 가진다(data, grad, grad_fn)
>> print('a.data : ')
>> print(a.data)
>> print('a.grad : ')
>> print(a.grad)
>> print('a.grad_fn : ')
>> print(a.grad_fn)
a.data : 
tensor([[1., 1.],
        [1., 1.]])
a.grad : 
None
a.grad_fn : 
None


>> b = a+2
>> print(b)
tensor([[3., 3.],
        [3., 3.]], grad_fn=<AddBackward0>)


>> c=b**2
>> print(c)
tensor([[9., 9.],
        [9., 9.]], grad_fn=<PowBackward0>)


>> out = c.sum()
>> print(out)
tensor(36., grad_fn=<SumBackward0>)


  • backward()
    >> print(out)
    >> out.backward()
    
tensor(36., grad_fn=<SumBackward0>)


  • grad_fn 이 None인 이유는 아직까지 a가 직접적으로 수행한 연산이 없기때문에 gradient를 수행하지 않았기 때문
    >> print('a.data : ')
    >> print(a.data)
    >> print('a.grad : ')
    >> print(a.grad)
    >> print('a.grad_fn : ')
    >> print(a.grad_fn)
    
a.data : 
tensor([[1., 1.],
        [1., 1.]])
a.grad : 
tensor([[6., 6.],
        [6., 6.]])
a.grad_fn : 
None


  • b.grad_fn :

<AddBackward0 object at 0x129550350> : add 연산에 대해 backward를 했다는 뜻

>> print('b.data : ')
>> print(b.data)
>> print('b.grad : ')
>> print(b.grad)
>> print('b.grad_fn : ')
>> print(b.grad_fn)
b.data : 
tensor([[3., 3.],
        [3., 3.]])
b.grad : 
None
b.grad_fn : 
<AddBackward0 object at 0x129550350>


>> print('c.data : ')
>> print(c.data)
>> print('c.grad : ')
>> print(c.grad)
>> print('c.grad_fn : ')
>> print(c.grad_fn)
c.data : 
tensor([[9., 9.],
        [9., 9.]])
c.grad : 
None
c.grad_fn : 
<PowBackward0 object at 0x1298ed6d0>


>> print('out.data : ')
>> print(out.data)
>> print('out.grad : ')
>> print(out.grad)
>> print('out.grad_fn : ')
>> print(out.grad_fn)
out.data : 
tensor(36.)
out.grad : 
None
out.grad_fn : 
<SumBackward0 object at 0x1296cb2d0>