본문 바로가기
  • AI 개발자가 될래요
Deep Learning

[딥러닝] pytorch의 autograd 란?

by 꿀개 2022. 10. 6.

 

 

torch.autograd 는 신경망 학습을 지원하는 PyTorch의 자동 미분 엔진이다.

autograd가 신경망 학습을 어떻게 돕는지에 대해 알아보도록 하자.

 

신경망의 학습

일단 autograd에 대해 알아보기 앞서 신경망의 학습에 대해 알아보자. 크게 2단계로 나눠진다:

 

- 순전파(Forward Propagation): 정답을 맞추기 위해 추측하는 단계.

 

- 역전파(Backward Propagation)

: 추측한 값에서 발생한 오류에 비례하여 매개변수들을 적절히 조절하는 단계.

  출력으로부터 역방향으로 이동하면서 오류에 대한 함수들의 매개변수들의 미분값(gradient)을 수집하고, 매개변수들을 최적화.

 

모델의 예측값과 그에 해당하는 정답(label)을 사용하여 오차(loss)를 계산하고, 역전파하는 과정에서 autograd가 사용된다. autograd가 parameter의 .grad 속성에, 모델의 각 parameter에 대한 gradient를 계산하고 저장하는것이다.

 

autograd가 어떻게 gradient를 수집하는가?

requires_grad=True를 갖는 2개의 텐서(tensor) a 와 b 를 예로 들어보자.

여기서 requires_grad=True 는 autograd 에 모든 연산들의 gradient를 계산해야 한다고 알려주는 속성이다.

import torch

a = torch.tensor([2., 3.], requires_grad=True)
b = torch.tensor([6., 4.], requires_grad=True)

 

a 와 b 로부터 새로운 텐서 Q 를 만든다.

Q = 3*a**3 - b**2

 

a 와 b 가 모두 신경망의 parameter이고, Q 가 오차라고 가정해보자.

신경망을 학습할 때, 아래와 같이 매개변수들에 대한 오차의 gradient를 구해야 한다.

 

$\frac{\partial Q}{\partial a} = 9a^2$
 
$\frac{\partial Q}{\partial b} = -2b$
 

Q 에 대해서 .backward() 를 호출할 때, autograd는 이러한 gradient들을 계산하고 이를 각 텐서의 .grad 속성에 저장한다. Q 는 벡터(vector)이므로 Q.backward() 에 gradient를 명시적으로 전달해야 한다. gradient 는 Q 와 shape이 같은 텐서로, Q에 대한 gradient를 나타낸다. 

 

변화도는 a.grad 와 b.grad 에 저장된다.

 

수학적인 관점에서

수학적으로, 벡터 함수 $\vec{y}=f(\vec{x})$ 에서 $\vec{x}$ 에 대한 $\vec{y}$ 의 gradient는 야코비안 행렬(Jacobian Matrix) $J$ 이다:

 

$J = \left(\begin{array}{cc} \frac{\partial \bf{y}}{\partial x_{1}} & ... & \frac{\partial \bf{y}}{\partial x_{n}} \end{array}\right) = \left(\begin{array}{ccc} \frac{\partial y_{1}}{\partial x_{1}} & \cdots & \frac{\partial y_{1}}{\partial x_{n}}\\ \vdots & \ddots & \vdots\\ \frac{\partial y_{m}}{\partial x_{1}} & \cdots & \frac{\partial y_{m}}{\partial x_{n}} \end{array}\right)$

 

일반적으로, torch.autograd 는 벡터-야코비안 곱을 계산하는 엔진이다. 이는, 주어진 어떤 벡터 $\vec{v}$ 에 대해 $J^{T}\cdot \vec{v}$을 연산한다.

 

만약 $\vec{v}$ 가 스칼라 함수 $l=g\left(\vec{y}\right)$ 의 gradient인 경우:

 

$\vec{v} = \left(\begin{array}{ccc}\frac{\partial l}{\partial y_{1}} & \cdots & \frac{\partial l}{\partial y_{m}}\end{array}\right)^{T}$
 

이며, 연쇄 법칙(chain rule)에 따라, 벡터-야코비안 곱은 $\vec{x}$ 에 대한 $l$ 의 변화도(gradient)가 된다:

 

$J^{T}\cdot \vec{v}=\left(\begin{array}{ccc} \frac{\partial y_{1}}{\partial x_{1}} & \cdots & \frac{\partial y_{m}}{\partial x_{1}}\\ \vdots & \ddots & \vdots\\ \frac{\partial y_{1}}{\partial x_{n}} & \cdots & \frac{\partial y_{m}}{\partial x_{n}} \end{array}\right)\left(\begin{array}{c} \frac{\partial l}{\partial y_{1}}\\ \vdots\\ \frac{\partial l}{\partial y_{m}} \end{array}\right)=\left(\begin{array}{c} \frac{\partial l}{\partial x_{1}}\\ \vdots\\ \frac{\partial l}{\partial x_{n}} \end{array}\right)$