Autograd를 활용한 간단한 예제

Autograd 개요

PyTorch의 autograd는 텐서 연산에 대해 자동으로 미분을 계산할 수 있도록 해주는 기능입니다. 이 기능은 텐서의 연산 기록을 추적하여, 역전파(Backpropagation)를 통해 기울기(Gradient)를 계산할 수 있습니다. 모든 텐서는 기본적으로 연산 그래프의 노드로 작동하며, requires_grad 속성을 통해 기울기 계산이 필요한 텐서인지 여부를 설정할 수 있습니다.

간단한 선형 회귀 모델 예제

선형 회귀 모델은 가장 기본적인 기계 학습 모델 중 하나로, 독립 변수 $\mathbf{x}$와 종속 변수 $y$ 사이의 관계를 직선 형태로 모델링합니다. 여기서는 $y = wx + b$ 형태의 간단한 선형 모델을 설정하고, PyTorch의 autograd를 활용해 기울기를 계산하는 과정을 살펴보겠습니다.

수학적 배경

먼저 선형 회귀 모델에서 예측 값 $\hat{y}$는 다음과 같이 정의됩니다.

[ \hat{y} = w x + b ]

여기서:

  • $w$: 가중치 (Weight)

  • $b$: 편향 (Bias)

  • $x$: 입력 값 (Input)

손실 함수로는 평균 제곱 오차(MSE)를 사용할 것입니다. 손실 함수 $L$은 다음과 같이 정의됩니다.

[ L = \frac{1}{N} \sum_{i=1}^{N} (y_i - \hat{y}i)^2 = \frac{1}{N} \sum{i=1}^{N} (y_i - (w x_i + b))^2 ]

여기서:

  • $N$: 데이터의 총 개수

  • $y_i$: 실제 출력 값 (Actual Output)

  • $\hat{y}_i$: 예측된 출력 값 (Predicted Output)

PyTorch 구현

다음으로, 이를 코드로 구현해 보겠습니다. PyTorch에서는 손실 함수를 직접 계산하고 autograd를 통해 기울기를 자동으로 계산할 수 있습니다.

그래프의 역할과 계산 그래프

위 코드에서 autograd는 텐서들의 연산을 기록하여, 이들을 통해 생성된 그래프를 구성합니다. 이를 통해 역전파 시, 그래프를 탐색하며 각 파라미터의 기울기를 계산할 수 있습니다. l.backward() 명령어를 실행하면, wb에 대한 기울기가 자동으로 계산됩니다.

아래는 l.backward() 실행 시, autograd가 구축한 계산 그래프의 개념을 보여줍니다.

spinner

기울기 계산

역전파를 통해 손실 $L$의 각 파라미터에 대한 기울기를 구하는 과정은 다음과 같습니다.

먼저 $L$을 $w$와 $b$에 대해 편미분합니다:

[ \frac{\partial L}{\partial w} = \frac{2}{N} \sum_{i=1}^{N} (y_i - (w x_i + b)) (-x_i) ]

[ \frac{\partial L}{\partial b} = \frac{2}{N} \sum_{i=1}^{N} (y_i - (w x_i + b)) (-1) ]

계산 그래프에서 각 연산의 노드는 역전파 시, 상류에서 내려온 기울기를 곱하여 전달하게 됩니다. 이 기울기 전달 과정이 PyTorch의 autograd 기능을 통해 자동으로 수행되므로, 사용자는 수식의 복잡성을 신경 쓰지 않아도 됩니다.

기울기 추적과 텐서의 requires_grad 속성

위 예제에서 wbrequires_grad=True로 설정되었습니다. 이는 PyTorch에게 이 변수들이 학습 중에 기울기를 추적해야 한다고 알리는 역할을 합니다. 만약 requires_grad=False로 설정하면, 역전파 시 해당 변수의 기울기가 계산되지 않습니다.

다음은 예제의 텐서 초기화 부분에서 requires_grad의 사용 예입니다:

