← Назад к вопросам

Какие функции потерь используются для классификации?

2.0 Middle🔥 221 комментариев
#Машинное обучение#Метрики и оценка моделей

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Функции потерь для классификации

Функция потерь (Loss Function) — это математическая функция, которая измеряет расстояние между предсказаниями модели и истинными значениями. Целью обучения является минимизация функции потерь. Выбор правильной функции потерь критичен для успеха модели.

1. Binary Cross-Entropy (Логарифмическая потеря)

Используется для бинарной классификации (два класса).

Формула

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

Где:

  • y — истинный класс (0 или 1)
  • p — предсказанная вероятность класса 1

Интуиция

  • Если y = 1 и p близко к 1: потеря низкая
  • Если y = 1 и p близко к 0: потеря очень высокая
  • Функция штрафует уверенные неправильные предсказания

Реализация

import numpy as np
from sklearn.metrics import log_loss
from keras.losses import BinaryCrossentropy
import torch.nn.functional as F

# Истинные значения и предсказания
y_true = np.array([0, 1, 1, 0, 1])
y_pred_proba = np.array([0.1, 0.9, 0.8, 0.3, 0.7])

# Scikit-learn
bce_sklearn = log_loss(y_true, y_pred_proba)
print(f'BCE (sklearn): {bce_sklearn:.4f}')

# Keras/TensorFlow
bce_keras = BinaryCrossentropy()(y_true, y_pred_proba).numpy()
print(f'BCE (Keras): {bce_keras:.4f}')

# NumPy (вручную)
bce_manual = -np.mean(y_true * np.log(y_pred_proba) + 
                      (1 - y_true) * np.log(1 - y_pred_proba))
print(f'BCE (manual): {bce_manual:.4f}')

2. Categorical Cross-Entropy

Для мультиклассовой классификации (3 и более классов).

Формула

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

Где:

  • y_i — one-hot кодирование истинного класса
  • p_i — предсказанная вероятность класса i

Реализация

from sklearn.metrics import log_loss
from keras.losses import CategoricalCrossentropy

# Пример: 3 класса
y_true = np.array([
    [1, 0, 0],  # класс 0
    [0, 1, 0],  # класс 1
    [0, 0, 1],  # класс 2
])

y_pred = np.array([
    [0.9, 0.05, 0.05],
    [0.1, 0.8, 0.1],
    [0.2, 0.3, 0.5],
])

# Keras
cce = CategoricalCrossentropy()(y_true, y_pred).numpy()
print(f'CCE: {cce:.4f}')

# NumPy (вручную)
cce_manual = -np.mean(np.sum(y_true * np.log(y_pred), axis=1))
print(f'CCE (manual): {cce_manual:.4f}')

3. Sparse Categorical Cross-Entropy

То же, что Categorical, но на входе целочисленные метки вместо one-hot.

from keras.losses import SparseCategoricalCrossentropy

# Входные данные: целые числа вместо one-hot
y_true = np.array([0, 1, 2])  # Не [1, 0, 0], [0, 1, 0], [0, 0, 1]
y_pred = np.array([
    [0.9, 0.05, 0.05],
    [0.1, 0.8, 0.1],
    [0.2, 0.3, 0.5],
])

scce = SparseCategoricalCrossentropy()(y_true, y_pred).numpy()
print(f'Sparse CCE: {scce:.4f}')

4. Hinge Loss (SVM Loss)

Используется в Support Vector Machines для мягких марж.

Формула

L = max(0, 1 - y * y_pred)

Где:

  • y — метка (-1 или 1)
  • y_pred — предсказание модели

Интуиция

  • Штрафует предсказания, которые находятся на неправильной стороне с низким запасом (margin)
  • Игнорирует примеры, которые правильно классифицированы с большим запасом
import numpy as np

# Истинные метки (-1 или 1)
y_true = np.array([-1, 1, 1, -1])
y_pred = np.array([-2.5, 0.5, 2.0, -0.1])

# Hinge loss
hinge_loss = np.mean(np.maximum(0, 1 - y_true * y_pred))
print(f'Hinge Loss: {hinge_loss:.4f}')

# Мощная реализация в sklearn
from sklearn.svm import LinearSVC
from sklearn.metrics import hinge_loss as sk_hinge_loss

