MNIST Lab 기본 구현 5편
SGD는 가장 단순한 파라미터 갱신 규칙이다. gradient가 손실이 증가하는 방향을 가리킨다면, 우리는 그 반대 방향으로 learning rate만큼 움직인다.
1. SGD 공식
업데이트 공식은 단순하다. param = param - lr * grad다. 여기서 lr은 한 번에 얼마나 크게 움직일지 정하는 학습률이다.
1
gradient 계산
현재 파라미터를 어느 방향으로 바꾸면 loss가 커지는지 알게 된다.
2
반대 방향 이동
loss를 줄이고 싶으므로 gradient 반대 방향으로 움직인다.
3
in-place 갱신
params 딕셔너리 안의 배열을 직접 수정한다.
2. 최종 구현 코드
class SGD:
def __init__(self, lr=0.01):
self.lr = lr
def update(self, params, grads):
for key in params.keys():
params[key] -= self.lr * grads[key]
3. 작은 숫자로 검산하기
| 값 | 예시 | 결과 |
|---|---|---|
| param | 1.0 | 현재 파라미터 |
| grad | 0.2 | 이 방향으로 가면 loss가 증가한다고 해석 |
| lr | 0.1 | 보폭 |
| new param | 1.0 - 0.1 * 0.2 = 0.98 | gradient 반대 방향으로 이동 |
4. 테스트가 묻는 것
| 테스트 | 확인 조건 |
|---|---|
| test_sgd_update_changes_params | params의 값이 gradient와 lr에 맞게 바뀌는가 |
비판적 코드 리뷰
SGD는 단순해서 디버깅 기준선으로 좋다. Adam이 잘 안 될 때도 SGD로 loss가 내려가는지 먼저 보면, 문제가 optimizer인지 다른 계층인지 좁힐 수 있다.
이번 글에서 기억할 것
SGD는 모든 파라미터를 gradient 반대 방향으로 lr만큼 이동시키는 가장 단순한 optimizer다.
스스로 점검
- 왜 gradient 방향이 아니라 반대 방향으로 이동하는가?
- learning rate가 너무 크면 어떤 문제가 생기는가?
- params를 새 dict로 만들지 않고 제자리 수정하는 이유는 무엇인가?
다음 글 예고
다음 글에서는 Adam을 구현한다. Adam은 gradient의 방향 기록과 크기 기록을 함께 사용한다.