【问题标题】:ValueError: This solver needs samples of at least 2 classes in the data, but the data contains only one class: 0.0ValueError:此求解器需要数据中至少 2 个类的样本,但数据仅包含一个类:0.0
【发布时间】:2017-03-24 07:33:57
【问题描述】:

在将数据集拆分为测试集和训练集后,我在训练集上应用了逻辑回归,但出现上述错误。我试图解决它,当我尝试在控制台中打印我的响应向量 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

与此同时,我遇到了未答复的 link。有没有解决办法。

【问题讨论】:

  • 一些备注:(1)LogisticRegression是分类,并不是真正的回归。所以你需要类 (2) Y 应该由类组成。每个样本的 1d-boolean-array 用 1 标记类别,或者每个样本的类别一个数字(例如 5 个类别 -> 数量为(0,1,2,3,4)。(3) Y 需要是整数型 -> 没有浮点数!(4) 检查你的 y_train!

标签: python-2.7 scikit-learn logistic-regression sklearn-pandas


【解决方案1】:

这里的问题是您的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。

【讨论】:

    【解决方案2】:

    我发现这是因为我的 y_test 中只有 1 或 0 结束,因为我的样本量非常小。尝试更改您的 test_size 值。

    【讨论】:

      【解决方案3】:

      我在使用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 参数。

      这并不能防止错误的发生,但它是一种增加函数使用子集中两个类的机会的方法。

      【讨论】:

        【解决方案4】:
        # 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)
        

        【讨论】:

          【解决方案5】:

          您可以找到每个类的第一次(或任何一次)出现的索引,并将它们连接到数组顶部并从它们的原始位置删除它们,这样每个类将至少有一个实例训练集。

          【讨论】:

            【解决方案6】:

            此错误与您正在使用的数据集有关,该数据集包含一个类,例如 1/benign,而它必须包含两个类 1 和 0 或 Benign 和 Attack。

            【讨论】:

            • 当样本数为1或样本只包含一个类时,会出现此问题。
            猜你喜欢
            • 2016-11-03
            • 2019-11-03
            • 2020-04-11
            • 2019-07-19
            • 2020-09-24
            • 2019-09-25
            • 2019-07-24
            • 2021-08-07
            • 2016-10-04
            相关资源
            最近更新 更多