밑바닥부터 시작하는 딥러닝 1 - 매개변수 갱신 방법
경사 하강법은 기울기를 따라 내려가면 된다는 단순한 아이디어에서 출발한다. 하지만 실제 손실 함수의 지형은 항상 둥근 그릇처럼 친절하지 않다.
길게 늘어진 골짜기에서는 SGD가 지그재그로 흔들릴 수 있고, 이를 줄이기 위해 Momentum, AdaGrad, Adam 같은 방법이 등장한다.
이번 글에서 잡을 것
- SGD는 현재 기울기만 보고 이동한다.
- Momentum은 과거 이동 방향, 즉 관성을 기억한다.
- AdaGrad는 매개변수별로 얼마나 많이 움직였는지 기억한다.
- Adam은 Momentum과 AdaGrad의 아이디어를 함께 사용한다.
SGD의 지그재그
길게 늘어진 그릇 모양의 지형에서는 한쪽 방향의 기울기가 훨씬 가파르다. SGD는 현재 위치의 가장 큰 기울기에 반응하기 때문에 정작 중심으로 부드럽게 가지 못하고 양쪽 벽을 오가며 지그재그로 이동한다.
각 optimizer의 기억
| 방법 | 무엇을 보는가 | 비유 | 효과 |
|---|---|---|---|
| SGD | 현재 기울기 | 그냥 경사 따라 내려감 | 단순하지만 흔들릴 수 있음 |
| Momentum | 과거 이동 방향 | 관성 있는 공 | 요동을 줄이고 한 방향으로 가속 |
| AdaGrad | 많이 움직인 정도 | 방향별 보폭 조절 | 많이 움직인 축의 학습률 감소 |
| Adam | 관성과 변동량 | 두 기억의 결합 | 실무에서 자주 쓰이는 안정적 선택 |
왜 Momentum은 지그재그를 줄일까
지그재그 방향은 위아래로 번갈아 힘을 받기 때문에 과거 이동을 누적하면 서로 상쇄된다. 반면 실제로 가야 하는 방향은 계속 같은 방향의 힘을 받으므로 점점 부드럽게 전진한다.
요동 방향
번갈아 반대로 움직여 누적 효과가 줄어든다.
전진 방향
작아도 계속 같은 방향이라 누적된다.
결과
골짜기 벽을 덜 타고 중심 방향으로 더 부드럽게 이동한다.
어떤 optimizer를 써야 하나
모든 문제에서 항상 최고인 방법은 없다. 다만 초반 학습에서는 SGD보다 Momentum, AdaGrad, Adam이 더 빠르거나 안정적인 경우가 많다. 지금 단계에서는 수식보다 각 방법이 무엇을 기억하는지 구분하는 것이 중요하다.
지그재그를 숫자로 보기
SGD가 긴 골짜기에서 흔들리는 이유는 가파른 축의 기울기에 너무 크게 반응하기 때문이다. 아래 표처럼 y방향은 크게 왔다 갔다 하고, x방향은 조금씩만 전진한다고 생각하면 된다.
| 반복 | x 방향 | y 방향 | 읽는 기준 |
|---|---|---|---|
| 1 | 조금 전진 | 위쪽 벽으로 크게 이동 | 튀어 오름 |
| 2 | 조금 전진 | 아래쪽 벽으로 크게 이동 | 반대편으로 튐 |
| 3 | 조금 전진 | 다시 위쪽으로 이동 | 지그재그 |
Adam을 과장해서 보지 않기
Adam은 이름만 보면 완전히 새로운 방법처럼 보이지만, 이 글의 수준에서는 '이동 방향의 관성'과 '매개변수별 보폭 조절'을 함께 쓰는 방법으로 이해하면 충분하다.
Momentum의 기억
이전에 어느 방향으로 움직였는지
AdaGrad의 기억
각 매개변수가 얼마나 많이 움직였는지
Adam의 기준
방향과 보폭을 함께 다듬는다.
갱신식을 작게 놓고 비교하기
비유만으로 끝내면 optimizer가 뜬구름처럼 보인다. 코드 모양으로 보면 차이는 기억 변수를 두는지, 그 기억을 어디에 쓰는지로 정리된다.
# SGD: 현재 기울기만 사용
W -= lr * grad
# Momentum: 이전 이동량 v를 기억
v = momentum * v - lr * grad
W += v
# AdaGrad: 과거 기울기 제곱합 h를 기억
h += grad * grad
W -= lr * grad / (np.sqrt(h) + 1e-7)
| 방법 | 기억 변수 | 그 기억의 쓰임 |
|---|---|---|
| SGD | 없음 | 현재 기울기만 보고 바로 이동 |
| Momentum | v | 이전 이동 방향을 섞어 관성 부여 |
| AdaGrad | h | 많이 움직인 매개변수의 보폭을 줄임 |
| Adam | m, v 계열 | 방향 평균과 크기 정보를 함께 사용 |
같은 기울기가 반복될 때 값이 어떻게 달라지나
기울기 `grad=0.5`, 학습률 `lr=0.1`이라고 두면 SGD는 매번 같은 크기로 이동한다. Momentum은 이동량 `v`가 누적되고, AdaGrad는 `h`가 커지며 보폭이 줄어든다.
| 반복 | SGD 이동량 | Momentum v | AdaGrad h |
|---|---|---|---|
| 1 | -0.05 | 이동량 생성 | h=0.25 |
| 2 | -0.05 | 이전 이동량이 섞임 | h=0.50 |
| 3 | -0.05 | 같은 방향이면 더 커짐 | h=0.75, 보폭 감소 |
읽는 법
여기서 중요한 것은 숫자 자체보다 'SGD는 기억이 없고, Momentum과 AdaGrad는 서로 다른 값을 누적한다'는 차이다.
스스로 점검
- SGD가 길게 늘어진 골짜기에서 지그재그로 움직이는 이유를 설명할 수 있는가?
- Momentum과 AdaGrad가 각각 무엇을 기억하는지 말할 수 있는가?
- Adam을 두 기억의 결합으로 설명할 수 있는가?
이번 글에서 기억할 것
- SGD는 현재 기울기만 보고 이동한다.
- Momentum은 과거 이동 방향, 즉 관성을 기억한다.
- AdaGrad는 매개변수별로 얼마나 많이 움직였는지 기억한다.
- Adam은 Momentum과 AdaGrad의 아이디어를 함께 사용한다.
다음 글로 이어지는 질문
다음 글에서는 학습을 안정시키는 초깃값, 배치 정규화, 드롭아웃, 검증 데이터 이야기를 묶어 정리한다.
한 줄 정리: optimizer의 차이는 단순히 공식 차이가 아니라, 학습 과정에서 무엇을 기억하고 보폭을 어떻게 조절하는지의 차이다.