본문 바로가기
C.W.K.
Stream
Lesson 03 of 10 · published

.backward()와 .grad 버퍼

~12 min · backward, grad, scalar

Level 0텐서 탐구자
0 XP0/62 lessons0/13 achievements
0/120 XP to next level120 XP to go0% complete

기울기를 계산하고 누적하는 법

tensor.backward()는 역전파를 시작하는 호출이야. 기본적으로 스칼라 텐서에서 호출해. 출력이 스칼라가 아니라면 각 출력 원소에 얼마만큼의 가중치를 줄지 나타내는 '들어오는 기울기'를 인자로 넘겨야 해. 일반적인 지도 학습에서는 손실이 스칼라이므로 이 인자를 쓸 일이 거의 없어.

.grad 누산기

역전파가 끝나면 기울기는 leaf_tensor.grad에 저장돼. 여기서 꼭 기억할 점이 있어. 역전파를 여러 번 호출하면 새 기울기가 기존 .grad에 더해지며, 이전 값을 덮어쓰지 않아. 모든 학습 반복문에 optimizer.zero_grad()가 있는 이유가 바로 누산기를 초기화하기 위해서야.

물론 이 누적 동작이 유용할 때도 있어. 여러 미니배치의 기울기를 모아 큰 배치를 흉내 내는 기울기 누적을 간단히 구현할 수 있거든.

스칼라가 아닌 출력

스칼라가 아닌 텐서에서 .backward()를 호출해야 한다면 출력과 같은 모양의 텐서를 '들어오는 기울기'로 넘겨야 해. 이렇게 벡터-야코비안 곱(vJP)을 계산해. 일반적인 학습보다는 샘플별 기울기나 사용자 정의 손실을 다루는 연구 코드에서 더 자주 만나.

Code

스칼라 역전파: 표준 케이스·python
import torch

x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
y = (x ** 2).sum()        # collapse to scalar
y.backward()
print(x.grad)             # tensor([2., 4., 6.])
누적: zero_grad가 존재하는 이유·python
import torch

x = torch.tensor(2.0, requires_grad=True)

(x ** 2).backward()       # dy/dx = 4
print(x.grad)             # tensor(4.)

(x ** 3).backward()       # dy/dx = 12, but accumulates with the 4
print(x.grad)             # tensor(16.) — 4 + 12

# The fix in real training:
x.grad = None             # or .zero_() — both work; None is faster
(x ** 3).backward()
print(x.grad)             # tensor(12.)
기울기 누적: 작은 GPU에서 큰 배치·python
import torch
import torch.nn as nn

model = nn.Linear(10, 2)
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
loss_fn = nn.MSELoss()
accumulation_steps = 4

optimizer.zero_grad()
for i in range(8):  # 8 mini-batches → effective batch = 8 * micro-batch
    x = torch.randn(16, 10)
    y = torch.randn(16, 2)
    loss = loss_fn(model(x), y) / accumulation_steps   # scale!
    loss.backward()                                     # accumulates

    if (i + 1) % accumulation_steps == 0:
        optimizer.step()
        optimizer.zero_grad()

External links

Exercise

누적 버그를 일부러 재현해 봐. zero_grad가 빠진 5단계 학습 반복문을 만들고, 매 단계가 끝날 때 매개변수의 L2 노름을 출력해. 그다음 zero_grad를 추가해 다시 실행해. 두 경우의 노름 변화 양상이 뚜렷하게 달라져야 해. 각각을 그래프로 그려 나중에 참고할 수 있게 보관해 둬.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.