본문 바로가기
C.W.K.
Stream
Lesson 01 of 08 · published

다섯 단계 해부

~12 min · loop, anatomy, rhythm

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

모든 PyTorch 학습 단계는 같은 다섯 줄로 이뤄져

이 리듬은 외워 둬. 앞으로 수없이 반복해서 쓰게 되며 기본 순서는 바뀌지 않아:

  1. optimizer.zero_grad(): 이전 단계에서 누적된 기울기를 비워.
  2. output = model(batch): 순전파를 실행하고 autograd 그래프를 만들어.
  3. loss = criterion(output, target): 스칼라 손실을 계산해.
  4. loss.backward(): 역전파를 실행해 모든 리프 텐서의 .grad를 채워.
  5. optimizer.step(): 계산한 기울기에 갱신 규칙을 적용해.

이 순서는 꼭 지켜야 해. 순전파 뒤에 손실을 계산하고, 손실 뒤에 역전파하며, 기울기가 생긴 뒤에 매개변수를 갱신해. zero_grad는 이 모든 과정 전이나 바로 앞 반복이 끝난 뒤에 호출해. 순서를 섞으면 오류 없이 조용히 잘못될 수 있어.

다섯 단계를 감싸는 구조

  • 에포크를 도는 바깥 반복문이 있어. 한 에포크는 데이터셋 전체를 한 번 처리하는 단위야.
  • DataLoader의 배치를 도는 안쪽 반복문이 있어.
  • 각 에포크가 시작될 때 model.train()을 호출해. 학습 모드가 기본값이라 반복문 전에 한 번만 호출해도 돼.
  • model.eval()torch.inference_mode()를 사용해 주기적으로 평가해.

이게 학습 반복문의 전체 뼈대야. 학습률 조정기, 기울기 제한, 혼합 정밀도, 기록, 체크포인팅은 모두 이 다섯 단계 주위에 쌓여.

Code

최소 완전 학습 반복문·python
import torch
import torch.nn as nn

model = nn.Linear(10, 2)
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-3)
criterion = nn.MSELoss()

for epoch in range(num_epochs):
    model.train()
    for x_batch, y_batch in train_loader:
        # 1. clear gradients
        optimizer.zero_grad()

        # 2. forward
        out = model(x_batch)

        # 3. loss
        loss = criterion(out, y_batch)

        # 4. backward
        loss.backward()

        # 5. step
        optimizer.step()
흔한 추가: 제한, 학습률 조정, 평가·python
import torch
import torch.nn as nn

# Setup
model = nn.Linear(10, 2)
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-3)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=50)
criterion = nn.MSELoss()

for epoch in range(50):
    model.train()
    for x, y in train_loader:
        optimizer.zero_grad()
        loss = criterion(model(x), y)
        loss.backward()
        torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)  # ← optional but common
        optimizer.step()

    scheduler.step()                    # ← per-epoch scheduler

    # Quick eval pass
    model.eval()
    with torch.inference_mode():
        val_loss = sum(criterion(model(x), y).item() for x, y in val_loader) / len(val_loader)
    print(f"epoch {epoch}: val_loss = {val_loss:.4f}")
'안전 단위 시험': 내 반복문이 실제로 학습?·python
import torch
import torch.nn as nn

# Tiny sanity test: can we overfit a single batch?
model = nn.Linear(10, 2)
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-2)
criterion = nn.MSELoss()

x = torch.randn(8, 10)
y = torch.randn(8, 2)

losses = []
for step in range(200):
    optimizer.zero_grad()
    loss = criterion(model(x), y)
    loss.backward()
    optimizer.step()
    losses.append(loss.item())

print(f"loss start: {losses[0]:.6f}, end: {losses[-1]:.6f}")
# loss start: 1.234567, end: 0.000012
# If end loss isn't << start loss, something is wrong with your loop.
# This 'overfit one batch' test catches 80% of training-loop bugs.

External links

Exercise

참고 자료를 보지 않고 다섯 단계 학습 반복문을 기억만으로 작성해 봐. 무작위 데이터와 TinyMLP에 실행한 다음, zero_grad를 일부러 빠뜨린 버전도 만들어 100단계 동안의 손실 곡선을 비교해. 두 그래프를 나중에 참고할 수 있게 저장해 두면 시각적인 차이가 오래 기억에 남을 거야.

Progress

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

댓글 0

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

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