기울기는 쌓여요 — 누적과 zero_grad ★★★
이 장에서 시험에 가장 잘 나올 부분이에요. backward()를 부를 때마다 PyTorch는 기울기를 덮어쓰지 않고 기존 값에 더해요(+=). 이것을 누적이라고 해요.
정산기에 어제 낸 금액이 안 지워진 채로 오늘 금액이 더해지면 총액이 엉망이 돼요. 새 계산을 하기 전에 정산기를 0으로 되돌려야 해요. zero_grad(기울기 0으로 만들기)가 그 "초기화 버튼"이에요.
교수님이 수업에서 든 예예요. 기존에 기울기가 1이었는데 새 기울기 3이 계산되면 덮어써서 3이 되는 게 아니라 더해져서 4가 돼요.
| 단계 | 그 단계의 기울기 | 저장된 .grad |
|---|---|---|
L1 = w² backward | 2w = 2×2 = 4 | 4 |
L2 = w³ backward | 3w² = 3×4 = 12 | 4 + 12 = 16 |
zero_() | — | 0으로 지워요 |
L3 = w⁴ backward | 4w³ = 4×8 = 32 | 0 + 32 = 32 |
왜 누적이 기본일까요? 같은 파라미터가 여러 경로로 loss에 영향을 주면, 각 경로의 기울기를 모두 더해야 전체 기울기가 되기 때문이에요. 하지만 보통 학습에서는 loss가 하나뿐이라서 매번 직접 지워 줘야 해요.
또 하나의 규칙이 규칙 4. 같은 계산 그래프는 한 번만 backward할 수 있다는 거예요. backward를 하면 메모리를 아끼려고 기록(그래프)을 풀어 버려요. 같은 L에서 또 부르면 오류가 나요. 다시 하려면 forward(계산)를 새로 해서 그래프를 다시 만들어야 해요.
교수님 자료의 기본 실습 2는 두 가지가 별개라는 점을 보여 줘요. 새 forward는 그래프를 새로 만들 뿐 .grad를 지우지 않아요. w = 2에서 loss = w²를 backward → 4, loss를 새로 계산해 다시 backward(초기화 없이) → 8, zero_() 후 → 0, 새 loss로 backward → 4예요.
| 하고 싶은 일 | 해야 하는 것 | 왜 |
|---|---|---|
| 이전 기울기 지우기 | grad.zero_() / optimizer.zero_grad() | 기울기가 쌓이기 때문이에요. |
| backward를 또 하기 | forward부터 다시 | 그래프가 한 번 쓰면 풀려요. |
실제 학습 루프에서는 매번 pred = model(x), loss = criterion(pred, y)를 새로 계산하니까 그래프 재사용 문제는 없어요. 대신 매 반복마다 기울기는 꼭 지워야 해요. 이것이 학습 5단계의 맨 앞 zero_grad예요(9장).
"새 forward ≠ 기울기 초기화". 그래프를 새로 만드는 것과 기울기를 지우는 것은 서로 상관없는 두 가지 일이에요. 4 → 8 → 0 → 4 순서를 기억하세요.
backward를 여러 번 호출하는 코드의 출력은 "앞 기울기 + 이번 기울기"를 손으로 더해 가면 나와요. 중간에 zero_()나 zero_grad()가 있으면 그 줄부터 0에서 다시 시작해요. 예를 들어 w=2에서 w² → w³ → (zero) → w⁴이면 4 → 16 → 32예요.
잠깐 확인 — w=2에서 L=w²를 backward하고, zero 없이 loss를 새로 계산해 또 backward하면 w.grad는?
8이에요. 첫 번째 4에 두 번째 4가 더해져요. 새로 forward를 했어도 .grad는 지워지지 않아요.
자료: 6주차 · Week04_Autograd_Loss_Optimizer · 6주차 녹취(빅데이터06), 7주차 녹취(빅데이터07)