역전파 (Backpropagation)¶
개요¶
역전파(Backpropagation)는 신경망의 가중치를 학습하기 위한 핵심 알고리즘이다. 손실 함수의 기울기(gradient)를 출력층에서 입력층 방향으로 효율적으로 계산하며, 이를 통해 각 파라미터가 손실에 얼마나 기여하는지 파악한다. 역전파는 미적분의 연쇄 법칙(chain rule)에 기반하며, 현대 딥러닝 프레임워크의 자동 미분(automatic differentiation) 시스템의 근간이다.
핵심 개념¶
1. 연쇄 법칙 (Chain Rule)¶
역전파의 수학적 기반이다.
단변수: $\(\frac{dz}{dx} = \frac{dz}{dy} \cdot \frac{dy}{dx}\)$
다변수: $\(\frac{\partial L}{\partial w} = \sum_{i} \frac{\partial L}{\partial z_i} \cdot \frac{\partial z_i}{\partial w}\)$
직관: 각 연산의 "로컬 기울기(local gradient)"를 체인처럼 연결하여 전체 기울기를 구한다.
예제: \(f(x) = (2x + 3)^2\)에서 \(\frac{df}{dx}\)를 구하자.
- \(u = 2x + 3\), \(f = u^2\)
- \(\frac{df}{du} = 2u\), \(\frac{du}{dx} = 2\)
- \(\frac{df}{dx} = \frac{df}{du} \cdot \frac{du}{dx} = 2u \cdot 2 = 4(2x + 3)\)
2. 계산 그래프 (Computational Graph)¶
수학적 연산을 방향 비순환 그래프(DAG)로 표현한 것이다.
- 노드: 연산 (덧셈, 곱셈, 활성화 함수 등)
- 엣지: 데이터 흐름 (텐서)
graph LR
x((x)) --> mul1[×]
w((w)) --> mul1
mul1 --> add[+]
b((b)) --> add
add --> sigma["σ(·)"]
sigma --> L["Loss"]
style L fill:#f96,stroke:#333 Forward mode vs Reverse mode differentiation: - Forward mode: 입력 수만큼 패스 필요 - Reverse mode (역전파): 출력 수만큼 패스 필요
신경망의 손실은 스칼라이므로, reverse mode에서는 1회 패스로 모든 파라미터에 대한 기울기를 계산할 수 있다. 이것이 역전파가 신경망에 효율적인 이유이다.
3. 역전파 알고리즘 단계별 과정¶
Step 1: Forward pass — 모든 중간 활성화 값 저장
Step 2: 출력층에서 손실의 기울기 계산
Step 3: 역방향으로 각 층의 기울기를 chain rule로 전파
Step 4: 파라미터 기울기 계산 및 업데이트
graph LR
subgraph "Forward Pass →"
A[입력 x] --> B["z⁽¹⁾ = Wx+b"]
B --> C["a⁽¹⁾ = σ(z⁽¹⁾)"]
C --> D["z⁽²⁾ = Wa⁽¹⁾+b"]
D --> E["ŷ = σ(z⁽²⁾)"]
E --> F[Loss L]
end
subgraph "← Backward Pass"
F --> G["δ⁽²⁾ = ∂L/∂z⁽²⁾"]
G --> H["δ⁽¹⁾ = W^T δ⁽²⁾ ⊙ σ'"]
H --> I["∂L/∂W, ∂L/∂b"]
end 메모리 요구: forward pass에서 저장한 중간 활성화 값이 메모리를 차지한다. 깊은 네트워크에서는 이것이 메모리 병목이 된다.
4. 자동 미분 (Automatic Differentiation)¶
| 방법 | 정확도 | 효율성 | 비고 |
|---|---|---|---|
| 수치 미분 (Numerical) | 근사값 | 느림 (파라미터당 2회 forward) | 디버깅용 |
| 기호 미분 (Symbolic) | 정확 | 수식 폭발 (expression swell) | 수학 소프트웨어 |
| 자동 미분 (Automatic) | 정확 | 효율적 | 딥러닝 프레임워크 |
구현 방식: - Define-and-run (정적 그래프): TensorFlow 1.x — 그래프를 먼저 정의하고 나중에 실행 - Define-by-run (동적 그래프): PyTorch, TF2 Eager — 실행하면서 그래프를 구성
PyTorch autograd 예시:
x = torch.tensor(2.0, requires_grad=True)
y = x ** 2 + 3 * x
y.backward()
print(x.grad) # 2*2 + 3 = 7.0
Gradient accumulation: GPU 메모리가 부족할 때, 큰 배치를 작은 미니배치로 나누어 기울기를 누적한 후 한 번에 업데이트한다.
실용 팁: 추론(inference) 시
torch.no_grad()또는@torch.inference_mode()를 사용하여 불필요한 기울기 계산과 메모리 사용을 방지하라.
5. 최적화 알고리즘 (Optimizers)¶
역전파로 계산한 기울기를 사용하여 파라미터를 업데이트하는 다양한 전략이 있다.
SGD (Stochastic Gradient Descent)¶
SGD + Momentum¶
골짜기(ravine) 형태의 손실 표면에서 진동을 감소시킨다.
Adam (Adaptive Moment Estimation)¶
가장 널리 사용되는 최적화 알고리즘. Momentum과 RMSProp을 결합했다.
AdamW¶
Weight decay를 L2 regularization과 분리한다 (decoupled weight decay). Adam에서 weight decay가 적응적 학습률과 상호작용하는 문제를 해결한다.
Optimizer 비교:
| Optimizer | 적응적 학습률 | Momentum | 주요 특징 |
|---|---|---|---|
| SGD | 없음 | 없음 | 단순, 일반화 우수 |
| SGD+Momentum | 없음 | 있음 | 수렴 안정화 |
| AdaGrad | 있음 | 없음 | 희소 데이터에 유리, 학습률 단조 감소 |
| RMSProp | 있음 | 없음 | AdaGrad 개선 |
| Adam | 있음 | 있음 | 범용적, 빠른 수렴 |
| AdamW | 있음 | 있음 | Adam + 올바른 weight decay |
Learning Rate Schedulers¶
| 스케줄러 | 설명 | 사용 시나리오 |
|---|---|---|
| Step Decay | 일정 에폭마다 학습률 감소 | 전통적 방법 |
| Cosine Annealing | 코사인 함수로 학습률 감소 | 일반적으로 우수 |
| Warmup | 초반에 학습률을 0에서 점진적 증가 | Transformer 학습 |
| One-Cycle | 학습률을 올렸다가 내림 | 빠른 수렴 |
| Cyclical LR | 학습률을 주기적으로 변화 | 지역 최솟값 탈출 |
상세 내용¶
기울기 체크 (Gradient Checking)¶
구현의 정확성을 확인하기 위한 디버깅 도구이다. 자동 미분의 결과를 수치 미분과 비교한다.
두 값의 상대 오차가 \(10^{-7}\) 이하면 구현이 올바르다고 판단할 수 있다.
Gradient Clipping¶
기울기 폭발을 방지하기 위한 기법이다.
- 값 클리핑 (Value Clipping): 각 기울기 요소를 \([-c, c]\) 범위로 제한
- 노름 클리핑 (Norm Clipping): 기울기 벡터의 노름이 임계값을 초과하면 스케일링
특히 RNN 학습에서 필수적이다.
Checkpoint Gradient (Gradient Checkpointing)¶
메모리 절약 기법으로, 모든 중간 활성화를 저장하는 대신 일부만 저장하고, 역전파 시 필요한 값을 다시 계산한다. 메모리 사용량을 \(O(\sqrt{n})\)으로 줄일 수 있지만, 계산 시간이 증가한다.
언제 사용하는가¶
역전파는 모든 신경망 학습에서 사용된다. 실무적 선택은 주로 최적화 알고리즘에 집중된다:
- 기본값: AdamW (대부분의 상황에서 좋은 출발점)
- 컴퓨터 비전 (CNN): SGD + Momentum + Cosine Annealing이 종종 최고 성능
- Transformer / LLM: AdamW + Warmup + Cosine Decay
- 정밀 튜닝이 필요한 경우: SGD가 일반화 성능에서 Adam보다 우수할 수 있음
흔한 오해와 함정¶
-
"Adam의 기본 하이퍼파라미터가 항상 최적": \(\beta_1=0.9\), \(\beta_2=0.999\), \(\epsilon=10^{-8}\)이 기본이지만, 특히 \(\epsilon\) 값이 학습 안정성에 큰 영향을 줄 수 있다. Transformer에서는 \(\beta_2=0.98\)이 자주 사용된다.
-
역전파를 수동으로 구현해야 한다: 현대 프레임워크(PyTorch, TensorFlow)가 자동 미분을 제공하므로, 수동 구현은 교육 목적을 제외하면 불필요하다. 그러나 원리를 이해하는 것은 디버깅에 필수적이다.
-
학습률을 고정: 학습률 스케줄러를 사용하지 않으면 최적 성능에 도달하기 어렵다. 특히 Transformer에서 warmup은 학습 안정성을 위해 필수적이다.
-
기울기 체크 무시: 커스텀 레이어나 손실 함수를 구현할 때 기울기 체크를 하지 않으면 미묘한 버그가 성능 저하로 이어질 수 있다.
-
추론 시 기울기 모드 유지:
torch.no_grad()를 사용하지 않으면 불필요한 메모리 사용과 느린 추론 속도가 발생한다.
다른 주제와의 연결¶
- 신경망 기초: 순전파와 손실 함수
- 활성화 함수: 활성화 함수의 도함수와 기울기 소실/폭발
- 가중치 초기화: 학습 시작점이 기울기 흐름에 미치는 영향
- 정규화: BatchNorm의 학습/추론 모드와 기울기 안정화
- RNN/LSTM/GRU: BPTT와 기울기 클리핑
- Transformer: AdamW + Warmup 스케줄링
- 전이 학습: 층별 학습률 전략