# 자동 미분 뒤의 계산: 카르파티가 역전파를 손으로 구현한 이유

> 2022-10-11 · Andrej Karpathy · 큐레이션 김태우
> https://challengekim.com/insights/자동-미분-뒤의-계산-카르파티가-역전파를-손으로-구현한-이유
> 원문: https://www.youtube.com/watch?v=q8SA3rM6ckI

## 핵심 요약

- 안드레이 카르파티는 PyTorch의 자동 미분 호출을 걷어내고, 기존 문자 예측 신경망의 역전파를 텐서 단위에서 직접 구현했다.
- 역전파를 이해하지 못하면 손실값을 제한하려다 일부 사례의 기울기를 0으로 만드는 것처럼, 코드가 실행돼도 학습을 잘못 이끌 수 있다고 설명했다.
- 텐서의 합산과 브로드캐스팅은 역방향에서 서로 반대의 형태로 나타난다. 한 값이 여러 곳에 쓰였다면 그곳에서 돌아온 기울기를 더해야 한다.
- 교차 엔트로피와 배치 정규화는 작은 연산마다 역전파하는 대신 수식을 정리해 더 짧은 역방향 계산으로 바꿀 수 있다.

## 자동 미분을 이해해야 하는 이유

카르파티의 출발점은 앞선 강의에서 학습한 다층 퍼셉트론이다. 문자 임베딩, 두 개의 선형 계층, 그 사이의 배치 정규화 계층으로 구성된 모델에서 순전파는 유지하고, 손실에 대한 PyTorch의 `backward` 호출만 직접 작성한 계산으로 대체한다. 역전파는 손실을 줄이기 위해 각 중간값과 매개변수를 어느 방향으로 얼마나 바꿔야 하는지 계산하는 과정이다.

그는 자동 미분이 신경망을 저절로 올바르게 학습시키지는 않는다고 강조한다. 예로 든 한 코드에서는 큰 기울기를 제한하려는 의도와 달리 손실값 자체에 상한을 걸었다. 손실이 그 상한을 넘는 사례에서는 기울기가 0이 돼 해당 사례가 학습에서 사실상 무시된다. 활성화 함수의 평평한 구간에서 기울기가 약해지거나 뉴런이 작동하지 않는 문제도 내부 계산을 알아야 살필 수 있다는 설명이다.

카르파티는 과거 자신의 코드에서도 역방향 계산을 직접 작성했다고 회고한다. 2010년 무렵 제한 볼츠만 머신 관련 코드는 MATLAB로 작성했고, 2014년 이미지와 문장의 일부를 대응시키는 작업에서는 손실과 역방향 계산을 NumPy 코드로 구현했다. 당시에는 수치적으로 추정한 기울기와 직접 계산한 기울기를 비교해 확인하는 방식이 쓰였다. 다만 그는 오늘날 실무에서 역전파 전체를 손으로 작성하는 방식을 권하지 않으며, 이번 구현을 이해를 위한 연습으로 제시한다.

## 작은 연산부터 거꾸로 따라가기

첫 번째 연습은 손실을 여러 중간 텐서로 나눈 뒤 끝에서부터 기울기를 구하는 것이다. 이 모델의 한 배치는 32개 사례이며, 각 사례는 다음 문자 27개에 대한 값을 갖는다. 정답 문자의 로그 확률을 골라 평균한 뒤 부호를 바꿔 손실을 만들므로, 선택된 위치의 기울기는 각각 배치 크기의 역수에 음수를 붙인 값이다. 선택되지 않은 로그 확률 위치의 기울기는 0이다.

이후 로그, 지수, 합산, 나눗셈에 해당하는 연산을 거슬러 올라간다. 핵심은 **값의 모양과 재사용 경로**다. 순전파에서 한 값을 여러 열로 복제해 계산했다면, 역전파에서는 그 열들에서 돌아온 기울기를 합친다. 반대로 순전파에서 여러 값을 합쳤다면, 역전파에서는 합계의 기울기가 각 입력으로 전달된다. 하나의 텐서가 두 경로에 쓰였을 때도 양쪽의 기여를 더해야 최종 기울기가 된다.

