Что такое дисбаланс классов в машинном обучении?

«Что такое дисбаланс классов в машинном обучении?» — вопрос из категории Предобработка данных, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Дисбаланс классов — это ситуация в задачах классификации, когда распределение экземпляров по классам существенно неравномерно. Один класс (мажоритарный, negative) содержит подавляющее большинство примеров, а другой (миноритарный, positive) — значительно меньше. Например, 99% транзакций легальны и 1% — мошеннические.

Проблемы, которые вызывает дисбаланс:

  1. Смещение модели: Алгоритм, оптимизирующий общую точность (accuracy), быстро научится всегда предсказывать мажоритарный класс, достигая высокой, но бессмысленной метрики (99% accuracy в примере выше).
  2. Плохое обучение на миноритарном классе: Модель редко видит примеры редкого класса и не может выучить его характерные признаки.
  3. Неадекватные метрики оценки: Точность (Accuracy) становится бесполезной. Необходимо использовать метрики, чувствительные к дисбалансу.

Методы борьбы с дисбалансом:

1. На уровне данных (Resampling):

from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import RandomUnderSampler
from imblearn.pipeline import Pipeline

# Передискретизация (увеличение числа примеров миноритарного класса)
# SMOTE создаёт синтетические примеры на основе существующих
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)

# Недостаточная выборка (уменьшение числа примеров мажоритарного класса)
rus = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = rus.fit_resample(X_train, y_train)

# Комбинация (часто лучший подход)
pipeline = Pipeline([
    ('oversample', SMOTE(sampling_strategy=0.5)),  # Увеличим миноритарный до 50% от мажоритарного
    ('undersample', RandomUnderSampler(sampling_strategy=0.8)) # Уменьшим мажоритарный
])
X_res, y_res = pipeline.fit_resample(X_train, y_train)

2. На уровне алгоритма:

  • Взвешивание классов (Class Weight): Присвоение большей «стоимости» ошибке на миноритарном классе в функции потерь.
    from sklearn.linear_model import LogisticRegression
    # 'balanced' автоматически присваивает веса, обратно пропорциональные частоте классов
    model = LogisticRegression(class_weight='balanced')
    # Или вручную:
    model = LogisticRegression(class_weight={0: 1, 1: 10}) # Ошибка для класса 1 в 10 раз «дороже»

3. На уровне оценки:

  • Использование правильных метрик: F1-score (гармоническое среднее precision и recall), Precision-Recall AUC, ROC-AUC, Cohen's Kappa.
  • Анализ матрицы ошибок (Confusion Matrix) вместо одной сводной цифры.

Выбор стратегии зависит от данных и задачи. Часто комбинация взвешивания классов и использования SMOTE даёт наилучшие результаты.