신경망이 학습을 멈출 때: 기울기 소실 이해
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.0Observation
- Sigmoid 그래디언트는 빠르게 사라집니다.
- 입력이 양수인 한 ReLU 그래디언트는 1을 유지하므로, 더 빠르고 안정적인 학습이 가능합니다.
마무리
이제 소실되는 그래디언트 문제에 대해 명확히 이해하셨길 바랍니다. 활성화 함수와 그래디언트와 함께, 이 개념은 신경망을 이해하기 위한 핵심 구성 요소 중 하나입니다. 앞으로의 기사에서는 이러한 기초를 바탕으로 다음에 무엇이 오는지 탐구할 것입니다.
예제는 Colab notebook에서 직접 실행해 볼 수 있습니다.