Automatic Differentiation with torch.autograd

안소희·2024년 10월 11일

PyTorch

목록 보기
6/8

PyTorch의 torch.autograd는 신경망 학습 시 가장 많이 사용되는 역전파 알고리즘을 통해 매개변수(가중치)의 변화도(gradient)를 자동으로 계산하는 엔진이다.

이를 통해 매개변수의 최적화를 돕는다. 자동 미분은 연산 그래프(Computational graph)를 생성하여 매개변수에 대한 변화도를 계산하는데, 이는 손실 함수와 매개변수 간의 미분 값을 자동으로 구해주는 방식이다.

image.png

1. 연산 그래프와 텐서

  • 입력 텐서 x, w, b와 같은 매개변수는 신경망에서 학습해야 하는 변수이다. 이때, 변화도를 계산하고 싶다면 텐서를 정의할 때 requires_grad=True 옵션을 설정해야한다
  • 연산 그래프는 텐서에 적용되는 연산을 Function 클래스 객체로 표현한다. 각 연산은 그래프에서 노드로 연결되고, 순전파(forward pass)와 역전파(backward pass)를 계산한다. 예를 들어, z = torch.matmul(x, w) + b와 같은 연산에서, z.grad_fn에는 그 연산의 역전파 함수가 저장된다.
print(f"Gradient function for z = {z.grad_fn}")
print(f"Gradient function for loss = {loss.grad_fn}")

2. 변화도 계산하기

  • 신경망 학습의 핵심은 손실 함수의 변화도를 계산하여 매개변수를 업데이트하는 것이다. loss.backward()를 호출하면 손실 함수에 대한 매개변수의 변화도(즉, ∂loss/∂w, ∂loss/∂b)가 계산된. 이후, w.grad, b.grad에서 계산된 변화도를 확인할 수 있다.
loss.backward()
print(w.grad)
print(b.grad)

변화도는 기본적으로 누적(accumulate)되므로, 여러 번의 backward 호출 전에 변화도를 초기화해야 한다. 그래디언트를 초기화하지 않으면 이전 변화도 값이 계속 누적되어 잘못된 결과를 얻을 수 있다.

3. 변화도 추적 멈추기

학습을 완료한 후에는 연산 추적이 필요 없을 수 있다. 특히 순전파 연산만 필요할 때 성능 향상을 위해 변화도 추적을 중단할 수 있다. 이를 위해서는 torch.no_grad()나 텐서의 detach() 메서드를 사용하여 변화도 계산을 멈출 수 있다.

with torch.no_grad():
    z = torch.matmul(x, w) + b

이 방법은 주로 모델 추론 단계에서 사용되며, 불필요한 메모리 사용을 줄이고 연산 성능을 높여준다.

4. 연산 그래프 동작

PyTorch의 연산 그래프는 동적(Dynamic으로 구성된다. 이는 매번 순전파 단계가 실행될 때마다 새로운 그래프가 생성된다는 것을 의미한다. 덕분에, 조건문이나 반복문과 같은 흐름 제어(control flow) 구조에서도 자유롭게 사용할 수 있다.

5. 야코비안 곱 (Jacobian Product)

대부분의 경우 손실 함수는 스칼라 값이지만, 출력이 다차원 텐서일 때는 야코비안 행렬을 이용한 계산이 필요하다. PyTorch는 이때 야코비안 곱(Jacobian Product)을 계산하는데, 이는 출력 텐서의 변화도를 효율적으로 구하기 위함이다.

out.backward(torch.ones_like(out), retain_graph=True)

여러 번 backward를 호출할 때는 retain_graph=True 옵션을 통해 그래프를 유지하고, 필요에 따라 그래디언트를 수동으로 초기화할 수 있다.

inp.grad.zero_()
profile
인공지능.관심 있습니다.

0개의 댓글