Skip to main content

역전파 (Backpropagation)

학습 목표

  • 역전파(Backpropagation) 알고리즘의 핵심인 연쇄 법칙(Chain Rule)을 이해한다
  • 계산 그래프(Computational Graph)를 통해 기울기 흐름을 추적할 수 있다
  • PyTorch의 Autograd가 역전파를 자동으로 수행하는 원리를 이해한다
  • 기울기 소실과 폭주 문제를 인식하고 대응 방법을 안다

왜 중요한가

역전파는 신경망의 학습을 가능하게 하는 핵심 알고리즘입니다. 손실 함수의 값을 줄이기 위해 각 가중치가 어느 방향으로, 얼마만큼 변해야 하는지를 계산합니다. 1986년 Rumelhart, Hinton, Williams가 재발견한 이후 모든 딥러닝 학습의 근간이 되었습니다.

연쇄 법칙 (Chain Rule)

합성 함수의 미분은 각 구성 함수의 미분의 곱으로 계산됩니다. Lw=Lyyzzw\frac{\partial L}{\partial w} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial z} \cdot \frac{\partial z}{\partial w} 예를 들어, z=wx+bz = wx + b, y=σ(z)y = \sigma(z), L=(yt)2L = (y - t)^2일 때: Lw=Lyyzzw=2(yt)σ(z)x\frac{\partial L}{\partial w} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial z} \cdot \frac{\partial z}{\partial w} = 2(y-t) \cdot \sigma'(z) \cdot x

계산 그래프

계산 그래프는 수식의 각 연산을 노드로 표현한 방향 그래프입니다. 순전파(Forward Pass)에서는 입력에서 출력 방향으로, 역전파(Backward Pass)에서는 출력에서 입력 방향으로 기울기가 흐릅니다.

구체적 예제

w=2,x=3,b=1w = 2, x = 3, b = 1, 정답 t=0t = 0에서: 순전파:
  1. z=wx+b=2×3+1=7z = wx + b = 2 \times 3 + 1 = 7
  2. y=σ(7)0.999y = \sigma(7) \approx 0.999
  3. L=(yt)2=(0.9990)20.998L = (y - t)^2 = (0.999 - 0)^2 \approx 0.998
역전파:
  1. Ly=2(yt)=2×0.9991.998\frac{\partial L}{\partial y} = 2(y - t) = 2 \times 0.999 \approx 1.998
  2. yz=σ(z)(1σ(z))0.001\frac{\partial y}{\partial z} = \sigma(z)(1 - \sigma(z)) \approx 0.001
  3. zw=x=3\frac{\partial z}{\partial w} = x = 3
  4. Lw=1.998×0.001×30.006\frac{\partial L}{\partial w} = 1.998 \times 0.001 \times 3 \approx 0.006
import torch

# 계산 그래프 구성
w = torch.tensor(2.0, requires_grad=True)
x = torch.tensor(3.0)
b = torch.tensor(1.0, requires_grad=True)
t = torch.tensor(0.0)

# 순전파
z = w * x + b
y = torch.sigmoid(z)
loss = (y - t) ** 2

# 역전파 (PyTorch가 자동 계산)
loss.backward()

print(f"∂L/∂w = {w.grad:.6f}")  # 약 0.006
print(f"∂L/∂b = {b.grad:.6f}")  # 약 0.002

다층 네트워크에서의 역전파

2층 MLP에서의 역전파를 단계별로 추적합니다.
import torch
import torch.nn as nn

# 간단한 2층 MLP
model = nn.Sequential(
    nn.Linear(2, 3),  # Layer 1: 2 → 3
    nn.ReLU(),
    nn.Linear(3, 1),  # Layer 2: 3 → 1
)

x = torch.tensor([[1.0, 2.0]])
target = torch.tensor([[1.0]])

# 순전파
output = model(x)
loss = nn.MSELoss()(output, target)

# 역전파
loss.backward()

# 각 층의 기울기 확인
for name, param in model.named_parameters():
    print(f"{name}: grad shape = {param.grad.shape}")
    print(f"  값: {param.grad}")
