본문 바로가기
C.W.K.
Stream
Lesson 03 of 08 · published

옵티마이저: SGD, Adam, AdamW, 매개변수 그룹

~14 min · optimizer, sgd, adam, adamw, weight_decay

Level 0텐서 탐구자
0 XP0/62 lessons0/13 achievements
0/120 XP to next level120 XP to go0% complete

실제로 자주 쓰는 세 가지 옵티마이저

  • SGD(보통 모멘텀과 함께 사용): 오래됐지만 잘 이해된 방법이고 메모리 비용도 낮아. 학습률 일정을 알맞게 조정하면 비전 작업에서 Adam과 비슷하거나 더 나은 성능을 내기도 해. CIFAR와 ImageNet 재현 실험의 기본 선택이야.
  • Adam: 기울기의 1차와 2차 모멘트에 대한 누적 추정치를 이용해 매개변수마다 학습률을 조절해. 작업의 특성을 아직 잘 모를 때 무난한 출발점이야.
  • AdamW: Adam에 분리된 가중치 감쇠를 적용해. Transformer, 미세 조정, 비전 이외의 많은 딥러닝 작업에서 사실상 현대적인 표준이야. 2026년 논문에서 'Adam'이라고 쓰더라도 실제 구현은 AdamW인 경우가 많아.

왜 Adam보다 AdamW일까?

기존 Adam의 weight_decay는 기울기에 감쇠 항을 더하는 방식이었어. AdamW는 가중치 감쇠를 기울기 갱신과 분리해 적용하며, 경험적으로 더 나은 동작을 보여. 현대적인 학습 구성에서는 AdamW를 우선해.

매개변수 그룹별 설정

옵티마이저는 평평한 매개변수 목록뿐 아니라 서로 다른 설정을 가진 매개변수 그룹 목록도 받을 수 있어. 대표적인 용도는 사전 학습된 백본에는 낮은 학습률을, 새 헤드에는 높은 학습률을 주는 거야. Transformer에서는 편향과 LayerNorm 매개변수에 가중치 감쇠를 적용하지 않는 구성도 흔해.

Code

세 최적화 도구, 세 맛·python
import torch
import torch.nn as nn
import torch.optim as optim

model = nn.Sequential(nn.Linear(100, 50), nn.ReLU(), nn.Linear(50, 10))

# SGD with momentum and weight decay — vision classic
opt_sgd = optim.SGD(model.parameters(), lr=1e-1, momentum=0.9, weight_decay=1e-4)

# Adam — adaptive, decoupled-weight-decay-FREE (the bad version)
opt_adam = optim.Adam(model.parameters(), lr=1e-3, betas=(0.9, 0.999))

# AdamW — adaptive AND decoupled weight decay (the good version)
opt_adamw = optim.AdamW(model.parameters(), lr=1e-3, betas=(0.9, 0.999), weight_decay=0.01)
그룹별 학습률: 사전 학습 백본 + 새 헤드·python
import torch.optim as optim
import torch.nn as nn
from torchvision.models import resnet18, ResNet18_Weights

backbone = resnet18(weights=ResNet18_Weights.DEFAULT)
backbone.fc = nn.Linear(backbone.fc.in_features, 5)   # new head

# Lower LR for pretrained, higher for new head
optimizer = optim.AdamW([
    {'params': [p for n, p in backbone.named_parameters() if 'fc' not in n], 'lr': 1e-5},
    {'params': backbone.fc.parameters(), 'lr': 1e-3},
], weight_decay=0.01)

for i, g in enumerate(optimizer.param_groups):
    print(f"group {i}: lr={g['lr']}, n_params={sum(p.numel() for p in g['params']):,}")
편향과 LayerNorm에는 가중치 감쇠를 적용하지 않는 Transformer 관례·python
import torch.optim as optim
import torch.nn as nn

model = nn.TransformerEncoder(nn.TransformerEncoderLayer(512, 8, batch_first=True), num_layers=6)

# Standard Transformer training trick — exclude bias and norm params from weight decay
decay, no_decay = [], []
for name, p in model.named_parameters():
    if not p.requires_grad: continue
    if p.dim() < 2 or any(k in name for k in ('bias', 'norm', 'embedding')):
        no_decay.append(p)
    else:
        decay.append(p)

optimizer = optim.AdamW([
    {'params': decay, 'weight_decay': 0.01},
    {'params': no_decay, 'weight_decay': 0.0},
], lr=1e-4)

print(f"decay: {sum(p.numel() for p in decay):,}, no_decay: {sum(p.numel() for p in no_decay):,}")

External links

Exercise

작은 모델 하나를 골라 같은 간단한 데이터에서 서로 다른 옵티마이저로 100단계씩 세 번 학습해 봐. SGD는 lr=1e-2와 momentum=0.9, Adam은 lr=1e-3, AdamW는 lr=1e-3과 weight_decay=0.01을 사용해. 손실 곡선을 그리면 AdamW와 Adam은 초반에 거의 같아 보이고, SGD는 학습률을 따로 조정하지 않으면 뒤처질 가능성이 커.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.