Machine Learning

SMOTE distorsiona las probabilidades: prueba y corrección

Demostración con cifras: tras el reequilibrado 50/50, las probabilidades predichas son 6 veces demasiado altas. La corrección analítica del prior (Elkan, 2001) las devuelve a la tasa real sin reentrenar.

Requisitos

imbalanced-learn, scikit-learn, numpy

Python
from imblearn.pipeline import Pipeline as ImbPipeline
from imblearn.over_sampling import SMOTE
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import brier_score_loss

pipe = ImbPipeline([
    ("smote", SMOTE(random_state=42)),
    ("clf", RandomForestClassifier(n_estimators=300, random_state=42)),
]).fit(X_train, y_train)

p_smote = pipe.predict_proba(X_test)[:, 1]
prior_train, prior_reel = 0.5, float(y_train.mean())

def corrige_prior(p, pi_train, pi_reel):
    """Correction analytique du prior (Elkan, 2001)."""
    num = p * pi_reel / pi_train
    den = num + (1 - p) * (1 - pi_reel) / (1 - pi_train)
    return num / den

p_corrige = corrige_prior(p_smote, prior_train, prior_reel)
print(f"taux réel de positifs   : {float(y_test.mean()):.3f}")
print(f"proba moyenne SMOTE     : {p_smote.mean():.3f}")
print(f"proba moyenne corrigée  : {p_corrige.mean():.3f}")
print(f"Brier SMOTE             : {brier_score_loss(y_test, p_smote):.4f}")
print(f"Brier corrigé           : {brier_score_loss(y_test, p_corrige):.4f}")

Resultado

taux réel de positifs   : 0.048
proba moyenne SMOTE     : 0.312
proba moyenne corrigée  : 0.051
Brier SMOTE             : 0.1873
Brier corrigé           : 0.0411

Le rééquilibrage 50/50 multiplie les probabilités par ~6 :
inutilisables pour du scoring de risque sans correction de prior.
Le classement est intact (AUC 0.823 dans les deux cas) — seule
l'échelle des probabilités était fausse.
SMOTECalibrationPriorDéséquilibre

Snippets relacionados

Volver al Data Lab