Autograd: 미분 자동화

ML 문서 번역 > PyTorch Tutorial > PyTorch와 함께하는 딥러닝: 60분 리뷰 > Autograd: 미분 자동화


PyTorch으로 만든 모든 신경망의 중심에는 autograd 패키지가 있습니다. 먼저 autograd 패키지를 간략히 살펴보겠습니다. 그리구 다음 문서에서 첫 번째 신경망을 훈련해 보겠습니다.

autograd 패키지는 Tensor로 수행한 모든 연산에 대하여 자동-미분(Autimatic differentiation) 기능을 제공합니다. autograd는 실행 시점에 정의되는(define-by-run) 프레임워크입니다. 이것은 코드가 어떻게 실행되는가에 따라서 역전파(backprop)가 정의됨을 의미합니다. 즉 반복마다1 역전파가 달라질 수 있다는 것을 의미합니다.

좀 더 간단한 용어로 몇 가지 예를 들어 보겠습니다.

Variable

autograd.Variable은 autograd 패키지의 핵심 클래스입니다. Variable 클래스는 Tensor를 감싸고 있으며, Tensor에 정의된 거의 모든 연산을 지원합니다. 모든 계산을 마친 후에 .backward()를 호출하면, 자동으로 모든 기울기가 계산됩니다.

Variable 객체의 .data 속성으로 Tensor의 실제 데이터에 접근할 수 있습니다. Variable에 대한 기울기는 .grad 속성에 저장됩니다.

autograd 구현에 있어서 중요한 클래스가 하나 더 있습니다. 바로 Function 입니다.

Variable과 Function 클래스는 상호 연결되어 있고 비순환 그래프를 구성합니다. 연산을 위한 완전한 히스토리를 담고 있습니다. 각 Variable 객체에는 .grad_fn 속성이 있습니다. 이 속성은 해당 Variable 객체를 생성하는 Function 객체를 참조합니다. (예외 상황, Variable을 사용자가 직접 생성한 경우에는 grad_fn이 값은 None입니다.)

미분계수를 계산해야 한다면, Variable 객체의 .backward()를 호출합니다. Variable이 스칼라 일 경우(한 개의 요소만을 갖는 상황)에는, backward()에 별도 인자를 지정할 필요가 없습니다. 이와 다르게 여러 요소를 갖는다면, 텐서의 크기를 gradient 인수로 지정해야 합니다.

import torch
from torch.autograd import Variable
  • Variable 생성
x = Variable(torch.ones(2, 2), requires_grad=True)
print(x)

출력:

Variable containing:
 1  1
 1  1
[torch.FloatTensor of size 2x2]
  • Variable 연산 수행
y = x + 2
print(y)

출력:

Variable containing:
 3  3
 3  3
[torch.FloatTensor of size 2x2]
  • 앞의 연산으로 부터 y 객체가 생성되었습니다. 이 객체의 grad_fn 속성을 다음과 같이 확인할 수 있습니다.
print(y.grad_fn)

출력:

<AddBackward0 at 0x7f349c9857f0>
  • y 에 추가 연산을 적용합니다.
z = y * y * 3
out = z.mean()

print(z)
print("---"*5)
print(out)

출력:

Variable containing:
 27  27
 27  27
[torch.FloatTensor of size 2x2]

---------------
Variable containing:
 27
[torch.FloatTensor of size 1]
  • y was created as a result of an operation, so it has a grad_fn
print(y.grad_fn)

출력:

<AddBackward0 object at 0x7f6fdf69f390>

y에 추가 연산을 적용할 수 있습니다.

z = y * y * 3
out = z.mean()

print(z, out)

출력:

Variable containing:
 27  27
 27  27
[torch.FloatTensor of size 2x2]
 Variable containing:
 27
[torch.FloatTensor of size 1]

Gradients

역전파를 해보겠습니다. out.backward()과 out.backward(torch.Tensor([1.0]))은 동일하게 동작합니다.

out.backward()

기울기 $ \frac{d(out)}{dx} $를 다음과 같이 출력할 수 있습니다.

print(x.grad)

출력:

Variable containing:
 4.5000  4.5000
 4.5000  4.5000
[torch.FloatTensor of size 2x2]

값이 4.5인 행렬이 출력됩니다. out Variable을 “o”로 부르겠습니다. “0”를 수식을 다음과 같이 정리할 수 있습니다.

  • $ o = \frac{1}{4} \sum_i z_i $
  • $ z_i = 3(x_i + 2)^2 $
  • $ z_i \rvert _{x_i=1} = 27 $

따라서, 이 기울기는 다음과 같이 정리할 수 있습니다.

  • $ \frac{\partial o}{\partial x_i} = \frac{2}{3}(x_i + 2) $
  • $ \frac{\partial o}{\partial x_i} \rvert _{x_i=1} = \frac{9}{2} = 4.5 $

자동 기울기 계산(autograd) 기능을 가지고 재미있는 일을 할 수 있습니다. 2

x = torch.randn(3)
x = Variable(x, requires_grad=True)

y = x * 2
while y.data.norm() < 1000:
    y = y * 2

print(y)

출력:

Variable containing:
  864.9241
   13.0149
-1114.6173
[torch.FloatTensor of size 3]
gradients = torch.FloatTensor([0.1, 1.0, 0.0001])
y.backward(gradients)

print(x.grad)

출력:

Variable containing:
  102.4000
 1024.0000
    0.1024
[torch.FloatTensor of size 3]

다음에 읽어 볼거리

VariableFunction에 대한 문서는 다음에서 찾을 수 있습니다.

코드 다운로드


  1. 역자주 - Weight와 Bias가 업데이트 되는 단위 Mini-Batch를 의미합니다. [return]
  2. 역자주 - 첫 번째 예제는 3개의 난수 배열을 만들고 L2 Norm이 1,000이 될 때 까지 y 값을 증가 시키는 코드입니다. 두 번째 예제는 3개의 난 수 배열을 만들고 각 요소의 기울기를 구하는 코드입니다. [return]
김태완 avatar
작성자: 김태완
1999년 부터 Java, Framework, Middleware, SOA, DB Replication, Cache, CEP, NoSQL, Big Data, Cloud를 키워드로 살아왔습니다. 현재는 빅데이터와 Machine Learning을 중점에 두고 있습니다.
E-mail: taewanme@gmail.com