【问题标题】:Typeerror with VotingClassifier带有 VotingClassifier 的类型错误
【发布时间】:2018-09-20 13:20:24
【问题描述】:

我想使用 VotingClassifier,但我在交叉验证方面遇到了一些问题

    x_train, x_validation, y_train, y_validation = train_test_split(x, y, test_size=.22, random_state=2)
    x_train = x_train.fillna(0)
    clf1 = CatBoostClassifier()
    clf2 = RandomForestClassifier()
    clf = VotingClassifier(estimators=[('cb', clf1), ('rf', clf2)])
    clf.fit(x_train.values(), y_train)

我的预测有误...

    cross_validate(clf, x_train, y_train, scoring='accuracy', return_train_score = True, n_jobs = 4)

TypeError: Cannot cast array data from dtype('float64') to dtype('int64') according to the rule 'safe'

(完全错误here


并在此处下载 x_train 和 y_train ↓

x_train
y_train

【问题讨论】:

    标签: python-3.x numpy scikit-learn typeerror catboost


    【解决方案1】:

    这个错误是因为这行:

    np.bincount(x, weights=self._weights_not_none)
    

    这里的x 是 VotingClassifier 中各个分类器返回的预测。

    根据np.bincount的文档:

    计算非负数组中每个值的出现次数 整数。

    x:array_like,一维,非负整数

    此方法只需要数组中的 int 值。

    现在,如果您将 CatBoostClassifier 替换为任何其他 Scikit-learn 分类器,您的代码将可以正常工作。因为所有 scikit-learn 估计器都从它们的 predict() 返回数组 np.int64

    但是 CatBoostClassifier 返回 np.float64 作为输出。因此错误。实际上它也应该返回 int64 因为predict() 函数应该返回类而不是任何浮点值。但我不知道为什么它返回浮动。

    您可以通过扩展 CatBoostClassifier 类并即时转换预测来纠正此问题。

    import numpy as np
    from catboost import CatBoostClassifier
    class CatBoostClassifierInt(CatBoostClassifier):
        def predict(self, data, prediction_type='Class', ntree_start=0, ntree_end=0, thread_count=1, verbose=None):
            predictions = self._predict(data, prediction_type, ntree_start, ntree_end, thread_count, verbose)
    
            # This line is the only change I did
            return np.asarray(predictions, dtype=np.int64).ravel()
    
    clf1 = CatBoostClassifierInt()
    clf2 = RandomForestClassifier()
    clf = VotingClassifier(estimators=[('cb', clf1), ('rf', clf2)])
    cross_validate(clf, x_train, y_train, scoring='accuracy', return_train_score = True)
    

    现在你不会得到那个错误了。

    更正确的版本应该是这个。这将处理具有匹配输入和输出的所有类型的标签,并且可以轻松地在 scikit 中使用:

    class CatBoostClassifierCorrected(CatBoostClassifier):
        def fit(self, X, y=None, cat_features=None, sample_weight=None, baseline=None, use_best_model=None,
            eval_set=None, verbose=None, logging_level=None, plot=False, column_description=None, verbose_eval=None):
    
            self.le_ = LabelEncoder().fit(y)
            transformed_y = self.le_.transform(y)
    
            self._fit(X, transformed_y, cat_features, None, sample_weight, None, None, None, baseline, use_best_model, eval_set, verbose, logging_level, plot, column_description, verbose_eval)
            return self
    
        def predict(self, data, prediction_type='Class', ntree_start=0, ntree_end=0, thread_count=1, verbose=None):
            predictions = self._predict(data, prediction_type, ntree_start, ntree_end, thread_count, verbose)
    
            # This line is the only change I did
            return self.le_.inverse_transform(predictions.astype(np.int64))
    

    这将处理所有不同类型的标签

    【讨论】:

      猜你喜欢
      • 2022-11-10
      • 2017-11-17
      • 2019-04-27
      • 2020-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-06
      • 1970-01-01
      相关资源
      最近更新 更多