🤖 AI/ML

손실 함수

Loss Function

모델 예측과 실제 값의 차이를 측정하는 함수. MSE, Cross-Entropy 등. 학습의 최적화 대상.

📖 상세 설명

손실 함수(Loss Function)는 모델의 예측값과 실제 정답 간의 차이를 수치화하는 함수입니다. 이 값이 작을수록 모델이 정답에 가깝게 예측하고 있다는 의미입니다. 머신러닝의 학습 과정은 결국 이 손실 함수를 최소화하는 파라미터를 찾는 최적화 문제입니다.

손실 함수는 문제 유형에 따라 다르게 선택합니다. 회귀 문제에서는 MSE(Mean Squared Error), MAE(Mean Absolute Error), Huber Loss 등을 사용합니다. 분류 문제에서는 Cross-Entropy Loss가 표준이며, 이진 분류에는 Binary Cross-Entropy, 다중 분류에는 Categorical Cross-Entropy를 사용합니다.

손실 함수의 특성이 학습에 큰 영향을 미칩니다. MSE는 큰 오차에 더 큰 페널티를 주어 이상치에 민감합니다. MAE는 모든 오차에 동일한 가중치를 주어 이상치에 강건합니다. Cross-Entropy는 확률 분포 간의 차이를 측정하며, 확률이 0에 가까운 잘못된 예측에 큰 페널티를 줍니다.

고급 손실 함수도 많이 활용됩니다. Focal Loss는 쉬운 샘플의 손실을 줄여 어려운 샘플에 집중합니다. Contrastive Loss와 Triplet Loss는 임베딩 학습에 사용됩니다. Dice Loss는 세그멘테이션에서 클래스 불균형 문제를 해결합니다. 실무에서는 여러 손실 함수를 가중합하여 사용하기도 합니다.

코드 예제

PyTorch에서 다양한 손실 함수 사용 및 커스텀 구현 예제입니다.

import torch
import torch.nn as nn
import torch.nn.functional as F

# ===== 회귀 손실 함수 =====
mse_loss = nn.MSELoss()
mae_loss = nn.L1Loss()
huber_loss = nn.HuberLoss(delta=1.0)

pred = torch.tensor([2.5, 0.0, 2.1, 7.8])
target = torch.tensor([3.0, -0.5, 2.0, 7.5])

print(f"MSE Loss: {mse_loss(pred, target):.4f}")  # 0.1275
print(f"MAE Loss: {mae_loss(pred, target):.4f}")  # 0.3250

# ===== 분류 손실 함수 =====
ce_loss = nn.CrossEntropyLoss()
bce_loss = nn.BCEWithLogitsLoss()

# 다중 분류: logits (B, C) vs labels (B,)
logits = torch.tensor([[2.0, 1.0, 0.1], [0.5, 2.5, 0.3]])
labels = torch.tensor([0, 1])
print(f"CrossEntropy: {ce_loss(logits, labels):.4f}")

# 이진 분류: logits (B,) vs labels (B,)
logits_binary = torch.tensor([0.9, -0.5, 0.3])
labels_binary = torch.tensor([1.0, 0.0, 1.0])
print(f"BCE: {bce_loss(logits_binary, labels_binary):.4f}")

# ===== Focal Loss 구현 =====
class FocalLoss(nn.Module):
    def __init__(self, alpha=1, gamma=2):
        super().__init__()
        self.alpha = alpha
        self.gamma = gamma

    def forward(self, inputs, targets):
        ce_loss = F.cross_entropy(inputs, targets, reduction='none')
        pt = torch.exp(-ce_loss)  # 정답 확률
        focal_loss = self.alpha * (1 - pt) ** self.gamma * ce_loss
        return focal_loss.mean()

# ===== Label Smoothing =====
ce_smooth = nn.CrossEntropyLoss(label_smoothing=0.1)

# ===== 가중 손실 함수 조합 =====
class CombinedLoss(nn.Module):
    def __init__(self, alpha=0.5):
        super().__init__()
        self.alpha = alpha
        self.ce = nn.CrossEntropyLoss()
        self.dice = DiceLoss()  # 커스텀 구현 필요

    def forward(self, pred, target):
        return self.alpha * self.ce(pred, target) + (1-self.alpha) * self.dice(pred, target)

성능 & 비용

손실 함수 적용 분야 장점 주의사항
MSE (L2) 회귀 수학적으로 다루기 쉬움 이상치에 민감
MAE (L1) 회귀 이상치에 강건 0에서 미분 불가
Cross-Entropy 분류 확률 해석 가능 클래스 불균형 취약
Focal Loss 객체 탐지 불균형 데이터에 효과적 gamma 튜닝 필요
Dice Loss 세그멘테이션 IoU 직접 최적화 배치 크기에 민감

🗣️ 실무에서 이렇게 말하세요

"클래스 불균형이 심해서 Focal Loss로 바꿨더니 Minority Class의 Recall이 20% 올랐어요. gamma=2로 설정했습니다."

영어로는 "Switching to Focal Loss improved minority class recall by 20%"라고 표현합니다. "loss landscape", "loss curve", "training loss vs validation loss" 등의 용어도 자주 사용됩니다. 학습 과정에서는 "loss가 떨어지고 있다/정체됐다/발산했다"라고 표현합니다.

⚠️ 흔한 실수 & 주의사항

  • 1. NaN 발생: log(0)이나 division by zero가 발생하면 NaN이 됩니다. 작은 epsilon을 더하거나 clamp를 사용하세요.
  • 2. reduction 모드 혼동: 'mean', 'sum', 'none' 중 어떤 것을 쓰느냐에 따라 learning rate 스케일이 달라집니다.
  • 3. Softmax 중복: CrossEntropyLoss는 내부에 log_softmax가 포함됩니다. 입력에 softmax를 또 적용하면 안 됩니다.
  • 4. 손실 함수와 평가 지표 불일치: Cross-Entropy로 학습하고 F1-Score로 평가하면 최적점이 다를 수 있습니다.
  • 5. 가중치 스케일: 여러 손실을 조합할 때 스케일이 다르면 한쪽에 치우칩니다. 정규화하거나 동적 가중치를 사용하세요.

🔗 관련 용어

📚 더 배우기