Deep Learning with PyTorch: A 60 Minutes Blitz (2) – Autograd: automatic differentiation
http://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html
Deep Learning with PyTorch: A 60 Minute Blitz
Autograd: automatic differentiation
PyTorch에서 모든 신경망의 중심에는 autograd
패키지가 있습니다. 이것에 대해 간단히 알아본 다음, 우리의 첫 신경망을 학습시켜보도록 하겠습니다.
audograd
패키지는 Tensor의 모든 연산에 대해서 자동 편미분 기능을 제공합니다. 이것은 define-by-run 방식의 프레임워크입니다. 즉, 코드가 어떻게 실행되고 있는지에 따라 역전파(backprop)가 정의되며, 따라서 매 반복마다 이것이 변화할 수 있음을 의미합니다.
예제와 함께 좀 더 간단한 설명으로 알아봅시다.
Variable
autograd.Variable
은 패키지의 중심 클래스입니다. 이는 Tensor를 감싸고 있으며, 정의되어있는 거의 모든 연산을 지원합니다. 하고자 하는 계산이 끝났을 때, .backward()
를 실행하면 자동적으로 계산된 모든 그래디언트를 얻을 수 있습니다.
가공 전의 텐서(raw tensor)에 .data
애트리뷰트를 통해 접근할 수 있습니다. 또한 이 변수와 관련된 그래디언트는 .grad
에 누적됩니다.
autograd 기능과 관련된 또 하나의 굉장히 중요한 클래스가 있습니다. 바로 Function
입니다.
Variable
과 Function
은 서로 연결되어있습니다. 이 둘은 acyclic graph를 통해 만들어져 있고, 이를 통해 계산 과정을 저장해 두고 있습니다. 각 variance은 .grad_fn
애트리뷰트를 가지는데, 이는 Variable
을 만든 Function
을 참조하고 있습니다. 단, 사용자에 의해 만들어진 Variable은 예외입니다. 이 경우 grad_fn
은 None
입니다.
도함수를 계산하기 위해서는, .backward()
를 Variable
에서 실행하면 됩니다. Variable
이 스칼라 값이라면, 그러니까 단 하나의 요소를 갖는 데이터라면 backward()
에 매개변수를 넣어줄 필요가 없습니다. 하지만 그렇지 않고 더 많은 요소를 갖는다면 크기를 맞춰주기 위한 텐서를 grad_output
매개변수를 입력하여 주어야 합니다.
1 2 3 |
import torch from torch.autograd import Variable |
Variable을 만듭니다.
1 2 3 |
x = Variable(torch.ones(2, 2), requires_grad=True) print x |
Out:
12345 Variable containing:1 11 1[torch.FloatTensor of size 2x2]
Variable에 연산을 시켜봅니다.
1 2 3 |
y = x + 2 print(y) |
Out:
12345 Variable containing:3 33 3[torch.FloatTensor of size 2x2]
y
가 연산의 결과로 생성되었습니다. 그리고 grad_fn
도 가지고 있습니다.
1 2 |
print(y.grad_fn) |
Out:
12 <AddBackward0 object at 0x7ff91b4f0908>
y
에 연산을 더 해봅시다.
1 2 3 4 5 |
z = y * y * 3 out = z.mean() print(z, out) |
Out:
12345678 Variable containing:27 2727 27[torch.FloatTensor of size 2x2]Variable containing:27[torch.FloatTensor of size 1]
Gradients
이제 역전파를 해 봅시다. out.backward()
를 실행하면 됩니다. 또한 out.backward(torch.Tensor([1.0]))
도 똑같은 결과를 갖습니다.
1 2 |
out.backward() |
그래디언트 d(out)/dx를 출력해봅시다.
1 2 |
print(x.grad) |
Out:
12345 Variable containing:4.5000 4.50004.5000 4.5000[torch.FloatTensor of size 2x2]
4.5
로 채워진 행렬을 얻었을 것입니다. out
Variable을 "$o$"라고 해봅시다. 우리가 계산한 것은 $o = \frac{1}{4} \sum_i z_i, z_i = 3(x_i + 2)^2$으로 계산된 것이고, $z_i|_{x_i=1}=27$ 입니다. 따라서 $\frac{\partial o}{\partial x_i}=\frac{3}{2}(x_i + 2)$이므로, $\frac{\partial o}{\partial x_i}\bigr\rvert_{x_i=1} = \frac{9}{2} = 4.5$가 계산되었습니다.
더 복잡한 짓들을 해도 autograd가 알아서 잘 해줍니다!
1 2 3 4 5 6 7 8 9 |
x = torch.randn(3) x = Variable(x, requires_grad=True) y = x * 2 while y.data.norm() < 1000: y = y * 2 print(y) |
Out:
123456 Variable containing:164.9539-511.5981-1356.4794[torch.FloatTensor of size 3]
1 2 3 4 5 |
gradients = torch.FloatTensor([0.1, 1.0, 0.0001]) y.backward(gradients) print(x.grad) |
Out:
123456 Variable containing:204.80002048.00000.2048[torch.FloatTensor of size 3]
읽을거리
Variable
과 Function
과 관련된 문서는 http://pytorch.org/docs/autograd에 있습니다.