5줄 루틴
학습의 기본 단위는 한 단계야. 언제나 같은 5줄을 같은 순서로 실행해:
opt.zero_grad(): 이전 단계에서 남은 기울기를 지워.logits = model(xb): 순전파를 실행해.loss = loss_fn(logits, yb): 스칼라 손실을 계산해.loss.backward(): autograd로 기울기를 계산해.opt.step(): 계산한 기울기를 매개변수에 적용해.
필요하다면 역전파와 매개변수 갱신 사이에 clip_grad_norm_을 넣고, 매개변수를 갱신한 다음 scheduler.step()을 실행해. 이게 학습 루프 본문의 전부야. 나머지는 모두 이 흐름을 뒷받침하는 주변 코드야.
팁: 이 5줄을 외워서 화이트보드에 바로 적지 못한다면 아직 손에 익지 않은 거야. 20번 써 봐. 나중에는 문장이 끝나기도 전에
opt.zero_grad()부터 치게 될 거야.자주 만나는 두 가지 버그
zero_grad() 잊음: 기울기가 학습 단계마다 계속 누적돼서, 각 단계가 이전의 모든 기울기를 합친 값을 보게 돼. 손실은 높은 채로 머물고 학습은 무너져. 수정은 한 줄이면 돼.
loss.backward() 전에 opt.step(): 이전 배치에서 남은 오래된 기울기로 매개변수를 갱신하게 돼. 손실 곡선만 보면 어렴풋이 학습하는 것처럼 보이지만, 모델은 실제로 현재 배치를 학습하지 않아.
기울기 누적 (zero_grad를 건너뛰는 올바른 방법)
가끔은 VRAM에 한 번에 올릴 수 있는 크기보다 더 큰 실효 배치 크기가 필요해. 이럴 때는 여러 배치를 처리하는 동안 zero_grad()를 건너뛰고, 손실을 누적 단계 수로 나눠. 마지막에 opt.step()과 opt.zero_grad()을 실행하면 돼. 이렇게 하면 accum_steps배 더 큰 단일 배치와 같은 기울기를 만들 수 있어.
원칙: 이 5줄 루틴이 학습의 가장 작은 단위야. 먼저 외워. 그런 다음 기울기 누적, 혼합 정밀도, 기울기 클리핑 같은 변형을 한 번에 하나씩 배워. 기본형을 건너뛰면 안 돼.