Оценка точности ValueError: Не удается обработать смесь двоичной и непрерывной цели

Я использую linear_model.LinearRegression из scikit-learn в качестве прогностической модели. Это работает, и это прекрасно. У меня проблема с оценкой прогнозируемых результатов с использованием метрики accuracy_score.

Это мои настоящие данные:

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

Мои предсказанные данные:

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])

Мой код:

accuracy_score(y_true, y_pred, normalize=False)

Сообщение об ошибке:

ValueError: Не удается обработать смесь двоичного и непрерывного целевого объекта

Помогите? Спасибо.

Ответ 1

РЕДАКТИРОВАТЬ (после комментария): ниже решит проблему кодирования, но настоятельно не рекомендуется использовать этот подход, потому что модель линейной регрессии является очень плохим классификатором, который, скорее всего, не будет правильно разделять классы.

Прочитайте хорошо написанный ответ ниже @desertnaut, объясняющий, почему эта ошибка является намеком на что-то неправильное в подходе машинного обучения, а не на то, что вы должны "исправить".

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

Ответ 2

Несмотря на множество неправильных ответов, которые пытаются обойти ошибку путем численного манипулирования прогнозами, коренная причина вашей ошибки - теоретическая, а не вычислительная проблема: вы пытаетесь использовать метрику классификации (точность) в регрессии (то есть, в числовом выражении). предсказание) модель (LinearRegression), которая не имеет смысла.

Как и большинство показателей эффективности, точность сравнивает яблоки с яблоками (т.е. Истинные метки 0/1 с прогнозами снова 0/1); поэтому, когда вы просите функцию сравнить двоичные истинные метки (яблоки) с непрерывными предсказаниями (апельсины), вы получите ожидаемую ошибку, в которой сообщение точно скажет, в чем проблема с вычислительной точки зрения:

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

Несмотря на то, что сообщение не говорит вам напрямую, что вы пытаетесь вычислить метрику, которая является недопустимой для вашей проблемы (и мы не должны ожидать, что она зайдет так далеко), это, безусловно, хорошая вещь, которую scikit-learn at по крайней мере дает вам прямое и явное предупреждение о том, что вы пытаетесь сделать что-то не так; это не обязательно имеет место с другими фреймворками - посмотрите, например, поведение Keras в очень похожей ситуации, когда вы вообще не получаете предупреждения, и в результате вы просто жалуетесь на низкую "точность" в настройке регрессии...

Я очень удивлен всеми другими ответами здесь (в том числе принятыми и высоко оцененными), фактически предлагающими манипулировать предсказаниями, чтобы просто избавиться от ошибки; Это правда, что, как только мы получим набор чисел, мы, безусловно, можем начать смешиваться с ними различными способами (округление, пороговое значение и т.д.), чтобы заставить наш код вести себя, но это, конечно, не означает, что наши числовые манипуляции смысл в конкретном контексте проблемы ОД, которую мы пытаемся решить.

Итак, подведем итог: проблема в том, что вы применяете метрику (точность), которая не подходит для вашей модели (LinearRegression): если вы находитесь в настройке классификации, вы должны изменить свою модель (например, использовать вместо этого LogisticRegression); если вы находитесь в настройке регрессии (то есть числового прогнозирования), вам следует изменить метрику. Проверьте список метрик, доступных в Scikit-Learn, где вы можете убедиться, что точность используется только в классификации.

Сравните также ситуацию с недавним вопросом SO, где OP пытается получить точность списка моделей:

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

где первые 6 моделей работают нормально, а все остальные (закомментированные) выдают ту же ошибку. К настоящему времени вы должны быть в состоянии убедить себя в том, что все закомментированные модели являются регрессионными (а не классификационными), следовательно, это оправданная ошибка.

Последнее важное замечание: для кого-то может показаться законным заявить:

Хорошо, но я хочу использовать линейную регрессию, а затем просто округлить/порогить результаты, эффективно обрабатывая предсказания как "вероятности" и, таким образом, преобразовывая модель в классификатор

На самом деле, это уже было предложено в нескольких других ответах здесь, неявно или нет; опять же, это неверный подход (и тот факт, что у вас есть негативные прогнозы, уже должен был предупредить вас, что их нельзя интерпретировать как вероятности). Эндрю Нг в своем популярном курсе машинного обучения в Coursera объясняет, почему это плохая идея - см. Его лекцию 6.1 "Логистическая регрессия | Классификация на Youtube (объяснение начинается в ~ 3:00), а также в разделе 4.2. Почему не линейная регрессия [для классификации]? учебника (настоятельно рекомендуется и в свободном доступе) Введение в статистическое обучение Хасти, Тибширани и его коллег...

Ответ 4

Склеарн.метрика. accuracy_score (y_true, y_pred) Метод определяет y_pred как:

y_pred: массив 1d или массив индикаторов меток/разреженная матрица. Предсказанные метки, возвращаемые классификатором.

Это означает, что y_pred должен быть массивом 1 или 0 (предикатные метки). Они не должны быть вероятностями.

Предикатные метки (1 и 0) и/или прогнозируемые вероятности могут быть сгенерированы с использованием методов модели LinearRegression() Forex() и Forex_Proba() соответственно.

1. Создать прогнозируемые ярлыки:

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

выход:

[1 1 0 1]

"y_preds" теперь можно использовать для метода accuracy_score(y_true, y_pred)(): accuracy_score(y_true, y_pred)

2. Генерация вероятностей для меток:

Некоторые метрики, такие как "precision_recall_curve (y_true, probas_pred)", требуют вероятности, которые можно сгенерировать следующим образом:

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

выход:

[0,87812372 0,77490434 0,30319547 0,84999743]

Ответ 5

Проблема заключается в том, что истинный y является двоичным (нули и единицы), в то время как ваши прогнозы не являются. Вы, вероятно, генерировали вероятности, а не прогнозы, следовательно, результат:) Попробуйте вместо этого сгенерировать членство в классе, и оно должно работать!

Ответ 6

Возможно, это помогает кому-то, кто находит этот вопрос:

Как уже указывал JohnnyQ, проблема в том, что у вас есть небинарные (не 0 или 1) значения в вашем y_pred, i. е. при добавлении

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

вы увидите True на выходе. (Команда обнаруживает, есть ли какое-либо значение, которое не равно 0 или 1).

Вы можете видеть свои не двоичные значения, используя:

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

Оператор печати может выводить приведенные выше производные переменные.

Наконец, эта функция может очищать ваши данные от всех небинных записей:

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)

Ответ 7

В случае, если вы получаете эту ошибку при использовании библиотеки Orange (использует sklearn под капотом).

У меня был numpy == 1.14.5 установлен другим пакетом Python. Решением было вручную обновить numpy до 1.16.4: pip install -U numpy=1.16.4