옵티마이저(Optimizer)는 손실 함수를 최소화하기 위해 신경망의 가중치를 업데이트하는 알고리즘이다. 학습 속도, 수렴 안정성, 최종 성능에 직접적인 영향을 미친다.
SGD (Stochastic Gradient Descent)
$$\theta_{t+1} = \theta_t - \eta \nabla_{\theta} L(\theta_t)$$
python
import torch.optim as optim
# 모멘텀 포함 SGD
optimizer = optim.SGD(
model.parameters(), lr=0.01,
momentum=0.9, # 이전 그래디언트 방향 유지
weight_decay=1e-4, # L2 정규화
nesterov=True # Nesterov 모멘텀 (더 정확한 업데이트)
)
AdaGrad
각 파라미터마다 적응적 학습률 적용. 희소 특성에 유용.
$$G_t = G_{t-1} + g_t^2, quad \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{G_t + \epsilon}} g_t$$
RMSProp
AdaGrad의 기울기 누적 문제 해결 (지수 이동 평균).
Adam (Adaptive Moment Estimation)
1차 모멘트(평균)와 2차 모멘트(분산)를 모두 추정.
$$m_t = \beta_1 m_{t-1} + (1-\beta_1) g_t$$
$$v_t = \beta_2 v_{t-1} + (1-\beta_2) g_t^2$$
$$\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\hat{v}_t} + \epsilon} \hat{m}_t$$
python
# Adam (딥러닝 표준)
optimizer = optim.Adam(model.parameters(), lr=1e-3,
betas=(0.9, 0.999), eps=1e-8,
weight_decay=0)
# AdamW (가중치 감퇴 분리 — 트랜스포머 표준)
optimizer = optim.AdamW(model.parameters(), lr=1e-4,
betas=(0.9, 0.999), weight_decay=0.01)
# 직접 구현
class AdamOptimizer:
def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8):
self.params = list(params)
self.lr, self.b1, self.b2, self.eps = lr, *betas, eps
self.m = [torch.zeros_like(p) for p in self.params]
self.v = [torch.zeros_like(p) for p in self.params]
self.t = 0
def step(self):
import torch
self.t += 1
for i, p in enumerate(self.params):
if p.grad is None: continue
g = p.grad.data
self.m[i] = self.b1 * self.m[i] + (1 - self.b1) * g
self.v[i] = self.b2 * self.v[i] + (1 - self.b2) * g**2
m_hat = self.m[i] / (1 - self.b1**self.t)
v_hat = self.v[i] / (1 - self.b2**self.t)
p.data -= self.lr * m_hat / (v_hat.sqrt() + self.eps)
옵티마이저 비교
| 옵티마이저 | 적응 학습률 | 모멘텀 | 추천 상황 |
|---|
| SGD | 없음 | 선택적 | 컴퓨터 비전(ResNet 등) |
| AdaGrad | 있음 | 없음 | 희소 특성 |
| RMSProp | 있음 | 있음 | RNN |
| Adam | 있음 | 있음 | 일반 딥러닝 |
| AdamW | 있음 | 있음 | 트랜스포머, LLM |
관련 개념