Skip to main content

학습률 스케줄러

학습률(Learning Rate)을 학습 과정에서 동적으로 조정하는 기법입니다. 초반에는 높은 학습률로 빠르게 탐색하고, 후반에는 낮은 학습률로 정밀하게 수렴합니다.
1

StepLR

고정 간격마다 학습률을 감쇠시킵니다.
import torch.optim as optim

optimizer = optim.Adam(model.parameters(), lr=0.01)
scheduler = optim.lr_scheduler.StepLR(
    optimizer,
    step_size=10,    # 10 에포크마다
    gamma=0.1,       # 0.1배로 감쇠
)

for epoch in range(30):
    train_one_epoch(model, train_loader, criterion, optimizer, device)
    scheduler.step()  # 에포크 종료 후 호출
    print(f"Epoch {epoch+1}: lr = {scheduler.get_last_lr()[0]:.6f}")
2

CosineAnnealingLR

코사인 함수 형태로 학습률을 부드럽게 감쇠합니다.ηt=ηmin+12(ηmaxηmin)(1+cos(TcurTmaxπ))\eta_t = \eta_{min} + \frac{1}{2}(\eta_{max} - \eta_{min})\left(1 + \cos\left(\frac{T_{cur}}{T_{max}}\pi\right)\right)
scheduler = optim.lr_scheduler.CosineAnnealingLR(
    optimizer,
    T_max=50,       # 전체 에포크 수
    eta_min=1e-6,   # 최소 학습률
)
3

CosineAnnealingWarmRestarts

주기적으로 학습률을 리셋(Warm Restart)하여 지역 최솟값을 탈출합니다.
scheduler = optim.lr_scheduler.CosineAnnealingWarmRestarts(
    optimizer,
    T_0=10,     # 첫 번째 주기 길이
    T_mult=2,   # 주기마다 2배 증가 (10→20→40)
)
4

OneCycleLR

학습률을 선형으로 증가 후 코사인으로 감소시킵니다. 빠른 수렴에 효과적입니다.
scheduler = optim.lr_scheduler.OneCycleLR(
    optimizer,
    max_lr=0.01,
    epochs=30,
    steps_per_epoch=len(train_loader),
)

# 주의: 배치마다 호출해야 함
for epoch in range(30):
    for batch in train_loader:
        optimizer.step()
        scheduler.step()  # 매 배치 후 호출
5

Linear Warmup + Cosine Decay

Transformer 학습에서 가장 많이 사용되는 패턴입니다.
from torch.optim.lr_scheduler import LambdaLR

def get_cosine_schedule_with_warmup(optimizer, warmup_steps, total_steps):
    def lr_lambda(current_step):
        if current_step < warmup_steps:
            return float(current_step) / float(max(1, warmup_steps))
        progress = float(current_step - warmup_steps) / float(max(1, total_steps - warmup_steps))
        return max(0.0, 0.5 * (1.0 + torch.cos(torch.tensor(progress * 3.14159)).item()))
    return LambdaLR(optimizer, lr_lambda)

total_steps = len(train_loader) * num_epochs
warmup_steps = int(0.1 * total_steps)  # 전체의 10%

scheduler = get_cosine_schedule_with_warmup(optimizer, warmup_steps, total_steps)

스케줄러 비교

스케줄러형태주 사용처호출 시점
StepLR계단식 감쇠간단한 실험에포크
CosineAnnealingLR코사인 감쇠CNN 학습에포크
OneCycleLR증가 → 감소빠른 수렴배치
Warmup + Cosine선형 증가 → 코사인 감소Transformer배치

체크리스트

  • CosineAnnealing과 OneCycleLR의 차이를 이해한다
  • Warmup의 목적과 적용 방법을 안다
  • scheduler.step()의 호출 시점(에포크 vs 배치)을 구분할 수 있다

다음 문서