손실 함수(Loss Functions) — 평균제곱오차(MSE), 교차 엔트로피(Cross-Entropy), 대조 손실(Contrastive)

신경망(network)이 예측을 합니다. 정답(ground truth)은 다르다고 말합니다. 얼마나 틀렸을까요? 그 숫자가 손실(loss)입니다. 손실 함수(loss function)를 잘못 고르면 모델(model)은 완전히 엉뚱한 것을 최적화(optimize)합니다.

유형: Build

언어: Python

선수 지식: Lesson 03.04 활성화 함수(Activation Functions)

예상 시간: 약 75분

학습 목표

  • 평균제곱오차(Mean Squared Error, MSE), 이진 교차 엔트로피(binary cross-entropy), 범주형 교차 엔트로피(categorical cross-entropy), 대조 손실(contrastive loss, InfoNCE)을 기울기(gradient)와 함께 처음부터 구현합니다.
  • MSE가 분류(classification)에서 실패하는 이유를 "모든 것에 0.5를 예측하는" 실패 모드(failure mode)로 설명합니다.
  • 교차 엔트로피(cross-entropy)에 레이블 스무딩(label smoothing)을 적용하고, 이것이 과신 예측(overconfident prediction)을 막는 방식을 설명합니다.
  • 회귀(regression), 이진 분류(binary classification), 다중 클래스 분류(multi-class classification), 임베딩 학습(embedding learning) 과제에 맞는 손실 함수(loss function)를 선택합니다.

문제

분류(classification) 문제에서 MSE를 최소화(minimize)하는 모델(model)은 모든 입력(input)에 0.5를 예측할 수 있습니다. 손실(loss)은 줄이고 있습니다. 동시에 쓸모는 없습니다.

손실 함수(loss function)는 모델이 실제로 최적화(optimize)하는 유일한 것입니다. 정확도(accuracy)도 아니고, F1 점수(F1 score)도 아니고, 관리자(manager)에게 보고하는 지표(metric)도 아닙니다. 옵티마이저(optimizer)는 손실 함수의 기울기(gradient)를 사용해 그 숫자를 작게 만들도록 가중치(weight)를 조정합니다. 손실 함수가 여러분이 정말 신경 쓰는 것을 담지 못하면, 모델은 수학적으로 가장 싼 방법을 찾아 그 손실을 만족시킵니다. 그리고 그 방법은 거의 항상 우리가 원한 것이 아닙니다.

구체적인 예를 보겠습니다. 이진 분류(binary classification) 과제가 있고 두 클래스(class)가 50/50으로 나뉘어 있습니다. MSE를 손실로 사용하면 모델은 모든 입력에 0.5를 예측할 수 있습니다. 평균 MSE(average MSE)는 0.25이고, 실제로 아무것도 학습하지 않고도 가능한 최소 손실에 가까워집니다. 모델은 판별 능력(discriminative ability)이 0이지만 기술적으로는 손실 함수를 최소화한 셈입니다. 교차 엔트로피(cross-entropy)로 바꾸면 같은 모델은 예측(prediction)을 0 또는 1 쪽으로 밀어야 합니다. -log(0.5) = 0.693은 나쁜 손실이고, -log(0.99) = 0.01은 확신 있는 정답 예측(confident correct prediction)에 보상을 줍니다. 손실 함수 선택은 학습하는 모델과 지표를 속이는 모델의 차이를 만듭니다.

자기지도학습(self-supervised learning)에서는 레이블(label)조차 없습니다. 대조 손실(contrastive loss)이 학습 신호(learning signal)를 완전히 정의합니다. 무엇이 비슷한지(similar), 무엇이 다른지(different), 모델이 그것들을 얼마나 강하게 밀어내야 하는지까지 정합니다. 대조 손실을 잘못 만들면 임베딩(embedding)이 한 점으로 붕괴(collapse)됩니다. 모든 입력이 같은 벡터(vector)로 매핑됩니다. 기술적으로는 손실이 0일 수 있지만 완전히 쓸모없습니다.

사전 테스트

2문제 · 이 강의를 시작하기 전에 얼마나 알고 있는지 확인해보세요

1.신경망 학습(neural network training)에서 손실 함수(loss function)는 무엇을 나타내나요?

