SGD·AdamW·LBFGS·CG·확률 최적화의 선택 기준
SGD, AdamW, LBFGS, Conjugate Gradient, Stochastic Programming의 특성과 문제 조건별 선택·튜닝 기준을 정리한다.
2026-08-14 · 최초 발행 2025-10-14
문제 조건이 옵티마이저를 가른다
최적화는 목적함수를 최소화하거나 최대화할 변수를 찾는 과정이다. 같은 목적함수라도 미분 가능성, 데이터의 노이즈, 제약조건, 모델 규모에 따라 적합한 탐색 방법이 달라진다.
SGD와 Adam 계열은 그래디언트를 이용하는 1차 기법이다. LBFGS와 CG는 헤시안 또는 그 근사를 통해 곡률 정보를 활용하는 계열에 속한다. 한편 확률적 프로그래밍은 수요·가격·고장률처럼 불확실한 입력을 전제로 기대값이나 리스크 기준을 최적화한다. 시나리오 기반의 샘플 평균 근사(SAA), 강건 모델, 확률제약 모델이 이 범주에 들어간다.
각 기법이 다루는 문제
SGD
확률적 경사하강법은 미니배치에서 구한 추정 기울기로 기대 기울기를 근사한다. 구현이 단순하고 메모리 부담이 낮으며, 대규모 학습으로 확장하기 좋다. 학습률 스케줄, 모멘텀, 정규화의 조합에 따라 결과가 크게 달라진다.
Adam과 AdamW
Adam은 1차·2차 모멘트 추정으로 적응형 학습률을 적용한다. 초기 수렴이 빠른 편이며, AdamW는 weight decay를 분리해 적용해 일반화 개선을 노린다. 노이즈가 크거나 비정규화된 데이터에서도 강인한 편이다.
LBFGS
LBFGS는 제한된 메모리 안에서 헤시안 역행렬 근사를 축적하는 준-뉴턴 방식이다. 배치 그래디언트와 라인서치가 필요하므로, 중소형 규모의 매끄럽고 잘 스케일된 목적함수에 적합하다.
Conjugate Gradient
CG는 대규모 대칭 양정(PSD) 선형계 Ax=b를 풀거나 2차 최적화의 내부 솔버로 쓴다. 행렬-벡터 곱을 반복하는 방식이라 메모리 효율이 좋다. 실제 성능은 사전조건(preconditioning)에 크게 좌우된다.
Stochastic Programming
Stochastic Programming은 불확실성 아래에서 기대 비용이나 CVaR 같은 리스크를 최소화한다. 보통 시나리오 생성, SAA, 정책 추정, 검증 순으로 진행하며, 강건 최적화나 확률제약과의 트레이드오프도 함께 판단해야 한다.
운영 관점에서 비교할 항목
| 알고리즘 | 수렴 속도(초기/후반) | 확장성(데이터/모델) | 일관성(재현성) | 안정성(학습/수치) | 운영 편의 |
|---|---|---|---|---|---|
| SGD | 보통/양호(스케줄 의존) | 우수(분산·대규모) | 높음(시드·스케줄 고정 시) | 양호(폭주 시 클리핑 필요) | 매우 간단 |
| Adam/AdamW | 빠름/보통 | 우수(이질/잡음 데이터) | 보통(적응 스텝 변동) | 강함(노이즈 견고) | 간단(튜닝 관용) |
| LBFGS | 빠름/빠름(매끄러움 가정) | 중간(배치 필요) | 높음(결정론적 라인서치) | 민감(스케일·라인서치 실패) | 보통(클로저 필요) |
| CG | 문제 의존(사전조건 좌우) | 우수(희소/대규모) | 높음 | 중간~강함(PSD·조건수 영향) | 보통(선형계·사전조건 설계) |
| Stochastic Programming | 시나리오·솔버 의존 | 중간(시나리오 폭증 주의) | 높음(시나리오 고정 시) | 강함(리스크 제어) | 보통~어려움(모형화·솔버) |
모델 학습과 운영 최적화에서의 배치
대규모 비전·자연어 모델에는 AdamW와 코사인 또는 원사이클 스케줄을 적용할 수 있다. 이때 배치 정규화와 가중 감쇠의 상호작용도 함께 확인한다. 라벨 노이즈가 적고 일반화 성능을 중시한다면 SGD와 모멘텀, 스텝 또는 코사인 기반의 장기 스케줄을 검토할 수 있다.
수십만 파라미터 이하의 밀집 특성을 가진 로지스틱 회귀나 회귀 문제는 LBFGS로 고정밀 수렴을 빠르게 얻을 수 있다. PDE 역문제와 희소 선형 시스템에는 사전조건을 결합한 CG가 적합하다.
뉴스벤더 재고 운용이나 포트폴리오 CVaR 최소화처럼 수요 불확실성을 포함하는 문제에는 Stochastic Programming을 적용한다. 시나리오 축소와 다단계 의사결정에서는 Benders, Progressive Hedging 같은 분해 기법도 활용한다.
선택부터 검증까지의 흐름
입력으로는 목적함수의 미분 가능성, 데이터 규모와 노이즈, 파라미터 수, 제약조건, 사용할 수 있는 리소스를 확인한다.
딥러닝 분류·회귀 문제에서는 노이즈와 스케일을 기준으로 SGD와 AdamW를 선택한 뒤 코사인·원사이클·스텝 스케줄을 정한다. 이어 weight decay와 clipping을 적용한다. 매끄러운 중소형 문제에는 Armijo 또는 Wolfe 라인서치를 포함한 LBFGS를 두고, 스케일링과 표준화를 먼저 수행한다.
대규모 선형계나 내부 반복 문제는 ILU, Jacobi, AMG 등의 사전조건과 CG를 조합하고 잔차·조건수를 종료 기준으로 둔다. 불확실성이 핵심인 경우에는 시나리오 생성, SAA, 아웃오브샘플 교차검증, 정책 고정의 흐름으로 진행한다.
출력물에는 수렴 기준을 만족한 모델 또는 정책뿐 아니라 학습 로그, 체크포인트, 재현성 설정도 포함한다. 그래디언트 폭주나 소실에는 gradient clipping, mixed precision loss scaling 조정, 초기화 재설계를 적용한다. LBFGS 라인서치가 실패하면 스텝 제한, 목적함수 스케일링, 초기 감쇠 스텝을 검토한다. CG가 발산하거나 정체하면 사전조건을 바꾸고 재시작 전략 및 대칭·PSD 위반 여부를 점검한다. SP의 시나리오가 과도하게 늘어나면 시나리오 축소, 중요도 샘플링, 분해 알고리즘을 고려한다.
실행 예제
전제조건은 다음과 같다.
- Python 3.10+
- PyTorch 2.2+ (SGD/Adam/LBFGS, CG 예시 1)
- SciPy 1.11+ (CG/최적화 예시 2)
PyTorch에서 SGD·AdamW·LBFGS 사용
# pip install torch==2.2.0 torchvision==0.17.0
import torch
from torch import nn
from torch.optim import SGD, AdamW, LBFGS
from torch.optim.lr_scheduler import CosineAnnealingLR
model = nn.Sequential(nn.Linear(100, 50), nn.ReLU(), nn.Linear(50, 10))
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
criterion = nn.CrossEntropyLoss()
# 선택: AdamW 또는 SGD+모멘텀
use_adamw = True
if use_adamw:
optimizer = AdamW(model.parameters(), lr=3e-4, weight_decay=0.01, betas=(0.9, 0.999))
else:
optimizer = SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4, nesterov=True)
scheduler = CosineAnnealingLR(optimizer, T_max=50)
# 더미 데이터
x = torch.randn(256, 100, device=device)
y = torch.randint(0, 10, (256,), device=device)
for epoch in range(5):
model.train()
optimizer.zero_grad(set_to_none=True)
logits = model(x)
loss = criterion(logits, y)
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
optimizer.step()
scheduler.step()
print(f"epoch {epoch} loss {loss.item():.4f}")
# LBFGS 사용 예: 전체 배치 + 클로저 필요
lbfgs = LBFGS(model.parameters(), lr=1.0, max_iter=20, history_size=10, line_search_fn="strong_wolfe")
def closure():
lbfgs.zero_grad()
logits = model(x)
loss = criterion(logits, y)
loss.backward()
return loss
loss = lbfgs.step(closure)
print(f"LBFGS final loss {loss.item():.4f}")
PyTorch에서 CG로 선형계 풀기
# PyTorch 2.2+
A = torch.randn(1000, 1000)
A = A @ A.T + 1e-3 * torch.eye(1000) # 대칭 양정 행렬 구성
b = torch.randn(1000)
# 행렬-벡터 연산자로 정의하면 대규모 희소 행렬에도 적합
def mv(v):
return A @ v
# torch.linalg.cg 사용
x, info = torch.linalg.cg(mv, b, maxiter=200, atol=1e-6)
print("CG converged:", info == 0)
SciPy에서 SAA 뉴스벤더 모형 실행
# pip install scipy==1.11.0 numpy==1.26.0
import numpy as np
from scipy.optimize import minimize
np.random.seed(42)
# 수요 불확실성 샘플(시나리오)
demand = np.random.lognormal(mean=3.0, sigma=0.5, size=5000)
c = 2.0 # 구매단가
p = 5.0 # 판매가격
h = 0.5 # 잉여 보관비
def saa_cost(q, samples):
q = np.clip(q[0], 0, 1e6)
sales = np.minimum(q, samples)
leftover = np.maximum(q - samples, 0)
return c*q - p*np.mean(sales) + h*np.mean(leftover)
# 샘플 평균 근사(SAA)로 1차원 연속 최적화
res = minimize(saa_cost, x0=[100.0], args=(demand,), method="L-BFGS-B", bounds=[(0.0, None)])
print("Optimal order quantity (SAA):", res.x[0], "cost:", res.fun)
성능과 리스크를 함께 관리하기
AdamW와 적절한 스케줄을 조합하면 동일 에폭 대비 초기 수렴 속도가 빨라지는 경향이 있다. 대형 모델에서는 실험적으로 10~30% 학습 시간 단축 사례가 보고됐으며, 이는 데이터·모델·하이퍼파라미터에 의존하므로 환경별 재검증이 필요하다.
CG와 LBFGS는 헤시안을 직접 계산하지 않고도 곡률 정보를 활용한다. 뉴턴 방법과 비교해 메모리를 수 배 줄일 수 있고, 희소 또는 대규모 선형계에서 CG로 수렴 가능성을 확보할 수 있다.
Stochastic Programming은 아웃오브샘플 성능의 변동을 완화하고 CVaR 같은 리스크 지표 개선에 기여할 수 있다. 다만 시나리오 설계 품질에 민감하므로 검증 데이터로 효과를 확인해야 한다.
운영에서는 시드와 스케줄을 고정해 재현성을 확보하고, 로깅·체크포인트·예외 대응 규칙을 표준화한다. 소규모 검증 실험에서 시작해 하이퍼파라미터 스윕을 거친 뒤 스케일 아웃하는 순서가 적합하다.