신경망이 학습을 멈출 때: 기울기 소실 이해
Source: Dev.to
소실되는 그래디언트 문제란?
신경망에서 그래디언트는 오류를 줄이기 위해 각 가중치를 얼마나 변경해야 하는지를 네트워크에 알려줍니다.
그래디언트가 너무 작으면, 네트워크는 극도로 느리게 학습하거나 때로는 완전히 학습을 멈추게 됩니다. 이것이 소실되는 그래디언트 문제입니다.
왜 이런 현상이 발생할까요?
Vanishing gradients usually happen in deep networks, especially with activation functions like sigmoid.
Sigmoid는 입력을 작은 범위인 0~1로 압축합니다. 여러 층을 거쳐 gradient를 계산하면 초기 층의 gradient는 다음과 같이 계산됩니다:
Gradient of layer 1 = Gradient at output × product of gradients of all subsequent layers
각 gradient가 1보다 작기 때문에, 많은 작은 수를 곱하면 매우 작은 gradient가 되어 초기 층에서는 거의 0에 가깝게 됩니다.
Vanishing Gradients 시각화
import numpy as np
import matplotlib.pyplot as plt
# Sigmoid activation
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# Sigmoid gradient
def sigmoid_grad(x):
s = sigmoid(x)
return s * (1 - s)
x = np.linspace(-10, 10, 1000)
grad = sigmoid_grad(x)
plt.figure(figsize=(8, 4))
plt.plot(x, grad, label="Sigmoid Gradient")
plt.title("Sigmoid Gradient (Vanishing at Extremes)")
plt.xlabel("Input")
plt.ylabel("Gradient")
plt.grid(True)
plt.legend()
plt.show()

관찰: 큰 양수 또는 음수 입력에 대해 기울기가 매우 작습니다. 이것이 깊은 신경망에서 vanishing gradient 현상을 일으키는 원인입니다.
간단한 딥 네트워크 시뮬레이션
# Simulate deep network gradient
layers = 10
x = 5 # extreme input
grad = 1.0
for i in range(layers):
grad *= sigmoid_grad(x) # multiply by each layer's gradient
print(f"Layer {i+1}, Gradient: {grad:.8f}")
출력
Layer 1, Gradient: 0.00665
Layer 2, Gradient: 0.00004
Layer 3, Gradient: 0.00000
Layer 4, Gradient: 0.00000
Layer 5, Gradient: 0.00000
Layer 6, Gradient: 0.00000
Layer 7, Gradient: 0.00000
Layer 8, Gradient: 0.00000
Layer 9, Gradient: 0.00000
Layer 10, Gradient: 0.00000
관찰: 그래디언트가 빠르게 매우 작아집니다. 초기 레이어는 효과적으로 학습할 수 없습니다.
Mitigation with ReLU
ReLU는 양의 값을 압축하지 않기 때문에, 그래디언트가 쉽게 사라지지 않습니다.
비슷한 깊은 네트워크에서 sigmoid와 ReLU를 비교해 봅시다:
# ReLU activation and gradient
def relu(x):
return np.maximum(0, x)
def relu_grad(x):
return np.where(x > 0, 1, 0)
layers = 10
x = 5 # extreme input
# Sigmoid deep gradient
grad_sigmoid = 1.0
grad_relu = 1.0
for i in range(layers):
grad_sigmoid *= sigmoid_grad(x)
grad_relu *= relu_grad(x)
print(f"Layer {i+1}, Sigmoid Grad: {grad_sigmoid:.8f}, ReLU Grad: {grad_relu}")
Output
Layer 1, Sigmoid Grad: 0.00664806, ReLU Grad: 1.0
Layer 2, Sigmoid Grad: 0.00004420, ReLU Grad: 1.0
Layer 3, Sigmoid Grad: 0.00000029, ReLU Grad: 1.0
Layer 4, Sigmoid Grad: 0.00000000, ReLU Grad: 1.0
Layer 5, Sigmoid Grad: 0.00000000, ReLU Grad: 1.0
Layer 6, Sigmoid Grad: 0.00000000, ReLU Grad: 1.0
Layer 7, Sigmoid Grad: 0.00000000, ReLU Grad: 1.0
Layer 8, Sigmoid Grad: 0.00000000, ReLU Grad: 1.0
Layer 9, Sigmoid Grad: 0.00000000, ReLU Grad: 1.0
Layer 10, Sigmoid Grad: 0.00000000, ReLU Grad: 1.0
Observation
- Sigmoid 그래디언트는 빠르게 사라집니다.
- 입력이 양수인 한 ReLU 그래디언트는 1을 유지하므로, 더 빠르고 안정적인 학습이 가능합니다.
마무리
이제 소실되는 그래디언트 문제에 대해 명확히 이해하셨길 바랍니다. 활성화 함수와 그래디언트와 함께, 이 개념은 신경망을 이해하기 위한 핵심 구성 요소 중 하나입니다. 앞으로의 기사에서는 이러한 기초를 바탕으로 다음에 무엇이 오는지 탐구할 것입니다.
예제는 Colab notebook에서 직접 실행해 볼 수 있습니다.