이제, 기울기 추적을 위해 어떤 방식으로 작동하는지 알아보겠습니다. 예를 들어, 다음과 같이 $w$에 대한 함수 $y = w^2 + 3w + 2$가 있다고 가정합시다:

[ y = w^2 + 3w + 2 ]

여기서 $w=1.0$일 때 $y$의 기울기를 계산해보겠습니다.

수학적 설명

위의 예에서 기울기를 수학적으로 계산해 보면:

[ \frac{\partial y}{\partial w} = 2w + 3 ]

따라서, $w=1.0$일 때:

[ \frac{\partial y}{\partial w} = 2(1.0) + 3 = 5.0 ]

위의 코드와 일치하는 결과를 얻을 수 있습니다. PyTorch의 autograd는 연산을 추적하여 그래프를 구성하고, 이 그래프를 역전파 시 탐색하여 자동으로 기울기를 계산합니다.

기울기 추적 멈추기: torch.no_grad()

때로는 기울기 추적이 필요하지 않을 때가 있습니다. 예를 들어, 학습이 완료된 후에 모델을 평가할 때, 파라미터를 변경하지 않기 때문에 기울기를 계산할 필요가 없습니다. 이때는 torch.no_grad() 블록을 사용하여 불필요한 메모리 사용과 계산을 방지할 수 있습니다:

이 블록 안에서는 wb의 기울기가 추적되지 않으며, 이를 통해 모델 평가 시 성능을 최적화할 수 있습니다.

retain_graph 옵션

autograd를 통해 역전파를 수행하면 기본적으로 그래프는 삭제됩니다. 동일한 그래프를 여러 번 사용하여 역전파를 실행하고 싶다면, retain_graph=True 옵션을 설정해야 합니다. 다음은 그 사용 예입니다:

이 옵션을 사용하는 상황은 드물지만, 복잡한 그래프에서 여러 번의 역전파를 해야 하는 경우에 유용합니다.

다중 입력과 다중 출력에서의 기울기 계산

autograd는 다중 입력과 다중 출력에 대해서도 유연하게 동작합니다. 예를 들어, 입력 벡터 $\mathbf{x} \in \mathbb{R}^n$와 출력 스칼라 $y \in \mathbb{R}$의 경우, $y$를 각 입력 요소 $x_i$에 대해 미분하면 다음과 같은 벡터 기울기를 얻게 됩니다:

[ \mathbf{g} = \nabla_{\mathbf{x}} y = \left[ \frac{\partial y}{\partial x_1}, \frac{\partial y}{\partial x_2}, \ldots, \frac{\partial y}{\partial x_n} \right] ]

이는 벡터 $\mathbf{x}$가 주어졌을 때 autograd가 자동으로 $\mathbf{g}$를 계산할 수 있음을 의미합니다.

또한, 다중 출력 $\mathbf{y} \in \mathbb{R}^m$일 경우, $\mathbf{y}$와 $\mathbf{x}$ 사이의 야코비안(Jacobian) 행렬 $\mathbf{J}$를 생성할 수 있으며, 이는 다음과 같이 정의됩니다:

[ \mathbf{J} = \frac{\partial \mathbf{y}}{\partial \mathbf{x}} = \begin{bmatrix} \frac{\partial y_1}{\partial x_1} & \frac{\partial y_1}{\partial x_2} & \cdots & \frac{\partial y_1}{\partial x_n} \ \frac{\partial y_2}{\partial x_1} & \frac{\partial y_2}{\partial x_2} & \cdots & \frac{\partial y_2}{\partial x_n} \ \vdots & \vdots & \ddots & \vdots \ \frac{\partial y_m}{\partial x_1} & \frac{\partial y_m}{\partial x_2} & \cdots & \frac{\partial y_m}{\partial x_n} \end{bmatrix} ]

PyTorch의 autograd는 이와 같은 복잡한 구조도 자동으로 처리할 수 있습니다.

Last updated