Puntuación de precisión ValueError: No se puede manejar la combinación de objectives binarios y continuos

Estoy usando linear_model.LinearRegression de scikit-learn como modelo predictivo. Funciona y es perfecto. Tengo un problema para evaluar los resultados predichos utilizando la métrica accuracy_score . Este es mi verdadero dato:

 array([1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0]) 

Mis datos predictivos:

 array([ 0.07094605, 0.1994941 , 0.19270157, 0.13379635, 0.04654469, 0.09212494, 0.19952108, 0.12884365, 0.15685076, -0.01274453, 0.32167554, 0.32167554, -0.10023553, 0.09819648, -0.06755516, 0.25390082, 0.17248324]) 

Mi código:

 accuracy_score(y_true, y_pred, normalize=False) 

Mensaje de error:

ValueError: no se puede manejar la mezcla de destino binario y continuo

Ayuda ? Gracias.

Related of "Puntuación de precisión ValueError: No se puede manejar la combinación de objectives binarios y continuos"

EDITAR (después del comentario): lo siguiente resolverá el problema de encoding, pero no se recomienda utilizar este enfoque porque un modelo de regresión lineal es un clasificador muy pobre, lo que probablemente no separará las clases correctamente.

Lea la respuesta bien escrita a continuación por @desertnaut, y explique por qué este error es un indicio de algo incorrecto en el enfoque de aprendizaje automático en lugar de algo que tiene que “arreglar”.

 accuracy_score(y_true, y_pred.round(), normalize=False) 

A pesar de la gran cantidad de respuestas incorrectas que intentan evitar el error manipulando numéricamente las predicciones, la causa principal de su error es un problema teórico y no computacional: está tratando de usar una métrica de clasificación (precisión) en una regresión (es decir, numérica predicción) modelo ( LinearRegression ), que no tiene sentido .

Al igual que la mayoría de las métricas de rendimiento, la precisión compara manzanas con manzanas (es decir, tags verdaderas de 0/1 con predicciones nuevamente de 0/1); así, cuando le pide a la función que compare tags binarias verdaderas (manzanas) con predicciones continuas (naranjas), obtiene un error esperado, donde el mensaje le dice exactamente cuál es el problema desde un punto de vista computacional :

 Classification metrics can't handle a mix of binary and continuous target 

A pesar de que el mensaje no le dice directamente que está tratando de calcular una métrica que no es válida para su problema (y que no deberíamos esperar que llegue tan lejos), es una buena cosa que scikit-learn at por lo menos te da una advertencia directa y explícita de que estás intentando algo mal; este no es necesariamente el caso con otros marcos; vea, por ejemplo, el comportamiento de Keras en una situación muy similar , donde no recibe ninguna advertencia, y uno termina por quejarse de baja “precisión” en una configuración de regresión …

Estoy muy sorprendido con todas las otras respuestas aquí (incluida la aceptada y altamente valorada) que sugiere manipular las predicciones para simplemente deshacernos del error; es cierto que, una vez que terminamos con un conjunto de números, podemos comenzar a mezclarnos con ellos de varias maneras (redondeo, umbrales, etc.) para hacer que nuestro código se comporte, pero esto, por supuesto, no significa que nuestras manipulaciones numéricas sean significativo en el contexto específico del problema de LD que estamos tratando de resolver.

Entonces, para terminar: el problema es que está aplicando una métrica (precisión) que no es apropiada para su modelo ( LinearRegression ): si está en una configuración de clasificación, debe cambiar su modelo (por ejemplo, use LogisticRegression lugar); Si está en un ajuste de regresión (es decir, predicción numérica), debe cambiar la métrica. Verifique la lista de métricas disponibles en scikit-learn , donde puede confirmar que la precisión se usa solo en la clasificación.

