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

손실 함수와 입력 계약

~12 min · loss, cross_entropy, mse, binary

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

작업에 맞는 손실을 고르고 입력 계약을 읽어

'모델이 학습되지 않는다'는 문제의 상당수는 손실 함수와 모델 출력의 계약이 맞지 않아서 생겨. 원인을 찾고 나면 보통 한 줄만 바꿔 해결할 수 있어.

분류

  • nn.CrossEntropyLoss: 다중 클래스 분류에 써. 모델은 (N, C) 모양의 가공하지 않은 로짓을 내고, 정답은 (N,) 모양의 int64 클래스 인덱스여야 해. 내부에서 수치적으로 안정적인 log_softmax와 NLL을 결합하므로 앞에서 소프트맥스를 적용하지 마.
  • nn.BCEWithLogitsLoss: 이진 분류나 다중 레이블 분류에 써. 모델은 가공하지 않은 로짓을 내고, 정답은 {0, 1}의 float 값이어야 해. 수치 안정성을 위해 시그모이드와 BCE를 결합하므로 앞에서 시그모이드를 적용하지 마.
  • nn.NLLLoss: 다중 클래스 분류용이지만 로짓이 아니라 로그 확률을 받아. log_softmax를 이미 적용한 경우에만 사용해.

회귀

  • nn.MSELoss: 평균 제곱 오차로, 회귀의 기본 선택이야. 오차를 제곱하므로 이상치에 큰 벌점을 줘.
  • nn.L1Loss: 평균 절댓값 오차야. 이상치에 더 강건해.
  • nn.SmoothL1Loss / nn.HuberLoss: 0 근처에서는 L2처럼, 꼬리에서는 L1처럼 작동해. 잡음이 많은 회귀에서 두 방식의 장점을 함께 얻을 수 있어.

덜 흔하지만 유용한 손실

  • nn.KLDivLoss: 두 분포 사이의 KL 발산을 계산해. 지식 증류에 사용해.
  • nn.CosineEmbeddingLoss: 얼굴 검증이나 임베딩 유사도처럼 유사성에 기반한 학습에 사용해.
  • nn.TripletMarginLoss: 기준·양성·음성 삼중항을 사용하는 메트릭 학습에 써.

Code

다중 클래스 분류: CrossEntropyLoss·python
import torch
import torch.nn as nn

# Model outputs raw logits, NOT softmax probabilities
model = nn.Linear(10, 5)               # 5 classes
criterion = nn.CrossEntropyLoss()

x = torch.randn(16, 10)
targets = torch.randint(0, 5, (16,))   # int64 class indices

logits = model(x)
loss = criterion(logits, targets)
print(loss.item())                      # scalar
이진 / 다중 레이블: BCEWithLogitsLoss·python
import torch
import torch.nn as nn

# Binary classifier — single logit per sample
model_bin = nn.Linear(10, 1)
criterion = nn.BCEWithLogitsLoss()

x = torch.randn(16, 10)
y_bin = torch.randint(0, 2, (16, 1)).float()   # MUST be float, not int
loss = criterion(model_bin(x), y_bin)

# Multi-label — N binary outputs per sample
model_ml = nn.Linear(10, 5)             # 5 independent binary labels
y_ml = torch.randint(0, 2, (16, 5)).float()
loss_ml = criterion(model_ml(x), y_ml)
print(loss_ml.item())
회귀: 이상치 행동으로 고르기·python
import torch
import torch.nn as nn

x = torch.randn(16, 10)
y = torch.randn(16, 2)
model = nn.Linear(10, 2)

mse = nn.MSELoss()                      # default; squared, sensitive to outliers
l1  = nn.L1Loss()                       # robust, less sharp gradient near zero
huber = nn.SmoothL1Loss(beta=1.0)       # L2 near zero, L1 in tails

for name, fn in [('MSE', mse), ('L1', l1), ('Huber', huber)]:
    print(f"{name}: {fn(model(x), y).item():.4f}")
class_weight: 불균형 클래스 처리·python
import torch
import torch.nn as nn

# Suppose class 0 is 9x more common than class 1
# Heavier weight on the rare class so the loss cares more about it
weights = torch.tensor([1.0, 9.0])      # one weight per class
criterion = nn.CrossEntropyLoss(weight=weights)

logits = torch.randn(16, 2)
targets = torch.cat([torch.zeros(14, dtype=torch.long), torch.ones(2, dtype=torch.long)])
loss = criterion(logits, targets)
print(loss.item())

External links

Exercise

출력 모양이 (B, 5)인 분류기를 만들어 봐. 같은 입력과 정답에 소프트맥스 뒤 NLLLoss를 적용한 경우와 가공하지 않은 로짓에 CrossEntropyLoss를 적용한 경우를 비교해. 두 손실 값이 같은지 확인한 다음, 소프트맥스 뒤에 CrossEntropyLoss까지 적용하면 소프트맥스가 두 번 들어가 잘못된 값이 나오는지도 확인해.

Progress

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

댓글 0

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

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