- 강의 주제: 손실 함수(Loss Function)의 정규화 기법과 신경망 학습을 위한 다양한 최적화 알고리즘(Optimization Algorithms) 심층 분석
- 목표: 미분(Derivative), 기울기(Gradient), 행렬 연산에 대한 이해가 필요하며, SGD부터 Adam까지의 알고리즘 발전 과정을 논리적으로 파악해야 함
- 핵심 키워드: #Regularization #L2_Ridge #Optimizatiion # SGD #Momentum #RMSProp #Adam #LearningRageSchedule
- 수학적 표기법(Notation) 정리:
- $W$: 가중치 행렬(Weights), $W\in \mathbb{R} ^{C\times D}$ ($C$: 클래스 수, $D$: 차원)
- $L$: 총 손실(Total Loss), $L=\text{Data loss} +\lambda \cdot \text{Regularization Loss}$
- $\lambda$ (Lambda): 정규화 강도 (Regularization strength)
- $\nabla _W L$: 가중치 $W$에 대한 손실 함수의 기울기 (Gradient)
- $\mu $: 학습률 (Learning Rate)
정규화 (Regularization)
지난 시간에 다룬 '데이터 손실(Data Loss)'은 모델이 학습 데이터를 얼마나 잘 설명하는지를 측정한다. 하지만 모델이 학습 데이터에만 지나치게 맞춰지면, 보지 못한 새로운 데이터(Test set)에 대해서는 성능이 떨어지는 과적합(Overfitting) 문제가 발생할 수 있다.
이를 방지하기 위해 손실 함수에 정규화(Regularization) 항을 추가한다. 정규화의 목표는 '학습 데이터에 대한 성능을 다소 희생하더라도, 테스트 데이터에서의 일반화(Generalization) 성능을 높이는 것'이다.
$$L(W)=\underbrace{\frac{1}{N} \sum_{i=1}^N L_i(f(x_i,W),y_i)}_{\text{Data Loss}}+ \underbrace{\lambda R(W)}_{\text{Regularization Loss}}$$
주요 정규화 기법은 다음과 같다 :
- L2 정규화 (L2 Regularization): 가중치 요소들의 제곱 합을 패널티로 사용한다. 가중치 감쇠(Weight Decay)라고도 부른다.
$$R(W)=\sum_k \sum_l W_{k,l}^2$$
- L1 정규화 (L1 Regularization): 가중치 요소들의 절댓값 합을 사용한다.
$$R(W)=\sum_k \sum_l |W_{k,l}|$$
L1 vs L2의 차이점:
- L2는 가중치가 전체적으로 골고루 펴져 있는(Diffuse) 작은 값들을 선호한다. 이는 입력 데이터의 모든 특징을 조금씩 고려하도록 유도한다.
- L1은 가중치 행렬이 희소(sparse)해지는 경향이 있다. 즉, 중요한 특징의 가중치만 남기고 나머지는 0으로 만든다.
[수식 해부] 왜 L2는 값을 퍼뜨리고, L1은 0으로 만들까?
이를 이해하기 위해서는 역전파(Backpropagation) 시의 미분 값을 봐야 한다.
- L2의 미분: $\frac{\partial}{\partial \omega} (\omega ^2)=2\omega $. 가중치 업데이트 시 $\omega \leftarrow w-\eta (2\lambda \omega )$ 형태가 된다. 즉, 가중치가 클수록 더 강하게 줄어들지만, 0에 가까워지면 패널티가 미미해져 0이 되지는 않고 작은 값으로 남는다. (Linear Decay)
- L1의 미분: $\frac{\partial }{\partial \omega}|\omega |= \text{sign}(\omega )$. 가중치의 크기와 상관없이 항상 상수 $\pm 1$의 힘으로 0을 향해 민다. 따라서 작은 값들도 0으로 완전히 수렴하게 된다.
[개념 풀이] Occam's Razer (오캄의 면도날)
강의에서 언급된 오캄의 면도날은 "같은 성능이라면 더 단순한 모델이 낫다"는 철학이다. 여기서 '단순함'을 수학적으로 정의하는 방법은 정규화이다. L2의 관점에서 '가중치의 분산이 더 작은 것'이 단순한 것이고, L1의 관점에서는 '0이 아닌 요소가 적은 것'이 단순한 것이다.
최적화의 기초 (Optimization Basics)
최적화는 손실 함수(Loss Lanscape)라는 계곡에서 가장 낮은 지점을 찾아가는 과정이다. 여기서 우리는 눈이 가려진 등산객과 같다. 전체 지형을 볼 수 없으며, 오직 발밑의 기울기(slope)만 느낄 수 있다.
- 무작위 탐색 (Random Search): 임의의 가중치를 여러 번 시도해보는 방법은 매우 비효율적이다.
- 경사 하강법 (Gradient Descent): 가장 가파른 경사를 따라 내려가는 방법. 수학적으로 1차원에서는 미분(Derivative), 다차원에서는 기울기(Gradient, $\nabla $)를 사용한다. 기울기는 함수가 가장 가파르게 증가하는 방향을 가리키므로, 그 반대 방향(음의 기울기, Negative Gradient)으로 이동해야 한다.
[Gradient의 차원 확인] Dimension Check $W$가 $D\times C$차원의 행렬이라면, 손실 함수 $L$에 대한 기울기 $\nabla _W L$ 역시 $W$와 동일한 $D\times C$차원을 가져야 한다. 즉, 가중치의 각 요소 $W_{ij}$ 하나하나가 손실에 미치는 영향력을 계산해야 한다.
[수치적 미분 vs 해석적 미분]
- Numerical Gradient: $f(x+h)-f(x)/h$을 이용한 근사치 계산. 구현이 쉽지만 느리고 부정확하다 주로 디버깅용(Gradient Check)으로 쓰인다.
- Analytic Gradient: 미분 공식을 이용해 정확한 수식을 도출. 빠르고 정확하지만 구현 실수가 있을 수 있다. 실제 딥러닝 라이브러리(PyTorch 등)는 이 방식을 사용한다.
경사 하강법의 변형과 문제점
기본 경사 하강법 (Batch Gradient Descent): 전체 데이터셋(N)을 사용하여 기울기를 계산한다. 데이터가 많으면 한 번 업데이트에 시간이 너무 오래 걸린다.
확률적 경사 하강법 (Stochastic Gradient Descent, SGD): 매 단계마다 미니 배치(Mini-batch)라는 작은 데이터 샘플(예: 32, 64, 256개)을 사용하여 기울기를 추정하고 업데이트한다. 훨씬 빠르지만 업데이트 경로가 '노이즈(Noisy)'하게 움직인다.
SGD의 문제점:
- 협곡(Ravines/Poor Conditioning): 한 방향으로는 경사가 급하고 다른 방향으로는 완만할 때, 경로가 지그재그로 진동(Oscillation)하며 수렴이 느려진다.
- 지역 최솟값(Local Minima) 및 안장점(Saddle Points): 기울기가 0이 되는 지점에서 멈출 수 있다. 특히 고차원 공간에서는 안장점(한쪽은 위로, 한쪽은 아래로 굽은 말안장 모양)이 지역 최솟값보다 훨씬 빈번하게 발생한다. 안장점에서도 기울기는 0이므로 학습이 정체된다.
[Insight] 고차원에서 안장점이 더 흔한 이유
강의에서 언급된 Dauphin et al.의 논문 내용은 중요하다. 100차원의 공간에서 기울기가 0인 지점이 있다고 가정하자. 이 점이 지역 최솟값이 되려면 100개의 모든 방향에서 아래로 오목해야 한다. 동전 던지기에서 모두 앞면이 나올 확률철럼 희박하다. 반면, 일부는 오목하고 일부는 볼록할 확률(안장점)은 훨씬 높다. 따라서 딥러닝에서는 Local Minima보다 Saddle Point 탈출이 더 중요한 과제이다.
고급 최적화 알고리즘 (Advanced Optimizers)
SGD의 문제점을 해결하기 위해 다양한 알고리즘이 개발되었다.
- Momentum (모멘텀)
- 개념: 물리적 관성(Inertia)을 이용한다. 기울기 방향으로 속도(Velocity)를 누적시킨다.
- 효과: 진동을 상쇄시키고, 안장점이나 평지(Local Minima)를 관성으로 돌파할 수 있게 해준다.
- 수식: $p$는 마찰 계수(주로 0.9)이다. $$v_{t+1}= pv_t+\nabla L (W_t)$$ $$W_{t+1}=W_t - \eta v_{t+1}$$
- RMSProp
- 개념: AdaGrad의 변형으로, 기울기 제곱의 지수 이동 평균(Exponential Moving Average)을 구한다.
- 효과: 기울기가 큰 방향(진동이 심한 축)은 가중치를 나눠주어 업데이트 폭을 줄이고, 기울기가 작은 방향은 업데이트 폭을 늘린다. 이를 통해 타원형 등고선을 원형으로 보정하여 진동을 줄이고 수렴 속도를 높이낟.
- 수식: $$\text{cache}=\text{decay_rate}\cdot \text{cache} + (1-\text{decay_rate})\cdot (\nabla L)^2$$ $$W_{t+1}=W_t-\frac{\eta}{\sqrt{\text{cache} + \epsilon}} \nabla L$$
- Adam
- 개념: 가장 대중적인 알고리즘으로, Momentum(속도 관성)과 RMSProp(기울기 크기 정규화)의 장점을 결합했다.
- Bias Correction: 학습 초기에는 누적 값들이 0으로 초기화되어 있어 업데이트가 너무 커지는 문제가 발생한다. 이를 보정하기 위해 편향 보정(Bias Correction)이라는 항을 추가하낟.
- 일반적인 하이퍼파라미터: $\beta _1 = 0.9,\beta _2=0.999,\eta=1e-3$
[심화] Adam vs AdanW
- Adam: L2 정규화를 손실 함수에 포함시켜 미분값(Gradient)을 계산할 때 함께 처리한다.
- AdamW: L2 정규화(Weight Decay)를 Gradient 업데이트와 분리(Decoupling)한다. Adam의 적응형 학습률 로직이 Weight Decay 효과를 왜곡시키는 것을 방지하기 위해서다. 최근 LLM(Llama 등)이나 대형 모델 학습 시에는 Adam보다 AdamW가 표준으로 사용된다.
학습률 스케줄링 및 2차 최적화
- Learning Rate Decay: 학습이 진행될수록 학습률을 줄여 더 정교하게 수렴하도록 한다.
- Step Decay: 특정 에폭마다 일정 비율(예: 0.1배)로 감소. (ResNet 학습 시 주로 사용)
- Cosine Decay: 코사인 곡선을 그리며 부드럽게 감소
- Linear Warmup: 초기에 학습률을 0에서 목표치까지 선형적으로 올린 후 감소시킴.
- 2차 최적화 (Second-Order Optimization): 해시안 행렬(Hessian Matrix, 2계 미분)을 사용하여 곡률(Curvature)까지 고려하는 방법(예: Newton's method)이다.
- 이론적으로는 한 번에 최적점으로 이동할 수 있지만, 딥러닝에서는 하이퍼파라미터 수가 너무 많아 해시안 행렬(N x N)을 메모리에 올릴 수 없어 사용하지 않는다.
코드 구현 - Adam Optimizer
강의에서 다룬 Adam Optimizer의 핵심 로직을 Python 코드로 구현한 예시이다. (Bias Correction 포함)
import numpy as np
class AdamOptimizer:
def __init__(self, learning_rate=1e-3, beta1=0.9, beta2=0.999, epsilon=1e-8):
self.lr = learning_rate
self.beta1 = beta1
self.beta2 = beta2
self.epsilon = epsilon
self.m = None # 1차 모멘트 (Momentum)
self.v = None # 2차 모멘트 (RMSProp)
self.t = 0 # 타임 스텝
def update(self, w, grad_w):
# 초기화
if self.m is None: self.m = np.zeros_like(w)
if self.v is None: self.v = np.zeros_like(w)
self.t += 1
# 1. Momentum 업데이트 (1차 모멘트)
self.m = self.beta1 * self.m + (1 - self.beta1) * grad_w
# 2. RMSProp 업데이트 (2차 모멘트 - Gradients의 제곱)
self.v = self.beta2 * self.v + (1 - self.beta2) * (grad_w ** 2)
# 3. Bias Correction (초기 0으로 쏠림 방지)
m_hat = self.m / (1 - self.beta1 ** self.t)
v_hat = self.v / (1 - self.beta2 ** self.t)
# 4. 파라미터 업데이트
# 1차 모멘트 방향으로 이동하되, 2차 모멘트로 스텝 크기 조절
w_new = w - self.lr * m_hat / (np.sqrt(v_hat) + self.epsilon)
return w_new
Review Quiz
이 질문들은 딥러닝 엔지니어 면접에서 자주 등장하는 심화 질문이다.
Q1. 손실 함수가 Convex(볼록)하지 않은 딥러닝 모델에서 경사 하강법이 잘 작동하는 이유는 무엇이며, 안장점(Saddle Point)에서 SGD와 Momentum, Adam은 각각 어떻게 동작하는가?
Q2. L1 정규화와 L2 정규화가 가중치 업데이트 식(Gradient Descent Update Rule)에 미치는 영향을 수식으로 설명하고, 왜 L1이 희소성(Sparsity)을 유도하는지 설명하시오.
Q3. Adam Optimizer에서 초기 단계(t가 작을 때)에 Bias Correction이 없다면 어떤 문제가 발생하며, 이것이 학습 안정성에 미치는 영향은 무엇입니까?