ValueError: этому решателю нужны образцы как минимум 2 классов в данных, но данные содержат только один класс: 0.0

Я применил логистическую регрессию к набору поездов после разделения набора данных на наборы тестов и поездов, но получил указанную выше ошибку. Я попытался разобраться, и когда я попытался напечатать свой вектор ответа y_train в консоли, он печатает целочисленные значения, такие как 0 или 1. Но когда я записал его в файл, я обнаружил, что значения были числами с плавающей запятой, такими как 0,0 и 1,0. Если это проблема, как я могу ее преодолеть.

lenreg = LogisticRegression()

print y_train[0:10]
y_train.to_csv(path='ytard.csv')

lenreg.fit(X_train, y_train)
y_pred = lenreg.predict(X_test)
print metics.accuracy_score(y_test, y_pred)

StrackTrace выглядит следующим образом:

Traceback (most recent call last):

  File "/home/amey/prog/pd.py", line 82, in <module>

    lenreg.fit(X_train, y_train)

  File "/usr/lib/python2.7/dist-packages/sklearn/linear_model/logistic.py", line 1154, in fit

    self.max_iter, self.tol, self.random_state)

  File "/usr/lib/python2.7/dist-packages/sklearn/svm/base.py", line 885, in _fit_liblinear

    " class: %r" % classes_[0])

ValueError: This solver needs samples of at least 2 classes in the data, but the data contains only one class: 0.0

Тем временем я перешел по ссылке который остался без ответа. Есть ли решение.


person Amey Yadav    schedule 10.11.2016    source источник
comment
Некоторые замечания: (1) Логистическая регрессия — это классификация, а не регрессия. Итак, вам нужны классы (2) Y должен состоять из классов. Либо 1d-boolean-массив для каждого образца, помечающего класс как 1, либо одно число для каждого образца с классом (например, 5 классов -> количество (0,1,2,3,4). (3) Y должен быть целочисленного типа -> никаких поплавков!(4) Проверьте свой y_train!   -  person sascha    schedule 10.11.2016


Ответы (6)


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

Это имеет смысл. Если ваш вектор y_train имеет только нули (т.е. только 1 класс), то классификатору действительно не нужно выполнять какую-либо работу, поскольку все прогнозы должны быть просто одним классом.

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

Способ проверки этого условия выглядит следующим образом:

lenreg = LogisticRegression()

print y_train[0:10]
y_train.to_csv(path='ytard.csv')

if len(np.sum(y_train)) in [len(y_train),0]:
    print "all one class"
    #do something else
else:
    #OK to proceed
    lenreg.fit(X_train, y_train)
    y_pred = lenreg.predict(X_test)
    print metics.accuracy_score(y_test, y_pred)

ЧТОБЫ решить эту проблему проще, я бы рекомендовал просто включить больше образцов в ваш тестовый набор, например, 100 или 1000 вместо 10.

person jeffery_the_wind    schedule 09.05.2017

У меня была такая же проблема с использованием learning_curve:

 train_sizes, train_scores, test_scores = learning_curve(estimator,
           X, y, cv=cv, n_jobs=n_jobs, train_sizes=train_sizes,
           scoring="f1", random_state=RANDOM_SEED, shuffle=True)

добавьте параметр suffle, который будет рандомизировать наборы.

Это не предотвращает возникновение ошибок, но позволяет увеличить вероятность наличия обоих классов в подмножествах, используемых функцией.

person Xfox    schedule 02.09.2019

# python3
import numpy as np
from sklearn.svm import LinearSVC

def upgrade_to_work_with_single_class(SklearnPredictor):
    class UpgradedPredictor(SklearnPredictor):
        def __init__(self, *args, **kwargs):
            self._single_class_label = None
            super().__init__(*args, **kwargs)

        @staticmethod
        def _has_only_one_class(y):
            return len(np.unique(y)) == 1

        def _fitted_on_single_class(self):
            return self._single_class_label is not None

        def fit(self, X, y=None):
            if self._has_only_one_class(y):
                self._single_class_label = y[0]
            else:
                super().fit(X, y)
            return self

        def predict(self, X):
            if self._fitted_on_single_class():
                return np.full(X.shape[0], self._single_class_label)
            else:
                return super().predict(X)
    return UpgradedPredictor

LinearSVC = upgrade_to_work_with_single_class(LinearSVC)

или трудным путем (более правильно):

import numpy as np

from sklearn.svm import LinearSVC
from copy import deepcopy, copy
from functools import wraps

def copy_class(cls):
    copy_cls = type(f'{cls.__name__}', cls.__bases__, dict(cls.__dict__))
    for name, attr in cls.__dict__.items():
        try:
            hash(attr)
        except TypeError:
            # Assume lack of __hash__ implies mutability. This is NOT
            # a bullet proof assumption but good in many cases.
            setattr(copy_cls, name, deepcopy(attr))
    return copy_cls

def upgrade_to_work_with_single_class(SklearnPredictor):
    SklearnPredictor = copy_class(SklearnPredictor)
    original_init = deepcopy(SklearnPredictor.__init__)
    original_fit = deepcopy(SklearnPredictor.fit)
    original_predict = deepcopy(SklearnPredictor.predict)

    @staticmethod
    def _has_only_one_class(y):
        return len(np.unique(y)) == 1

    def _fitted_on_single_class(self):
        return self._single_class_label is not None

    @wraps(SklearnPredictor.__init__)
    def new_init(self, *args, **kwargs):
        self._single_class_label = None
        original_init(self, *args, **kwargs)

    @wraps(SklearnPredictor.fit)
    def new_fit(self, X, y=None):
        if self._has_only_one_class(y):
            self._single_class_label = y[0]
        else:
            original_fit(self, X, y)
        return self

    @wraps(SklearnPredictor.predict)
    def new_predict(self, X):
        if self._fitted_on_single_class():
            return np.full(X.shape[0], self._single_class_label)
        else:
            return original_predict(self, X)

    setattr(SklearnPredictor, '_has_only_one_class', _has_only_one_class)
    setattr(SklearnPredictor, '_fitted_on_single_class', _fitted_on_single_class)
    SklearnPredictor.__init__ = new_init
    SklearnPredictor.fit = new_fit
    SklearnPredictor.predict = new_predict
    return SklearnPredictor

LinearSVC = upgrade_to_work_with_single_class(LinearSVC)
person Антон Талецкий    schedule 01.10.2019

Я обнаружил, что это произошло из-за того, что в моем y_test оказались только 1 или 0, поскольку размер моей выборки был очень маленьким. Попробуйте изменить значение test_size.

person Guesting    schedule 02.07.2019

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

person Navkanth    schedule 17.03.2021

Эта ошибка связана с используемым вами набором данных, набор данных содержит класс, например, 1/доброкачественный, тогда как он должен содержать два класса 1 и 0 или доброкачественный и атакующий.

person Redhwan Ghailan    schedule 11.04.2021