선형 계층의 행렬곱 역시 작은 행렬의 각 원소가 어떤 곱과 합으로 만들어졌는지 풀어 쓰면 역방향 계산을 도출할 수 있다. 카르파티는 입력과 가중치의 기울기가 다시 행렬곱으로 표현되고, 편향의 기울기는 배치 방향으로 더한 값이 된다고 설명한다. 마지막 임베딩 조회 단계에서는 같은 문자가 배치에 여러 번 등장할 수 있으므로, 각 사용 지점의 기울기를 해당 임베딩 행에 누적한다. 그는 단계마다 직접 구한 값과 PyTorch 자동 미분 결과를 비교한다.

## 교차 엔트로피의 짧은 역방향 계산

작은 연산을 모두 통과하는 방식은 원리를 드러내지만 계산이 길다. 두 번째 연습에서는 교차 엔트로피 손실을 하나의 수식으로 보고, 문자별 원점수인 로짓에 대한 기울기를 직접 유도한다. 각 사례에서 로짓을 확률로 바꾼 값에 정답 위치만 1을 빼고, 배치 평균에 맞춰 배치 크기로 나누면 된다. 직접 계산한 기울기는 PyTorch 결과와 완전히 같은 비트값은 아니었지만, 최대 차이가 약 5×10⁻⁹ 수준이었다고 카르파티는 보고했다.

이 식은 학습 신호의 방향도 보여준다. 정답이 아닌 문자에 부여한 확률은 낮추고 정답 문자의 값은 높이는 방향으로 작용한다. 한 사례에서 각 위치의 기울기를 더하면 0이 된다. 모델이 틀린 문자에 높은 확률을 줬다면 그 위치를 낮추는 신호가 커지고, 정답 위치를 높이는 신호도 그만큼 커진다는 설명이다.

## 배치 정규화에서 주의한 조건

세 번째 연습은 배치 정규화다. 배치의 평균과 분산으로 중간값을 정규화한 뒤 학습 가능한 배율과 편향을 적용하는 연산을, 작은 단계로 나눈 계산에서 하나의 역방향 식으로 정리한다. 이때 평균과 분산은 여러 사례가 공유하는 값이므로, 각 사례에서 돌아오는 기울기의 모든 경로를 고려해야 한다. 카르파티는 종이에 유도한 식을 64개 뉴런에 병렬로 적용하고, 구현 결과를 자동 미분과 비교했다.

분산 계산에는 별도 선택이 있다. 카르파티의 예제는 배치 크기 `n` 대신 `n-1`로 나누는 베셀 보정을 사용한다. 그는 배치 정규화 논문과 PyTorch의 동작에서 학습 시 분산 추정과 추론에 쓰는 분산 추정 방식이 달라지는 점을 혼란스럽게 본다고 밝혔다. 작은 미니배치가 전체 학습 데이터의 표본이라는 점을 들어, 자신의 구현에서는 보정된 방식을 일관되게 쓰는 편을 택했다. 이는 강의에서 제시한 구현상의 판단이다.

## 직접 만든 기울기로 학습한 결과

마지막 연습에서는 앞서 구한 역방향 계산을 합쳐 모델을 다시 학습한다. 처음에는 PyTorch가 계산한 기울기와 비교했다. 일부 값은 정확히 일치하지 않았지만 차이가 작음을 확인한 뒤 자동 미분을 끄고, 직접 계산한 기울기로 매개변수를 갱신했다. 학습 후 배치 정규화에 필요한 값을 보정해 평가했으며, 카르파티는 이전과 비슷한 손실과 문자 이름 형태의 생성 결과를 얻었다고 설명한다.

이 강의의 결론은 자동 미분을 버리자는 것이 아니다. 손실에서 임베딩까지 기울기가 어떤 경로로 흐르고 어디서 더해지는지 직접 확인하면, 자동 미분을 사용할 때도 학습 문제의 원인을 더 구체적으로 살필 수 있다는 것이다.

---

원문을 바탕으로 AI 가 한국어로 요약·재구성한 글입니다. 인용·수치는 원문 링크에서 확인해 주세요. [원문 링크](https://www.youtube.com/watch?v=q8SA3rM6ckI)