기울기는 출력층에서 입력층 방향으로 전파됩니다: LW1=Ly^y^hhz1z1W1\frac{\partial L}{\partial W_1} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial h} \cdot \frac{\partial h}{\partial z_1} \cdot \frac{\partial z_1}{\partial W_1}

기울기 소실과 폭주

기울기 소실 (Gradient Vanishing)

깊은 네트워크에서 기울기가 역전파되면서 점점 작아져 0에 가까워지는 현상입니다. Sigmoid나 Tanh는 최대 기울기가 0.25(Sigmoid) 또는 1(Tanh)이므로, 층이 깊어질수록 기울기가 지수적으로 감소합니다. Lw1=σ(zn)σ(zn1)σ(z1)n번 곱셈Lznx\frac{\partial L}{\partial w_1} = \underbrace{\sigma'(z_n) \cdot \sigma'(z_{n-1}) \cdots \sigma'(z_1)}_{\text{n번 곱셈}} \cdot \frac{\partial L}{\partial z_n} \cdot x Sigmoid의 최대 미분값이 0.25이므로, 10층 네트워크에서는 0.25101060.25^{10} \approx 10^{-6}으로 기울기가 거의 사라집니다.

기울기 폭주 (Gradient Exploding)

반대로 기울기가 지수적으로 커지는 현상입니다. RNN에서 특히 빈번하며, 가중치 행렬의 최대 고유값이 1보다 크면 발생합니다.

해결 방법

문제해결 방법설명
기울기 소실ReLU 계열 활성화 함수양수 영역 기울기 = 1
기울기 소실스킵 연결 (Skip Connection)ResNet의 핵심 아이디어
기울기 소실적절한 가중치 초기화He/Xavier 초기화
기울기 폭주Gradient Clipping기울기 크기 제한
기울기 폭주BatchNorm/LayerNorm활성화 값 정규화
# Gradient Clipping 예시
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

loss.backward()
# 기울기 크기를 최대 1.0으로 제한
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
optimizer.step()

가중치 초기화

적절한 가중치 초기화는 기울기 소실/폭주를 예방하는 첫 번째 방어선입니다.
초기화 방법적합한 활성화 함수분산
Xavier (Glorot)Sigmoid, TanhVar(w)=2nin+nout\text{Var}(w) = \frac{2}{n_{in} + n_{out}}
He (Kaiming)ReLU, Leaky ReLUVar(w)=2nin\text{Var}(w) = \frac{2}{n_{in}}
import torch.nn as nn

# He 초기화 (ReLU 사용 시)
layer = nn.Linear(256, 128)
nn.init.kaiming_normal_(layer.weight, mode='fan_in', nonlinearity='relu')

# Xavier 초기화 (Tanh 사용 시)
layer2 = nn.Linear(256, 128)
nn.init.xavier_normal_(layer2.weight)
PyTorch의 nn.Linear는 기본적으로 Kaiming Uniform 초기화를 사용합니다.
PyTorch의 Autograd 엔진은 텐서 연산을 수행할 때마다 동적으로 계산 그래프를 구성합니다. requires_grad=True인 텐서에 대한 모든 연산이 기록되며, .backward() 호출 시 이 그래프를 역순으로 순회하며 연쇄 법칙을 적용합니다. 자세한 내용은 Autograd 문서에서 다룹니다.
수치 미분(Numerical Differentiation)은 f(x+h)f(xh)2h\frac{f(x+h) - f(x-h)}{2h}로 근사하는 방법입니다. 정확하지만 파라미터마다 별도 계산이 필요해 매우 느립니다. 역전파는 한 번의 역방향 패스로 모든 파라미터의 기울기를 동시에 계산하므로 효율적입니다. 수치 미분은 역전파 구현의 정확성을 검증하는 용도(gradient checking)로 사용됩니다.

체크리스트

  • 연쇄 법칙이 역전파에서 어떻게 적용되는지 설명할 수 있다
  • 계산 그래프에서 순전파와 역전파 방향을 구분할 수 있다
  • 기울기 소실과 폭주의 원인과 해결책을 설명할 수 있다
  • He 초기화와 Xavier 초기화의 차이를 안다

다음 문서