1 votos

Calibración de las probabilidades del clasificador Ridge en un conjunto de datos desequilibrado

Tengo un proyecto de clasificación sobre un conjunto de datos desequilibrado (HomeCredit Kaggle dataset) y he elegido el clasificador Ridge (implementación de sklearn) como el más eficiente tanto en términos de tiempo como en términos de mi indicador de rendimiento (puntuación ROC AUC).

El conjunto de datos inicial está muy desequilibrado (0,92 TARGET = 0, 0,08 TARGET = 1), por lo que tuve que realizar un sobremuestreo SMOTE al conjunto de datos de entrenamiento para devolver la proporción al 50/50. Hay unas 450 características con 300k muestras.

En una entrada anterior, los comentaristas parecían dudar de los méritos del sobremuestreo. He probado diferentes proporciones (desde la proporción inicial hasta 1 o 50/50) y se ha producido una mejora lineal del AUC del ROC al aumentar la proporción y llevarla hasta 1. Así que creo que es necesario en este caso, posiblemente debido al elevado número de características.

Como se me pide que proporcione probabilidades para mis predicciones, he ampliado la clase RidgeClassifier con softmax como tal (a partir de la investigación en otro post) :

class RidgeClassifierWithProba(RidgeClassifier):
    def predict_proba(self, X):
        d = self.decision_function(X)
        d_2d = np.c_[-d, d]
        return softmax(d_2d)

Las puntuaciones finales que obtengo de mi modelo son relativamente buenas, con una puntuación ROC AUC final de 0,76 cuando se tienen en cuenta esas probabilidades (0,70 sólo con las predicciones). Los mejores Kagglers solo han sido capaces de alcanzar 0,805 durante la competición, así que creo que está bastante cerca.

El problema es que el histograma de probabilidades muestra que no hay separación entre las 2 clases, con una densidad distribuida casi normalmente:

enter image description here

He intentado implementar las siguientes funciones de CalibratedClassifierCV para mejorar esta distribución:

pipe_iso = CalibratedClassifierCV(final_pipe, cv=2, method="isotonic")
pipe_sig = CalibratedClassifierCV(final_pipe, cv=2, method="sigmoid")

Pero hace que la distribución de probabilidades sea aún peor, con todas ellas sesgadas hacia la clase mayoritaria :

enter image description here

¿Estoy haciendo algo mal? ¿Mi modelo no es lo suficientemente bueno como para tener un histograma de probabilidades separado? ¿Qué más puedo hacer para calibrar mis probabilidades?

Editar : A petición de @Ben Reiniger, he subido mi trabajo a Kaggle : Enlace a Kagggle y estoy publicando más código a continuación. Esta es mi tubería final:

#Defining our final pipeline
final_pipe = Pipeline([
    ('cat_encode', cat_encode),
    ('imputation', SimpleImputer(strategy='median')),
    ('scaler', StandardScaler()),
    ('var', boruta),
    ('os', ADASYN()),
    ('ridge',RidgeClassifierWithProba(alpha=6.967)),
    ], memory="./Cache/")

Si hay alguna diferencia, esta es una tubería Imbalearn y no una tubería Sklearn ya que implementa el sobremuestreo.

El codificador Cat es un transformador de columna que imputa los campos categóricos en función del número de categorías únicas (One Hot cuando nunique <= 5 y WOE cuando nunique >5). Boruta es un FunctionTransformer construido a partir de un Selector Boruta.

Aquí están mis resultados en el conjunto de pruebas (los resultados en el conjunto de entrenamiento son similares) :

enter image description here

Para aclarar mi afirmación sobre la puntuación ROC AUC, cuando introduzco en la función roc_auc_score sólo los resultados predichos del clasificador Ridge base, devuelve 0,7, mientras que cuando introduzco las probabilidades, devuelve 0,76 (porque suaviza la curva).

final_pipe.fit(X_train_reduced, y_train)
train_predictions = final_pipe.predict(X_train_reduced)
proba_train = final_pipe.predict_proba(X_train_reduced)[:, 1]
test_predictions = final_pipe.predict(X_test)
proba_test = final_pipe.predict_proba(X_test)[:, 1]

roc_auc_score(y_test, test_predictions) #Returns 0.7
roc_auc_score(y_test, proba_test) #Returns 0.76

Al calibrar las probabilidades con mi calibrador isotónico, obtengo el siguiente gráfico de barras "apilado", que se ve bien pero en realidad los colores son las probabilidades de cada clase. Así que, a menos que esté malinterpretando algo, significa que con un umbral de probabilidad de 0,5 esto predeciría que todos los resultados de las pruebas están en la clase mayoritaria (azul) .

test_prob = pipe_iso.predict_proba(X_test)

plt.hist(test_prob, stacked=True)
plt.show()

enter image description here

Para comparar, este es el mismo gráfico con mi tubería sin calibrar:

enter image description here

0voto

Rob Van Dam Puntos 5073

El problema es que el histograma de probabilidades muestra que no hay separación entre las 2 clases, con una densidad distribuida casi normalmente

Con un AUROC de 0,76, creo que es lo esperado. Si la densidad de la distribución fuera bimodal (y el rendimiento no fuera una basura, de modo que la mayoría de los datos con valores en los dos picos estuvieran correctamente ordenados), se obtendría un gran número de pares puestos en el orden correcto (el AUROC tiene una interpretación como "proporción de pares positivos-negativos que aparecen en el orden correcto por puntuación). Y el hecho de que las puntuaciones sean unimodales no significa que las clases no lo sean Algo así como bien separados, de ahí mi sugerencia en un comentario de dividir las barras por clase.

Pero hace que la distribución de probabilidades sea aún peor, con todas ellas sesgadas hacia la clase mayoritaria

¡Eso no es peor! La clase mayoritaria domina, por lo que las probabilidades debe estar inclinado hacia ella.

Tenga en cuenta que la última casilla del gráfico sigmoide tiene muy pocos datos, así que tome la tasa positiva muy baja con un grano de sal. (También podría utilizar strategy='quantile' en lugar de la opción por defecto 'uniform' para que los intervalos del gráfico sean de igual volumen en lugar de igual anchura).

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X