딥러닝 기초 (4) - 역전파: 연쇄법칙과 계산 그래프
수많은 가중치의 기울기를 어떻게 한꺼번에 구하는가 — 연쇄법칙과 계산 그래프로 출력에서 입력으로 거슬러 계산하는 역전파의 원리를 정리하고, NumPy만으로 신경망을 만들어 XOR을 실제로 학습시켜 본 딥러닝 기초 (4)편입니다.
딥러닝 기초 시리즈의 4편입니다. 전체 목차는 0편에 있습니다. 순전파(1편)·손실(3편)까지 왔으니, 이 편은 그 손실을 줄일 방향을 구하는 역전파를 다루고, NumPy만으로 XOR을 학습시킵니다.
방향을 구하는 법: 경사하강과 기울기
손실을 줄이려면 가중치를 어느 쪽으로 옮길지 알아야 합니다. 답은 미분에 있습니다. 손실을 어떤 가중치로 미분한 값, 곧 기울기(gradient)는 그 가중치를 키울 때 손실이 가장 가파르게 커지는 방향을 가리킵니다. 그러니 손실을 줄이려면 그 반대 방향으로 조금 옮기면 됩니다. 이 갱신을 반복하는 것이 경사하강법입니다(자세한 최적화는 5편).
1
w ← w − η · (∂L/∂w)
문제는 신경망에 가중치가 수천에서 수백만 개라는 것입니다. 이 많은 ∂L/∂w를 어떻게 다 구할까요.
연쇄법칙과 계산 그래프
손실은 여러 층의 연산이 합성된 함수입니다. 미적분의 연쇄법칙(chain rule)을 쓰면, 은닉층 가중치 W1에 대한 기울기를 국소적인 조각들의 곱으로 쪼갤 수 있습니다.
1
∂L/∂W1 = (∂L/∂a2) · (∂a2/∂z2) · (∂z2/∂a1) · (∂a1/∂z1) · (∂z1/∂W1)
각 조각은 한 층 안에서 계산할 수 있는 값입니다. 이 곱을 출력 쪽에서 입력 쪽으로 거꾸로 계산해 나가는 것이 역전파(backpropagation)입니다. 순전파 때 계산해둔 중간값(z1, a1 등)을 재사용하기 때문에, 가중치가 아무리 많아도 순전파 한 번과 비슷한 비용으로 모든 기울기를 한꺼번에 구합니다.
정리하면 한 번의 학습 스텝은 세 박자입니다.
- 순전파 — 입력을 밀어 예측과 손실을 구한다.
- 역전파 — 손실을 거꾸로 전파해 모든 기울기를 구한다.
- 갱신 — 경사하강으로 가중치를 기울기 반대로 옮긴다.
밑바닥부터: NumPy로 XOR 학습
이제 1편에서 선형 모델이 못 풀던 XOR을 직접 풀어봅니다. 입력 2 → 은닉 4 → 출력 1짜리 신경망을, 라이브러리 없이 NumPy만으로 만들고 역전파를 손으로 구현합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import numpy as np
np.random.seed(0)
X = np.array([[0,0],[0,1],[1,0],[1,1]], dtype=float)
y = np.array([[0], [1], [1], [0]], dtype=float) # XOR
def sigmoid(z): return 1 / (1 + np.exp(-z))
W1 = np.random.randn(2, 4); b1 = np.zeros(4)
W2 = np.random.randn(4, 1); b2 = np.zeros(1)
lr, N = 0.5, len(X)
for epoch in range(10001):
# --- 순전파 ---
z1 = X @ W1 + b1; a1 = sigmoid(z1)
z2 = a1 @ W2 + b2; a2 = sigmoid(z2)
loss = np.mean((a2 - y) ** 2)
# --- 역전파 (연쇄법칙을 뒤에서 앞으로) ---
d2 = (2 * (a2 - y) / N) * a2 * (1 - a2) # 출력층 오차
dW2 = a1.T @ d2; db2 = d2.sum(axis=0)
d1 = (d2 @ W2.T) * a1 * (1 - a1) # 은닉층으로 전파
dW1 = X.T @ d1; db1 = d1.sum(axis=0)
# --- 갱신 ---
W2 -= lr * dW2; b2 -= lr * db2
W1 -= lr * dW1; b1 -= lr * db1
if epoch in (0, 1000, 5000, 10000):
print(f"epoch {epoch:5d} loss {loss:.4f}")
print("최종 예측:", np.round(a2.ravel(), 3))
a2 * (1 - a2)는 시그모이드의 미분값입니다. 역전파 세 줄이 앞의 연쇄법칙을 그대로 옮긴 것이고, 출력층 오차 d2에서 시작해 W2를 타고 은닉층 d1으로 거슬러 오르는 흐름이 보입니다. 실행하면 손실이 꾸준히 줄어듭니다.
1
2
3
4
5
epoch 0 loss 0.3267
epoch 1000 loss 0.0902
epoch 5000 loss 0.0014
epoch 10000 loss 0.0006
최종 예측: [0.024 0.977 0.979 0.026]
최종 예측 [0.024, 0.977, 0.979, 0.026]은 반올림하면 정확히 [0, 1, 1, 0], 곧 XOR의 정답입니다. 직선 하나로는 가를 수 없던 네 점을 은닉층이 비선형 경계로 갈라낸 것입니다.
이 30줄이 딥러닝의 밑바닥입니다. PyTorch가 해주는 일도 원리는 똑같고, 다만 우리가 손으로 짠 역전파를 자동 미분(autograd)으로 대신 계산하고 GPU로 병렬화할 뿐입니다. 그 도구는 PyTorch 기초에서 다룹니다.
정리
| 개념 | 한 줄 요약 |
|---|---|
| 기울기 | 손실이 커지는 방향. 반대로 가면 손실이 준다 |
| 연쇄법칙 | 합성함수의 미분을 국소 조각의 곱으로 |
| 역전파 | 그 곱을 출력→입력으로 거꾸로. 중간값 재사용 |
| 학습 한 스텝 | 순전파 → 역전파 → 갱신의 반복 |
여기까지가 신경망의 토대입니다. 다음 편부터는 이 학습을 더 잘, 더 깊은 망에서도 되게 만드는 장치들 — 먼저 최적화 — 로 넘어갑니다.