2.분류 과제(classification task)에서 MSE보다 교차 엔트로피(cross-entropy)가 선호되는 이유는 무엇인가요?

0/2 답변 완료

개념

평균제곱오차(Mean Squared Error, MSE)

회귀(regression)의 기본 손실입니다. 예측(prediction)과 타깃(target)의 차이를 제곱하고 모든 샘플(sample)에 대해 평균합니다.

MSE = (1/n) * sum((y_pred - y_true)^2)

제곱이 중요한 이유는 큰 오차(error)를 이차적으로(quadratically) 벌주기 때문입니다. 오차 2는 오차 1보다 4배, 오차 10은 100배의 비용(cost)을 가집니다. 그래서 MSE는 이상치(outlier)에 민감합니다. 하나의 매우 틀린 예측(prediction)이 손실을 지배할 수 있습니다.

실제 숫자로 보면 더 분명합니다. 모델이 주택 가격을 예측한다고 가정합니다. 대부분의 집에서는 10,000달러 정도 틀리지만, 어떤 대저택 하나에서 200,000달러를 틀렸다면 MSE는 그 대저택 하나를 공격적으로 고치려고 합니다. 이 과정에서 나머지 99채의 성능이 나빠질 수 있습니다.

MSE의 예측(prediction)에 대한 기울기(gradient)는 다음과 같습니다.

dMSE/dy_pred = (2/n) * (y_pred - y_true)

오차에 대해 선형(linear)입니다. 큰 오차는 큰 기울기(gradient)를 받습니다. 회귀에서는 좋은 특성입니다. 큰 오차에는 큰 수정(correction)이 필요하기 때문입니다. 하지만 분류에서는 문제입니다. 확신 있게 틀린 답(confident wrong answer)은 선형이 아니라 지수적으로(exponentially) 벌주고 싶습니다.

교차 엔트로피 손실(Cross-Entropy Loss)

분류(classification)의 손실 함수입니다. 정보 이론(information theory)에 뿌리가 있으며, 예측 확률분포(predicted probability distribution)와 실제 분포(true distribution) 사이의 발산(divergence)을 측정합니다.

이진 교차 엔트로피(Binary Cross-Entropy; BCE):

BCE = -(y * log(p) + (1 - y) * log(1 - p))

y는 실제 레이블(true label, 0 또는 1), p는 예측 확률(predicted probability)입니다. -log(p)가 왜 작동하는지 보겠습니다. 실제 레이블이 1일 때 p = 0.99를 예측하면 손실은 -log(0.99) = 0.01입니다. p = 0.01을 예측하면 손실은 -log(0.01) = 4.6입니다. 이 460배 차이가 교차 엔트로피가 분류에서 작동하는 이유입니다. 확신 있게 틀린 예측은 가혹하게 벌주고, 확신 있게 맞춘 예측은 거의 벌주지 않습니다.

기울기(gradient)도 같은 이야기를 합니다.

dBCE/dp = -(y/p) + (1-y)/(1-p)

y = 1이고 p가 0에 가까우면 기울기는 -1/p이며 음의 무한대(negative infinity)에 가까워집니다. 모델은 실수를 고치라는 매우 큰 신호(signal)를 받습니다. p가 1에 가까우면 기울기는 작습니다. 이미 맞았으니 고칠 것이 거의 없습니다.

범주형 교차 엔트로피(Categorical Cross-Entropy; CCE):

다중 클래스 분류(multi-class classification)에서 원-핫 인코딩(one-hot encoded) 타깃을 사용할 때 씁니다.

CCE = -sum(y_i * log(p_i))

실제 클래스(true class)만 손실에 기여합니다. 나머지 y_i는 모두 0이기 때문입니다. 10개 클래스에서 정답 클래스(correct class)의 확률(probability)이 0.1이면 무작위 추측(random guessing)에 가깝고 손실은 -log(0.1) = 2.3입니다. 정답 클래스 확률이 0.9라면 손실은 -log(0.9) = 0.105입니다. 모델은 올바른 답에 확률 질량(probability mass)을 집중하는 방향으로 학습합니다.

분류에서 MSE가 실패하는 이유

