← Назад к вопросам
Что такое дисбаланс классов?
1.7 Middle🔥 241 комментариев
#Машинное обучение#Метрики и оценка моделей
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Class Imbalance (дисбаланс классов)
Class imbalance — это ситуация, когда количество образцов одного класса значительно превышает количество образцов другого класса в датасете.
Примеры
import numpy as np
# Пример: Fraud detection (мошенничество)
total_transactions = 10000
fraudulent = 50 # 0.5%
legitimate = 9950 # 99.5%
ratio = fraudulent / legitimate
print(f"Imbalance ratio: 1:{int(legitimate/fraudulent)}") # 1:199
# Пример: Disease detection
diseased = 100 # 10%
healthy = 900 # 90%
print(f"Imbalance ratio: 1:{int(healthy/diseased)}") # 1:9
# Пример: Extremely imbalanced (очень неуравновешенный)
rare_event = 1
common_event = 99999
print(f"Imbalance ratio: 1:{int(common_event/rare_event)}") # 1:99999
Проблема: Accuracy парадокс
from sklearn.metrics import accuracy_score, precision_score, recall_score
from sklearn.linear_model import LogisticRegression
import numpy as np
# Данные: 95% класс 0, 5% класс 1
y_true = np.array([0]*95 + [1]*5)
y_pred_lazy = np.array([0]*100) # модель всегда предсказывает класс 0
accuracy = accuracy_score(y_true, y_pred_lazy)
precision = precision_score(y_true, y_pred_lazy, zero_division=0)
recall = recall_score(y_true, y_pred_lazy, zero_division=0)
print(f"Accuracy: {accuracy:.2%}") # 95% (высокий!)
print(f"Precision: {precision:.2%}") # 0% (класс 1 не предсказан)
print(f"Recall: {recall:.2%}") # 0% (класс 1 не предсказан)
# Модель бесполезна, но accuracy выглядит хорошо!
Почему это проблема
1. Accuracy не отражает качество
→ модель может быть бесполезной, но иметь 95%+ accuracy
2. Модель смещена к majority классу
→ учится предсказывать только frequent класс
3. Неправильная оценка performance
→ нужны другие метрики
Правильные метрики для imbalanced данных
from sklearn.metrics import (
confusion_matrix, precision_recall_curve, roc_auc_score,
f1_score, roc_curve
)
y_true = np.array([0]*95 + [1]*5)
y_proba = np.random.random(100)
# НЕПРАВИЛЬНО (не использовать)
accuracy = accuracy_score(y_true, y_proba > 0.5)
# ПРАВИЛЬНО (используй эти метрики)
# 1. F1-score (balance между precision и recall)
f1 = f1_score(y_true, y_proba > 0.5)
print(f"F1: {f1:.3f}")
# 2. Precision-Recall curve (вместо ROC)
precision, recall, _ = precision_recall_curve(y_true, y_proba)
print(f"Precision-Recall AUC: {np.trapz(precision, recall):.3f}")
# 3. ROC-AUC (работает лучше, чем accuracy)
roc_auc = roc_auc_score(y_true, y_proba)
print(f"ROC-AUC: {roc_auc:.3f}")
# 4. Confusion matrix
tn, fp, fn, tp = confusion_matrix(y_true, y_proba > 0.5).ravel()
print(f"TP: {tp}, FN: {fn}, FP: {fp}, TN: {tn}")
Методы борьбы с дисбалансом
1. Oversampling (увеличение minority класса)
from imblearn.over_sampling import RandomOverSampler, SMOTE
from imblearn.pipeline import Pipeline
X_train = np.array([[1, 2], [2, 3], [3, 4], [4, 5]])
y_train = np.array([0, 0, 0, 1]) # дисбаланс
# Random oversampling (просто дублируем minority)
ros = RandomOverSampler(random_state=42)
X_resampled, y_resampled = ros.fit_resample(X_train, y_train)
print(f"Original: {len(y_train)}, Resampled: {len(y_resampled)}")
# SMOTE: синтетические образцы
smote = SMOTE(random_state=42)
X_smote, y_smote = smote.fit_resample(X_train, y_train)
2. Undersampling (уменьшение majority класса)
from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = rus.fit_resample(X_train, y_train)
print(f"Original: {len(y_train)}, Resampled: {len(y_resampled)}")
# Минус: теряем информацию
3. Weighted loss (взвешивание классов)
from sklearn.utils.class_weight import compute_class_weight
from sklearn.ensemble import RandomForestClassifier
# Вычисляем веса
class_weights = compute_class_weight(
'balanced',
classes=np.unique(y_train),
y=y_train
)
print(f"Class weights: {class_weights}")
# Используем в модели
model = RandomForestClassifier(
class_weight='balanced' # даёт больший вес minority
)
model.fit(X_train, y_train)
# Или вручную указать веса
model = RandomForestClassifier(
class_weight={0: 1, 1: 10} # класс 1 в 10 раз важнее
)
4. Hybrid: SMOTE + ENN (Edited Nearest Neighbors)
from imblearn.pipeline import Pipeline
from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import EditedNearestNeighbours
pipeline = Pipeline([
('smote', SMOTE(random_state=42)),
('enn', EditedNearestNeighbours()),
])
X_resampled, y_resampled = pipeline.fit_resample(X_train, y_train)
Практический пример: Fraud Detection
import pandas as pd
from sklearn.model_selection import train_test_split
from xgboost import XGBClassifier
from sklearn.metrics import roc_auc_score, f1_score
from imblearn.over_sampling import SMOTE
# Данные
X = pd.DataFrame(np.random.randn(10000, 10))
y = np.array([0]*9950 + [1]*50) # 0.5% fraud
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# SMOTE на тренировочных данных
smote = SMOTE(random_state=42)
X_train_smoted, y_train_smoted = smote.fit_resample(X_train, y_train)
print(f"Before SMOTE: {len(y_train)}")
print(f"After SMOTE: {len(y_train_smoted)}")
print(f"Class balance: {np.mean(y_train_smoted):.2%}") # 50%
# Обучение на сбалансированных данных
model = XGBClassifier(
scale_pos_weight=(y_train == 0).sum() / (y_train == 1).sum(),
random_state=42
)
model.fit(X_train_smoted, y_train_smoted)
# Оценка на оригинальном тестовом наборе
y_pred_proba = model.predict_proba(X_test)[:, 1]
roc_auc = roc_auc_score(y_test, y_pred_proba)
f1 = f1_score(y_test, y_pred_proba > 0.5)
print(f"ROC-AUC: {roc_auc:.3f}")
print(f"F1-score: {f1:.3f}")
Checklist для imbalanced данных
✓ Используй stratified k-fold для кросс-валидации
✓ Применяй SMOTE или weighted loss
✓ Выбирай F1, Precision-Recall, ROC-AUC (не Accuracy)
✓ Визуализируй confusion matrix
✓ Проверяй recall и precision для каждого класса
✓ Тестируй на оригинальном (imbalanced) тестовом наборе
✓ Не забывай про бизнес-контекст (cost of FP vs FN)
Резюме
Class Imbalance:
- Minority класс сильно недопредставлен
- Accuracy парадокс: высокая accuracy при бесполезной модели
- Методы: SMOTE, weighted loss, stratified CV
- Метрики: F1, ROC-AUC, Precision-Recall (не Accuracy)
- Всегда тестируй на оригинальных (imbalanced) данных