Stochastic Gradient Descent (SGD)
SGD는 작은 무작위 데이터 배치에서 계산한 비용이 낮은 가중치 업데이트를 여러 차례 수행해 모델을 학습합니다. 업데이트 규칙, 모멘텀, 배치 크기, 코드를 다룹니다.
확률적 경사 하강법(SGD)은 전체 데이터셋 대신 학습 데이터의 소규모 무작위 샘플에서 구한 손실의 그래디언트로 모델의 가중치를 반복해서 갱신하는 최적화 알고리즘입니다. 각 샘플의 그래디언트는 잡음이 있지만 편향되지 않은 전체 데이터셋 그래디언트의 추정치입니다. 따라서 SGD는 전체 배치 그래디언트 하강법이 한 번의 값비싼 업데이트를 수행할 시간에 저렴한 업데이트를 여러 번 수행합니다. 이 방법은 Robbins와 Monro가 1951년에 제안한 확률적 근사법에서 비롯되었으며, 모멘텀과 함께 합성곱 신경망(CNN)의 표준 옵티마이저로 남아 있습니다.
SGD 작동 방식#
SGD의 각 단계에서는 미니 배치 B를 가져와 역전파로 해당 배치의 손실 그래디언트를 계산하고, 각 가중치를 그래디언트의 반대 방향으로 조금 이동시킵니다. w ← w − η·∇L_B(w)이며, η는 학습률입니다. 엄밀히 말해 SGD는 단계마다 예제 하나를 사용하지만, 딥러닝 프레임워크에서는 수십 개에서 수천 개의 예제로 구성된 미니 배치를 사용하므로 실제로는 "SGD"와 "미니 배치 경사 하강법"을 같은 의미로 사용합니다. 배치 크기가 커지면 그래디언트의 잡음이 줄고 하드웨어 활용률이 높아지는 대신, 에포크당 업데이트 횟수는 줄어듭니다.
학습은 각 에포크가 시작될 때 데이터를 섞고, 미니 배치로 데이터를 순회하며 배치마다 한 번씩 업데이트합니다. 잡음이 있는 점 1,000개에 직선을 피팅하는 과정을 통해 전체 절차를 확인할 수 있습니다.
import torch
torch.manual_seed(0)
# 1,000 noisy samples of y = 3x + 2
x = torch.randn(1000, 1)
y = 3 * x + 2 + 0.1 * torch.randn(1000, 1)
model = torch.nn.Linear(1, 1)
optimizer = torch.optim.SGD(model.parameters(), lr=0.05, momentum=0.9)
for epoch in range(5):
# Reshuffle every epoch, then update the weights once per 32-sample mini-batch
for idx in torch.randperm(1000).split(32):
loss = torch.nn.functional.mse_loss(model(x[idx]), y[idx])
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f"epoch {epoch}: w = {model.weight.item():.3f}, b = {model.bias.item():.3f}, loss = {loss.item():.4f}")두 에포크, 총 64회의 업데이트 후 가중치는 3.081, 편향은 2.012에 도달합니다. 이후 세 에포크 동안 가중치는 수렴하지 않고 2.967과 3.003 사이에서 계속 움직입니다. 각 미니 배치의 그래디언트에 샘플링 잡음이 포함되어 있기 때문입니다. 마지막 배치의 손실은 y에 더해진 잡음의 분산인 0.01 근처에 머뭅니다.
학습률, 노이즈 및 배치 크기#
학습률이 일정하면 SGD는 최솟값 주변에서 변동하며, 변동 영역의 크기는 학습률과 그래디언트 노이즈가 커질수록 증가합니다. 확률 근사 이론에 따르면 학습률이 0에 가까워질 때만 수렴이 보장되므로, 실제 학습에서는 일반적으로 짧은 워밍업 이후 스텝 감쇠 또는 코사인 스케줄을 사용해 학습률을 시간에 따라 낮춥니다. 작은 배치에서 발생하는 그래디언트 노이즈는 SGD가 대규모 배치 학습에서 찾는 날카로운 최솟값보다 일반화 성능이 뛰어난 평탄한 최솟값을 찾도록 유도하며, 이는 암묵적인 정규화 방식입니다.
학습률과 배치 크기는 서로 영향을 줍니다. 배치 크기에 비례해 학습률을 높이고 5에포크 동안 워밍업하면, ResNet-50은 이미지 8,192개씩 미니배치로 사용하면서 ImageNet을 1시간 만에 학습할 수 있으며 정확도도 저하되지 않습니다.
모멘텀 및 네스테로프 모멘텀#
손실 표면의 길고 좁은 골짜기에서는 그래디언트가 주로 골짜기를 가로지르는 방향을 가리키므로, 일반 SGD는 골짜기 바닥을 따라 천천히 진행하면서 양쪽 벽 사이를 지그재그로 움직입니다. 모멘텀은 누적 속도 v ← μ·v + g를 유지하고 그 방향으로 w ← w − η·v만큼 이동합니다. 따라서 일관된 그래디언트 방향은 속도를 높이고, 진동하는 방향은 서로 상쇄됩니다. 일반적으로 계수 μ = 0.9를 기본값으로 사용합니다. 네스테로프 모멘텀은 속도 방향으로 미리 이동한 지점에서 그래디언트를 계산해 오버슈트를 더 줄입니다. PyTorch의 SGD는 두 방식을 모두 구현하며, 그래디언트에 λ·w를 더하는 방식으로 weight_decay를 적용합니다. SGD에서는 이 방식이 가중치에 L2 페널티를 적용하는 것과 같습니다.
SGD와 다른 옵티마이저 비교#
- 배치 경사 하강법: 업데이트마다 전체 데이터셋에 대한 정확한 그래디언트를 계산하므로, 에포크마다 한 번만 업데이트하며 메모리 요구량은 데이터셋 크기에 따라 증가합니다.
- Adam: 각 파라미터의 그래디언트와 제곱 그래디언트의 이동 평균을 이용해 파라미터별 스텝 크기를 정합니다. 모멘텀을 사용하는 SGD가 파라미터당 상태값 하나를 저장하는 데 비해, Adam은 상태값 두 개를 저장합니다. Adam은 초기 학습 속도가 더 빠르고 학습률에 덜 민감하지만, CNN에서는 잘 조정된 모멘텀 SGD가 최종 정확도에서 Adam과 대등하거나 더 나은 경우가 많습니다. 가중치 감쇠를 분리 적용하는 변형인 AdamW는 Transformer의 표준 옵티마이저입니다.
- Muon: 각 가중치 행렬의 모멘텀 업데이트를 행렬 전체 기준으로 직교화하며, 대규모 언어 모델 학습까지 확장되었습니다.
Ultralytics YOLO 학습에서는 optimizer="SGD"을 설정하면 Nesterov 모멘텀을 사용하는 PyTorch SGD를 생성하며 기본값은 lr0=0.01 및 momentum=0.937입니다. 기본 optimizer="auto"는 lr0를 무시하고, 10,000회 반복을 초과하는 실행에는 SGD와 Muon 업데이트를 혼합한 하이브리드 MuSGD를 선택하며 더 짧은 실행에는 AdamW를 선택합니다.
SGD의 사용 분야#
모멘텀 SGD는 대표적인 ImageNet CNN 대부분을 학습하는 데 사용되었습니다. 최초의 ResNet 모델은 모멘텀 0.9, 가중치 감쇠 0.0001, 이미지 256개씩 미니배치를 사용했으며, 학습률은 0.1에서 시작해 오류가 정체될 때마다 10분의 1로 낮췄습니다. 딥러닝 외에도 scikit-learn의 SGDClassifier 및 SGDRegressor는 SGD로 로지스틱 회귀 및 선형 서포트 벡터 머신과 같은 선형 모델을 학습합니다. 또한 해당 모델의 partial_fit 메서드는 메모리에 모두 담을 수 없는 대규모 데이터셋을 한 번에 한 청크씩 학습합니다.