graph TD
    subgraph "분류에서의 MSE"
        P1["class 1에 대해 0.5 예측<br/>MSE = 0.25"]
        P2["class 1에 대해 0.9 예측<br/>MSE = 0.01"]
        P3["class 1에 대해 0.1 예측<br/>MSE = 0.81"]
    end
    subgraph "분류에서의 교차 엔트로피"
        C1["class 1에 대해 0.5 예측<br/>CE = 0.693"]
        C2["class 1에 대해 0.9 예측<br/>CE = 0.105"]
        C3["class 1에 대해 0.1 예측<br/>CE = 2.303"]
    end
    P3 -->|"MSE 기울기는<br/>포화 근처에서 평평"| Slow["느린 수정"]
    C3 -->|"CE 기울기는<br/>틀린 답 근처에서 큼"| Fast["빠른 수정"]

MSE 기울기는 시그모이드(sigmoid) 포화(saturation) 때문에 예측이 0이나 1에 가까울 때 평평해집니다(flatten). 교차 엔트로피 기울기는 이를 보완합니다. -log가 시그모이드의 평평한 구간(flat region)을 상쇄해, 기울기가 가장 필요한 곳에서 강한 기울기를 제공합니다.

레이블 스무딩(Label Smoothing)

표준 원-핫 레이블(standard one-hot label)은 "이것은 100% 클래스 3이고 나머지는 0%"라고 말합니다. 강한 주장입니다. 레이블 스무딩(label smoothing)은 이를 부드럽게 합니다.

smooth_label = (1 - alpha) * one_hot + alpha / num_classes

alpha = 0.1, 클래스 10개라면 [0, 0, 1, 0, ...] 대신 [0.01, 0.01, 0.91, 0.01, ...]가 됩니다. 모델은 1.0이 아니라 0.91을 타깃(target)으로 삼습니다.

소프트맥스(softmax)로 정확히 1.0을 출력하려면 로짓(logit)을 무한대로 밀어야 합니다. 이는 과신(overconfidence)을 만들고 일반화(generalization)를 해치며 분포 변화(distribution shift)에 취약하게 만듭니다. 레이블 스무딩은 타깃을 0.9 근처로 제한해 로짓을 합리적인 범위에 둡니다. GPT와 대부분의 현대 모델(modern model)은 레이블 스무딩 또는 그에 준하는 방식을 사용합니다.

대조 손실(Contrastive Loss)

레이블(label)도 클래스(class)도 없습니다. 입력 쌍(input pair)과 질문만 있습니다. 이 둘은 비슷한가요(similar), 다른가요(different)?

SimCLR 스타일 대조 손실(SimCLR-style contrastive loss)인 NT-Xent / InfoNCE는 하나의 이미지(image)에서 두 개의 증강된 뷰(augmented view)를 만듭니다. 예를 들면 자르기(crop), 회전(rotate), 색상 변형(color jitter)을 적용합니다. 이 두 뷰는 양성 쌍(positive pair)입니다. 비슷한 임베딩을 가져야 합니다. 배치(batch)의 다른 모든 이미지는 음성 쌍(negative pair)입니다. 서로 다른 임베딩을 가져야 합니다.

L = -log(exp(sim(z_i, z_j) / tau) / sum(exp(sim(z_i, z_k) / tau)))

sim()은 코사인 유사도(cosine similarity), z_iz_j는 양성 쌍(positive pair), 합(sum)은 모든 음성(negative)에 대한 합입니다. tau는 온도(temperature)이며 분포의 날카로움(sharpness)을 조절합니다. 낮은 온도는 더 어려운 음성(harder negative)과 더 공격적인 분리(aggressive separation)를 의미합니다.

실제 숫자로 보면, 배치 크기(batch size)가 256이면 양성 쌍 하나당 255개의 음성이 있습니다. 온도 tau = 0.07은 SimCLR의 기본값입니다. 이 손실은 유사도(similarity)에 대한 소프트맥스(softmax)처럼 보입니다. 256개 선택지 중 양성 쌍의 유사도가 가장 높아지기를 원합니다.

트리플릿 손실(Triplet Loss)은 앵커(anchor), 양성(positive, 같은 클래스), 음성(negative, 다른 클래스) 세 입력을 받습니다.

L = max(0, d(anchor, positive) - d(anchor, negative) + margin)

