Tengo muchos problemas para entender cómo funciona el class_weight
parámetro de Regresión logística de scikit-learn.
La situación
Quiero usar la regresión logística para hacer una clasificación binaria en un conjunto de datos muy desequilibrado. Las clases están etiquetadas como 0 (negativo) y 1 (positivo) y los datos observados están en una proporción de aproximadamente 19: 1 y la mayoría de las muestras tienen un resultado negativo.
Primer intento: preparación manual de datos de entrenamiento
Dividí los datos que tenía en conjuntos separados para entrenamiento y pruebas (alrededor de 80/20). Luego hice una muestra aleatoria de los datos de entrenamiento a mano para obtener datos de entrenamiento en diferentes proporciones que 19: 1; desde 2: 1 -> 16: 1.
Luego entrené la regresión logística en estos diferentes subconjuntos de datos de entrenamiento y tracé el recuerdo (= TP / (TP + FN)) en función de las diferentes proporciones de entrenamiento. Por supuesto, la recuperación se calculó en las muestras de PRUEBA disjuntos que tenían las proporciones observadas de 19: 1. Tenga en cuenta que, aunque entrené los diferentes modelos en diferentes datos de entrenamiento, calculé la recuperación para todos ellos en los mismos datos de prueba (disjuntos).
Los resultados fueron los esperados: la recuperación fue de alrededor del 60% en proporciones de entrenamiento de 2: 1 y cayó bastante rápido cuando llegó a 16: 1. Hubo varias proporciones 2: 1 -> 6: 1 en las que el retiro fue decentemente superior al 5%.
Segundo intento: búsqueda en cuadrícula
A continuación, quería probar diferentes parámetros de regularización, por lo que usé GridSearchCV e hice una cuadrícula de varios valores del C
parámetro, así como del class_weight
parámetro. Para traducir mis n: m proporciones de muestras de entrenamiento negativas: positivas al idioma del diccionario de class_weight
, pensé que solo especifico varios diccionarios de la siguiente manera:
{ 0:0.67, 1:0.33 } #expected 2:1
{ 0:0.75, 1:0.25 } #expected 3:1
{ 0:0.8, 1:0.2 } #expected 4:1
y también incluí None
y auto
.
Esta vez los resultados fueron totalmente descabellados. Todos mis retiros resultaron pequeños (<0.05) para cada valor de class_weight
excepto auto
. Así que solo puedo asumir que mi comprensión de cómo configurar el class_weight
diccionario es incorrecta. Curiosamente, el class_weight
valor de 'auto' en la búsqueda de la cuadrícula fue de alrededor del 59% para todos los valores de C
, y supuse que se equilibra en 1: 1.
Mis preguntas
¿Cómo se usa correctamente
class_weight
para lograr diferentes equilibrios en los datos de entrenamiento de los que realmente les da? Específicamente, ¿a qué diccionario paso paraclass_weight
usar n: m proporciones de muestras de entrenamiento negativas: positivas?Si pasa varios
class_weight
diccionarios a GridSearchCV, durante la validación cruzada, ¿reequilibrará los datos del pliegue de entrenamiento de acuerdo con el diccionario, pero utilizará las proporciones de muestra reales dadas para calcular mi función de puntuación en el pliegue de prueba? Esto es fundamental ya que cualquier métrica solo me es útil si proviene de datos en las proporciones observadas.¿Qué hace el
auto
valor declass_weight
en cuanto a proporciones? Leí la documentación y supongo que "equilibra los datos de forma inversamente proporcional a su frecuencia", solo significa que los hace 1: 1. ¿Es esto correcto? Si no, ¿alguien puede aclararlo?
fuente
Respuestas:
En primer lugar, puede que no sea bueno limitarse a recordar solo. Simplemente puede lograr una recuperación del 100% clasificando todo como la clase positiva. Por lo general, sugiero usar AUC para seleccionar parámetros y luego encontrar un umbral para el punto de operación (digamos, un nivel de precisión dado) que le interesa.
Cómo
class_weight
funciona: penaliza los errores en muestras declass[i]
con enclass_weight[i]
lugar de 1. Por lo tanto, un peso de clase más alto significa que desea poner más énfasis en una clase. Por lo que dice, parece que la clase 0 es 19 veces más frecuente que la clase 1. Por lo tanto, debe aumentar elclass_weight
de la clase 1 en relación con la clase 0, digamos {0: .1, 1: .9}. Siclass_weight
no suma 1, básicamente cambiará el parámetro de regularización.Para saber cómo
class_weight="auto"
funciona, puede echar un vistazo a esta discusión . En la versión dev puedes usarclass_weight="balanced"
, que es más fácil de entender: básicamente significa replicar la clase más pequeña hasta tener tantas muestras como en la más grande, pero de forma implícita.fuente
La primera respuesta es buena para comprender cómo funciona. Pero quería entender cómo debería usarlo en la práctica.
RESUMEN
class_weight="balanced"
funciona decente en ausencia de que desee optimizar manualmenteclass_weight="balanced"
captura más eventos verdaderos (mayor recuperación VERDADERA) pero también es más probable que reciba alertas falsas (menor precisión VERDADERA)nótese bien
El resultado puede diferir al utilizar RF o GBM. sklearn no tiene
class_weight="balanced"
para GBM pero lightgbm tieneLGBMClassifier(is_unbalance=False)
CÓDIGO
fuente