← Назад к вопросам
Какие функции потерь используются для классификации?
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 Loss | SVM-стиль | 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 — для дистилляции и вероятностных задач
- Выбор функции потерь влияет на поведение модели больше, чем думают многие