마진(margin)은 보통 0.2-1.0이며, 양성과 음성 거리 사이의 최소 간격을 강제합니다. 음성이 이미 충분히 멀리 있으면 손실은 0이고 기울기도 없습니다. 업데이트도 없습니다. 그래서 학습은 효율적이지만, 앵커에 가까운 어려운 음성(hard negative)을 고르는 트리플릿 마이닝(triplet mining)이 중요합니다.

초점 손실(Focal Loss)

불균형 데이터셋(imbalanced dataset)에서 사용합니다. 표준 교차 엔트로피(standard cross-entropy)는 쉽게 맞춘 예제(easy example)도 똑같이 다룹니다. 초점 손실(focal loss)은 쉬운 예제의 가중치(weight)를 낮춥니다.

FL = -alpha * (1 - p_t)^gamma * log(p_t)

p_t는 실제 클래스(true class)의 예측 확률(predicted probability)이고 gamma는 초점(focusing)을 조절합니다. gamma = 0이면 표준 교차 엔트로피입니다. 기본값으로 자주 쓰이는 gamma = 2일 때:

  • 쉬운 예제(easy example, p_t = 0.9): 가중치 = (0.1)^2 = 0.01입니다. 사실상 무시됩니다.
  • 어려운 예제(hard example, p_t = 0.1): 가중치 = (0.9)^2 = 0.81입니다. 충분한 기울기 신호를 받습니다.

초점 손실(focal loss)은 Lin 등이 객체 탐지(object detection)를 위해 제안했습니다. 객체 탐지에서는 후보 영역(candidate region)의 99%가 배경(background), 즉 쉬운 음성(easy negative)입니다. 초점 손실이 없으면 모델은 쉬운 배경 예제에 파묻혀 객체 탐지를 배우지 못합니다. 초점 손실을 쓰면 모델 용량(capacity)을 중요하고 모호한 어려운 사례(hard, ambiguous case)에 집중시킬 수 있습니다.

손실 함수 결정 트리(Loss Function Decision Tree)

flowchart TD
    Start["과제가 무엇인가요?"] --> Reg{"회귀(Regression)?"}
    Start --> Cls{"분류(Classification)?"}
    Start --> Emb{"임베딩 학습(Embedding learning)?"}

    Reg -->|"예"| Outliers{"이상치에 민감?"}
    Outliers -->|"예, 이상치를 벌줌"| MSE["MSE 사용"]
    Outliers -->|"아니오, 이상치에 강건"| MAE["MAE / Huber 사용"]

    Cls -->|"이진"| BCE["Binary CE 사용"]
    Cls -->|"다중 클래스"| CCE["Categorical CE 사용"]
    Cls -->|"불균형"| FL["Focal Loss 사용"]
    CCE -->|"과신?"| LS["Label Smoothing 추가"]

    Emb -->|"쌍 데이터"| CL["Contrastive Loss 사용"]
    Emb -->|"트리플릿 사용 가능"| TL["Triplet Loss 사용"]
    Emb -->|"대형 배치 자기지도"| NCE["InfoNCE 사용"]

손실 지형(Loss Landscape)

graph LR
    subgraph "손실 표면 형태"
        MSE_S["MSE<br/>부드러운 포물선<br/>단일 최솟값<br/>최적화가 쉬움"]
        CE_S["Cross-Entropy<br/>틀린 답 근처에서 가파름<br/>맞는 답 근처에서 평평함<br/>필요한 곳에서 강한 기울기"]
        CL_S["Contrastive<br/>많은 국소 최솟값<br/>배치 구성에 의존<br/>온도가 날카로움 제어"]
    end
    MSE_S -->|"가장 적합"| Reg2["회귀"]
    CE_S -->|"가장 적합"| Cls2["분류"]
    CL_S -->|"가장 적합"| Emb2["표현 학습"]

직접 만들기

단계 1: MSE와 기울기(gradient)

def mse(predictions, targets):
    n = len(predictions)
    total = 0.0
    for p, t in zip(predictions, targets):
        total += (p - t) ** 2
    return total / n

def mse_gradient(predictions, targets):
    n = len(predictions)
    grads = []
    for p, t in zip(predictions, targets):
        grads.append(2.0 * (p - t) / n)
    return grads

단계 2: 이진 교차 엔트로피(Binary Cross-Entropy)

log(0) 문제는 실제로 생깁니다. 모델이 양성 예제(positive example)에 정확히 0을 예측하면 log(0)은 음의 무한대(negative infinity)입니다. 클리핑(clipping)으로 막습니다.

