Weight Decay
가중치 감쇠는 모델 가중치를 0에 가깝게 줄이는 정규화 기법으로, 신경망이 과적합을 줄이고 새로운 데이터에 일반화하는 데 도움이 됩니다.
가중치 감쇠는 학습 중 모델의 학습된 가중치를 0에 가깝게 당기는 정규화 기법입니다. 이러한 반복적인 축소는 불필요하게 큰 파라미터 값을 억제하고, 신경망이 보지 못한 예제에 일반화하도록 돕습니다. 모델의 용량이 학습 데이터의 노이즈를 암기할 만큼 충분히 큰 경우 특히 유용합니다.
Geoffrey Hinton은 1986년 논문 개념의 분산 표현 학습에서 가중치 감쇠를 소개했습니다. 가계도 실험에서 그는 학습된 연결을 더 쉽게 해석할 수 있도록 각 업데이트 후 가중치 크기를 0.2% 줄였습니다. 이후 가중치 감쇠는 과적합을 제어하는 데 널리 사용되었습니다.
가중치 감쇠의 작동 방식#
경사 하강법 중에 옵티마이저는 기울기를 사용해 파라미터를 변경합니다. 기울기는 각 파라미터가 손실 함수에 미치는 영향을 나타내는 도함수입니다. 가중치 감쇠는 파라미터를 0에 가깝게 당기는 효과를 더합니다. 많은 옵티마이저가 사용하는 학습률을 적용하는 방식에서, 모멘텀이 없는 일반 SGD 업데이트는 new weight = (1 - learning rate × decay) × old weight - learning rate × gradient입니다. 이 업데이트는 예측 오류를 통한 학습과 비례적인 축소를 결합합니다.
감쇠 계수는 이러한 당김의 강도를 제어합니다. 값이 0이면 감쇠가 비활성화되고, 양수 값이 커질수록 고정된 학습률에서 축소가 강해집니다. 예측을 개선하는 경우 작업 기울기는 여전히 가중치를 증가시킬 수 있습니다. 학습률 감쇠는 옵티마이저의 스텝 크기를 점차 줄이는 반면, 가중치 감쇠는 파라미터 값에 작용합니다.
가중치 감쇠와 L2 정규화 비교#
L2 정규화는 학습 목적 함수에 제곱 가중치 합에 비례하는 항을 더합니다. 일반 확률적 경사 하강법에서는 이 페널티를 미분하면 계수를 적절히 일치시켰을 때 동일한 비례적 축소가 발생합니다. 선형 회귀에서 이러한 제곱 가중치 페널티를 적용한 피팅을 능형 회귀라고 합니다.
Adam 옵티마이저에 L2 페널티를 더하면 페널티 기울기가 Adam의 이동 평균과 파라미터별 스케일 조정을 거칩니다. 반면 AdamW는 이러한 적응형 기울기 계산과 별도로 축소를 적용합니다. Ilya Loshchilov와 Frank Hutter는 2017년 논문 분리된 가중치 감쇠 정규화에서 AdamW를 소개했으며, 이 논문은 ICLR 2019에서 발표되었습니다. 이러한 분리를 통해 감쇠 강도는 Adam의 기울기 이력에 따른 스케일 조정과 무관해집니다.
감쇠 강도 선택#
가중치 감쇠는 검증 데이터를 사용해 선택하는 하이퍼파라미터입니다. 감쇠가 너무 약하면 과적합을 충분히 억제하지 못합니다. 감쇠가 지나치면 과소적합이 발생합니다. 즉, 모델이 유용한 패턴을 학습하지 못해 학습 및 검증 예제에서 오차가 커집니다. 감쇠 설정별 검증 점수를 비교하면 특정 모델과 데이터셋에 적절한 강도를 찾을 수 있습니다.
누적 효과는 학습률 스케줄과 옵티마이저 업데이트 횟수에도 영향을 받습니다. 배치 크기나 학습 에포크를 변경하면 감쇠 적용 횟수가 달라질 수 있으며, 기울기 누적은 여러 배치를 결합한 후 업데이트를 수행합니다. 드롭아웃 레이어는 활성값을 무작위로 0으로 만들어 정규화하며, 조기 종료는 학습 시간을 제한합니다.
Ultralytics YOLO는 weight_decay 학습 설정을 제공하며, 기본값은 0.0005로 YOLO26과 같은 모델을 학습할 때 정규화를 제어합니다. 옵티마이저 파라미터 그룹은 바이어스와 정규화 계층의 파라미터를 가중치 감쇠에서 제외합니다.
PyTorch에서의 가중치 감쇠#
torch.optim.AdamW 옵티마이저는 PyTorch에서 분리된 가중치 감쇠를 제공합니다. pip install torch으로 패키지를 설치합니다. 다음 예제는 작업 기울기를 0으로 설정해 출력된 업데이트에 가중치 감쇠만 반영되도록 합니다.
import torch
weight = torch.nn.Parameter(torch.tensor([2.0]))
optimizer = torch.optim.AdamW([weight], lr=0.1, weight_decay=0.1)
before = weight.item()
# Create a zero gradient while keeping the parameter in the computation.
optimizer.zero_grad()
loss = (weight * 0).sum()
loss.backward()
optimizer.step()
print(f"Weight: {before:.2f} -> {weight.item():.2f}")출력은 Weight: 2.00 -> 1.98입니다. 한 번 업데이트하면 가중치에 1 - 0.1 × 0.1을 곱해 크기가 1% 감소합니다.