Compare también la situación con una pregunta SO reciente , donde el OP está tratando de obtener la precisión de una lista de modelos:

 models = [] models.append(('SVM', svm.SVC())) models.append(('LR', LogisticRegression())) models.append(('LDA', LinearDiscriminantAnalysis())) models.append(('KNN', KNeighborsClassifier())) models.append(('CART', DecisionTreeClassifier())) models.append(('NB', GaussianNB())) #models.append(('SGDRegressor', linear_model.SGDRegressor())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets #models.append(('BayesianRidge', linear_model.BayesianRidge())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets #models.append(('LassoLars', linear_model.LassoLars())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets #models.append(('ARDRegression', linear_model.ARDRegression())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets #models.append(('PassiveAggressiveRegressor', linear_model.PassiveAggressiveRegressor())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets #models.append(('TheilSenRegressor', linear_model.TheilSenRegressor())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets #models.append(('LinearRegression', linear_model.LinearRegression())) #ValueError: Classification metrics can't handle a mix of binary and continuous targets 

donde los primeros 6 modelos funcionan bien, mientras que todos los demás (comentados) dan el mismo error. A estas alturas, debería poder convencerse de que todos los modelos comentados son de regresión (y no de clasificación), de ahí el error justificado.

Una última nota importante: puede sonar legítimo para alguien reclamar:

Está bien, pero quiero usar la regresión lineal y luego redondear / limitar las salidas, tratar las predicciones como “probabilidades” y convertir el modelo en un clasificador.

En realidad, esto ya ha sido sugerido en varias otras respuestas aquí, implícitamente o no; de nuevo, este es un enfoque no válido (y el hecho de que tenga predicciones negativas ya debería haberle alertado de que no se pueden interpretar como probabilidades). Andrew Ng, en su popular curso de Aprendizaje de Máquina en Coursera, explica por qué es una mala idea – vea su Conferencia 6.1 – Regresión logística | Clasificación en Youtube (la explicación comienza en ~ 3:00), así como en la sección 4.2 ¿Por qué no una regresión lineal [para la clasificación]? del libro de texto (altamente recomendado y disponible gratuitamente) Una Introducción al Aprendizaje Estadístico por Hastie, Tibshirani y compañeros de trabajo …

Los sklearn.metrics. El método precision_score (y_true, y_pred) define y_pred como:

y_pred : 1d array-like, o matriz de indicador de etiqueta / matriz dispersa. Etiquetas predichas , según lo devuelto por un clasificador.

Lo que significa que y_pred tiene que ser una matriz de 1 o 0 (tags predicadas). No deben ser probabilidades.

Las tags predicadas (1’s y 0’s) y / o probabilites predichos pueden generarse usando los métodos predecir () y predict_proba () del modelo LinearRegression () respectivamente.

1. Generar tags predichas:

 LR = linear_model.LinearRegression() y_preds=LR.predict(X_test) print(y_preds) 

salida:

[1 1 0 1]

‘y_preds’ ahora se puede usar para el método precision_score (): accuracy_score(y_true, y_pred)

2. Generar probabilidades para las tags:

Algunas métricas como ‘precision_recall_curve (y_true, probas_pred)’ requieren probabilidades, que se pueden generar de la siguiente manera:

 LR = linear_model.LinearRegression() y_preds=LR.predict_proba(X_test) print(y_preds) 

salida:

[0.87812372 0.77490434 0.30319547 0.84999743]

precision_score es una métrica de clasificación, no puede usarla para un problema de regresión.

Puedes ver las métricas de regresión disponibles aquí.

Tal vez esto ayude a alguien que encuentre esta pregunta:

Como JohnnyQ ya señaló, el problema es que tiene valores no binarios (no 0 ni 1) en su y_pred , es decir, al agregar

 print(((y_pred != 0.) & (y_pred != 1.)).any()) 

Verá True en la salida. (El comando descubre si hay algún valor que no sea 0 o 1).

Puedes ver tus valores no binarios usando:

 non_binary_values = y_pred[(y_pred['score'] != 1) & (y_pred['score'] != 0)] non_binary_idxs = y_pred[(y_pred['score'] != 1) & (y_pred['score'] != 0)].index 

Una statement de impresión puede generar las variables derivadas anteriores.

Finalmente, esta función puede limpiar sus datos de todas las entradas no binarias:

 def remove_unlabelled_data(X, y): drop_indexes = X[(y['score'] != 1) & (y['score'] != 0)].index return X.drop(drop_indexes), y.drop(drop_indexes) 

El problema es que la verdadera y es binaria (ceros y unos), mientras que sus predicciones no lo son. Probablemente generaste probabilidades y no predicciones, de ahí el resultado 🙂 ¡Intenta en cambio generar membresía de clase, y debería funcionar!