def binary_cross_entropy(predictions, targets, eps=1e-15):
    n = len(predictions)
    total = 0.0
    for p, t in zip(predictions, targets):
        p_clipped = max(eps, min(1 - eps, p))
        total += -(t * math.log(p_clipped) + (1 - t) * math.log(1 - p_clipped))
    return total / n

def bce_gradient(predictions, targets, eps=1e-15):
    grads = []
    for p, t in zip(predictions, targets):
        p_clipped = max(eps, min(1 - eps, p))
        grads.append(-(t / p_clipped) + (1 - t) / (1 - p_clipped))
    return grads

단계 3: 소프트맥스(softmax)를 포함한 범주형 교차 엔트로피(Categorical Cross-Entropy)

소프트맥스는 원시 로짓(raw logits)을 확률(probability)로 바꿉니다. 그다음 원-핫 타깃(one-hot target)에 대해 교차 엔트로피를 계산합니다.

def softmax(logits):
    max_val = max(logits)
    exps = [math.exp(x - max_val) for x in logits]
    total = sum(exps)
    return [e / total for e in exps]

def categorical_cross_entropy(logits, target_index, eps=1e-15):
    probs = softmax(logits)
    p = max(eps, probs[target_index])
    return -math.log(p)

def cce_gradient(logits, target_index):
    probs = softmax(logits)
    grads = list(probs)
    grads[target_index] -= 1.0
    return grads

소프트맥스 + 교차 엔트로피의 기울기는 아름답게 단순화됩니다. 참(true) 클래스는 (예측 확률 - 1), 나머지는 (예측 확률)입니다. 이 조합이 함께 쓰이는 이유입니다.

단계 4: 레이블 스무딩(Label Smoothing)

def label_smoothed_cce(logits, target_index, num_classes, alpha=0.1, eps=1e-15):
    probs = softmax(logits)
    loss = 0.0
    for i in range(num_classes):
        if i == target_index:
            smooth_target = 1.0 - alpha + alpha / num_classes
        else:
            smooth_target = alpha / num_classes
        p = max(eps, probs[i])
        loss += -smooth_target * math.log(p)
    return loss

단계 5: 대조 손실(Contrastive Loss, 간단한 InfoNCE)

def cosine_similarity(a, b):
    dot = sum(x * y for x, y in zip(a, b))
    norm_a = math.sqrt(sum(x * x for x in a))
    norm_b = math.sqrt(sum(x * x for x in b))
    if norm_a < 1e-10 or norm_b < 1e-10:
        return 0.0
    return dot / (norm_a * norm_b)

def contrastive_loss(anchor, positive, negatives, temperature=0.07):
    sim_pos = cosine_similarity(anchor, positive) / temperature
    sim_negs = [cosine_similarity(anchor, neg) / temperature for neg in negatives]
    max_sim = max(sim_pos, max(sim_negs)) if sim_negs else sim_pos
    exp_pos = math.exp(sim_pos - max_sim)
    exp_negs = [math.exp(s - max_sim) for s in sim_negs]
    total_exp = exp_pos + sum(exp_negs)
    return -math.log(max(1e-15, exp_pos / total_exp))

단계 6: 분류에서 MSE와 교차 엔트로피 비교

Lesson 04의 원형 데이터셋(circle dataset) 신경망을 같은 구조로 학습하되, 손실만 MSE와 BCE로 바꿔 비교합니다. 교차 엔트로피가 분류에서 더 빨리 수렴하는 이유를 손실 곡선(loss curve)으로 확인합니다.

import random

def sigmoid(x):
    x = max(-500, min(500, x))
    return 1.0 / (1.0 + math.exp(-x))

def make_circle_data(n=200, seed=42):
    random.seed(seed)
    data = []
    for _ in range(n):
        x = random.uniform(-2, 2)
        y = random.uniform(-2, 2)
        label = 1.0 if x * x + y * y < 1.5 else 0.0
        data.append(([x, y], label))
    return data