y_true_binary = np.array([0, 1, 1, 0])
y_pred_scores = np.array([-2.5, 0.5, 2.0, -0.1])
y_true_signed = 2 * y_true_binary - 1  # Преобразовать в -1/1

hinge = sk_hinge_loss(y_true_signed, y_pred_scores)
print(f'Hinge Loss (sklearn): {hinge:.4f}')

5. Focal Loss

Для работы с несбалансированными данными. Штрафует легкие примеры меньше.

Формула

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

Где:

  • p_t — предсказанная вероятность правильного класса
  • gamma — параметр концентрации (обычно 2)
  • alpha — вес редкого класса

Реализация

import tensorflow as tf
from tensorflow.keras.losses import BinaryFocalCrossentropy

# Бинарный Focal Loss
y_true = np.array([0, 1, 1, 0, 1])
y_pred = np.array([0.1, 0.9, 0.7, 0.3, 0.6])

focal_loss = BinaryFocalCrossentropy(gamma=2.0, alpha=0.25)
loss = focal_loss(y_true, y_pred).numpy()
print(f'Focal Loss: {loss:.4f}')

# Реализация вручную для понимания
def focal_loss_numpy(y_true, y_pred, gamma=2, alpha=0.25):
    y_pred = np.clip(y_pred, 1e-7, 1 - 1e-7)
    loss = -(alpha * y_true * (1 - y_pred)**gamma * np.log(y_pred) +
             (1 - alpha) * (1 - y_true) * y_pred**gamma * np.log(1 - y_pred))
    return np.mean(loss)

print(f'Focal Loss (manual): {focal_loss_numpy(y_true, y_pred):.4f}')

6. Kullback-Leibler Divergence (KL Divergence)

Для дистилляции моделей и работы с вероятностными распределениями.

Формула

KL = sum(y_i * log(y_i / p_i))

Где:

  • y_i — истинное распределение вероятностей
  • p_i — предсказанное распределение
from keras.losses import KLDivergence
import tensorflow as tf

y_true = np.array([[0.8, 0.2], [0.1, 0.9]])
y_pred = np.array([[0.7, 0.3], [0.15, 0.85]])

kl_loss = KLDivergence()(y_true, y_pred).numpy()
print(f'KL Divergence: {kl_loss:.4f}')

Сравнение функций потерь

LossТип задачиФормулаКогда использовать
Binary CEБинарная-(y log p + (1-y) log(1-p))Базовая бинарная классификация
Categorical CEМультикласс-sum(y_i log p_i)Обычная мультиклассовая
Focal LossНесбалансированные-alpha(1-p)^gamma log pДисбалансированные данные (0.1% vs 99.9%)
Hinge LossSVM-стильmax(0, 1 - y * y_pred)Максимальный margin, мягкое разделение
KL DivergenceДистилляцияsum(y log(y/p))Приближение к распределению

Полный пример сравнения

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import tensorflow as tf
from tensorflow.keras import Sequential, layers
from tensorflow.keras.losses import CategoricalCrossentropy, KLDivergence

# Загрузить данные
X, y = load_iris(return_X_y=True)
y_onehot = tf.keras.utils.to_categorical(y)
X_train, X_test, y_train, y_test = train_test_split(X, y_onehot, test_size=0.2)

# Масштабировать
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# Модель с CCE
model = Sequential([
    layers.Dense(64, activation='relu', input_shape=(4,)),
    layers.Dense(3, activation='softmax')
])

model.compile(loss=CategoricalCrossentropy(), optimizer='adam', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=10, verbose=0)
evaluation = model.evaluate(X_test, y_test)
print(f'CCE - Loss: {evaluation[0]:.4f}, Accuracy: {evaluation[1]:.4f}')

Выводы

  • Binary CE — стандарт для бинарной классификации
  • Categorical CE — для мультикласса
  • Focal Loss — лучший выбор при дисбалансе классов
  • Hinge Loss — для SVM и максимального margin
  • KL Divergence — для дистилляции и вероятностных задач
  • Выбор функции потерь влияет на поведение модели больше, чем думают многие
Какие функции потерь используются для классификации? | PrepBro