class LossComparisonNetwork:
    def __init__(self, loss_type="bce", hidden_size=8, lr=0.1):
        random.seed(0)
        self.loss_type = loss_type
        self.lr = lr
        self.hidden_size = hidden_size

        self.w1 = [[random.gauss(0, 0.5) for _ in range(2)] for _ in range(hidden_size)]
        self.b1 = [0.0] * hidden_size
        self.w2 = [random.gauss(0, 0.5) for _ in range(hidden_size)]
        self.b2 = 0.0

    def forward(self, x):
        self.x = x
        self.z1 = []
        self.h = []
        for i in range(self.hidden_size):
            z = self.w1[i][0] * x[0] + self.w1[i][1] * x[1] + self.b1[i]
            self.z1.append(z)
            self.h.append(max(0.0, z))

        self.z2 = sum(self.w2[i] * self.h[i] for i in range(self.hidden_size)) + self.b2
        self.out = sigmoid(self.z2)
        return self.out

    def backward(self, target):
        if self.loss_type == "mse":
            d_loss = 2.0 * (self.out - target)
        else:
            eps = 1e-15
            p = max(eps, min(1 - eps, self.out))
            d_loss = -(target / p) + (1 - target) / (1 - p)

        d_sigmoid = self.out * (1 - self.out)
        d_out = d_loss * d_sigmoid

        for i in range(self.hidden_size):
            d_relu = 1.0 if self.z1[i] > 0 else 0.0
            d_h = d_out * self.w2[i] * d_relu
            self.w2[i] -= self.lr * d_out * self.h[i]
            for j in range(2):
                self.w1[i][j] -= self.lr * d_h * self.x[j]
            self.b1[i] -= self.lr * d_h
        self.b2 -= self.lr * d_out

    def compute_loss(self, pred, target):
        if self.loss_type == "mse":
            return (pred - target) ** 2
        else:
            eps = 1e-15
            p = max(eps, min(1 - eps, pred))
            return -(target * math.log(p) + (1 - target) * math.log(1 - p))

    def train(self, data, epochs=200):
        losses = []
        for epoch in range(epochs):
            total_loss = 0.0
            correct = 0
            for x, y in data:
                pred = self.forward(x)
                self.backward(y)
                total_loss += self.compute_loss(pred, y)
                if (pred >= 0.5) == (y >= 0.5):
                    correct += 1
            avg_loss = total_loss / len(data)
            accuracy = correct / len(data) * 100
            losses.append((avg_loss, accuracy))
            if epoch % 50 == 0 or epoch == epochs - 1:
                print(f"    Epoch {epoch:3d}: 손실={avg_loss:.4f}, 정확도={accuracy:.1f}%")
        return losses

사용해보기

PyTorch는 수치 안정성(numerical stability)이 내장된 표준 손실 함수(standard loss function)를 제공합니다.

import torch
import torch.nn.functional as F

predictions = torch.tensor([0.9, 0.1, 0.7], requires_grad=True)
targets = torch.tensor([1.0, 0.0, 1.0])

mse_loss = F.mse_loss(predictions, targets)
bce_loss = F.binary_cross_entropy(predictions, targets)

logits = torch.randn(4, 10)
labels = torch.tensor([3, 7, 1, 9])
ce_loss = F.cross_entropy(logits, labels)
ce_smooth = F.cross_entropy(logits, labels, label_smoothing=0.1)

F.cross_entropy를 사용합니다. 수동(manual) 소프트맥스 뒤에 로그(log)를 취하는 것보다 log-softmax와 음의 로그 가능도(negative log-likelihood)를 결합한 수치적으로 안정적인 구현입니다. 대조 학습(contrastive learning)은 사용자 정의 구현(custom implementation)이나 lightly, pytorch-metric-learning 같은 라이브러리(library)를 사용하는 경우가 많지만 핵심 루프(core loop)는 같습니다. 유사도(similarity)를 계산하고, 양성(positive)과 음성(negative)에 대한 소프트맥스를 만들고, 역전파(backpropagate)합니다.

산출물 만들기

이 lesson의 산출물은 다음입니다.

  • outputs/prompt-loss-function-selector.md: 과제(task)에 맞는 손실 함수(loss function)를 선택하는 재사용 프롬프트(prompt)
  • outputs/prompt-loss-debugger.md: 손실 곡선(loss curve)이 이상할 때 진단하는 프롬프트

연습문제

  1. (쉬움) 작은 오차(small error)에는 MSE, 큰 오차(large error)에는 MAE처럼 동작하는 후버 손실(Huber loss, smooth L1 loss)을 구현합니다. y = sin(x) 회귀(regression)에서 이상치(outlier)가 있을 때 MSE와 후버 손실을 비교합니다.
  2. (중간) 이진 분류(binary classification) 학습 루프에 초점 손실(focal loss)을 추가합니다. 90% class 0, 10% class 1의 불균형 데이터셋(imbalanced dataset)을 만들고 BCE와 초점 손실을 소수 클래스 재현율(minority class recall) 기준으로 비교합니다.
  3. (어려움) 준-어려운 음성 마이닝(semi-hard negative mining)을 사용하는 트리플릿 손실(triplet loss)을 구현합니다. 5개 클래스의 2차원 임베딩 데이터(2D embedding data)를 생성하고 무작위 트리플릿 선택(random triplet selection)과 수렴(convergence)을 비교합니다.
  4. (중간) MSE와 교차 엔트로피 비교 실험에서 층별(layer-wise) 기울기 크기(gradient magnitude)를 추적합니다. 초기 에폭(early epoch)에서 교차 엔트로피가 더 큰 기울기를 만드는지 확인합니다.
  5. (어려움) KL 발산 손실(KL divergence loss)을 구현하고 원-핫 참 분포(one-hot true distribution)에서 KL(true || predicted)를 최소화(minimize)할 때 교차 엔트로피와 같은 기울기가 나오는지 확인합니다. 이어서 교사 모델(teacher model)의 소프트맥스 출력(softmax output)을 타깃으로 하는 소프트 타깃(soft target)을 시험합니다.

핵심 용어

용어흔한 설명실제 의미
손실 함수(Loss function)"모델이 얼마나 틀렸는지"예측과 타깃을 옵티마이저(optimizer)가 최소화할 스칼라(scalar)로 매핑하는 미분 가능한 함수
평균제곱오차(MSE)"평균 제곱 오차"예측과 타깃 차이의 제곱 평균. 큰 오차를 이차적(quadratic)으로 벌줌
교차 엔트로피(Cross-entropy)"분류 손실"-log(p)로 예측 확률분포와 참(true) 분포의 발산(divergence)을 측정
이진 교차 엔트로피(Binary cross-entropy)"BCE"두 클래스용 교차 엔트로피: -(y*log(p) + (1-y)*log(1-p))
레이블 스무딩(Label smoothing)"타깃을 부드럽게 함"딱딱한 0/1 타깃을 0.1/0.9 같은 부드러운 값으로 바꿔 과신(overconfidence)을 줄이는 기법
대조 손실(Contrastive loss)"당겨 모으고 밀어내기"비슷한 쌍은 가깝게, 다른 쌍은 멀게 하며 표현(representation)을 학습하는 손실
InfoNCE"CLIP/SimCLR 손실"유사도 점수에 대한 온도 조정 교차 엔트로피(temperature-scaled cross-entropy)
초점 손실(Focal loss)"불균형 데이터 해결책"쉬운 예제의 가중치를 낮추고 어려운 예제에 집중하는 교차 엔트로피 변형
트리플릿 손실(Triplet loss)"앵커-양성-음성"앵커(anchor)가 음성(negative)보다 양성(positive)에 마진(margin) 이상 더 가깝도록 임베딩을 학습하는 손실
온도(Temperature)"날카로움 조절 손잡이"로짓이나 유사도를 나누는 스칼라. 낮을수록 분포가 날카로워짐

더 읽을거리

실습 코드

이 강의의 실습 코드 1개

main
Code

산출물

이 강의에서 생성된 프롬프트, 스킬, 코드 산출물 2개

prompt-loss-debugger

A diagnostic prompt for debugging loss curves and training failures

Prompt
prompt-loss-function-selector

A decision prompt for choosing the right loss function for any ML task

Prompt

확인 문제

3문제 · 모두 맞추면 완료 표시가 가능합니다

1.이진 분류(binary classification)에 MSE 손실(MSE loss)을 사용하면 어떤 일이 생길 수 있나요?

2.레이블 스무딩(label smoothing)은 무엇을 하며 왜 유용한가요?

3.대조 손실(contrastive loss, InfoNCE)에서 온도 파라미터(temperature parameter)의 역할은 무엇인가요?

0/3 답변 완료