【问题标题】:Multiclass classification with xgboost classifier?使用 xgboost 分类器进行多类分类?
【发布时间】:2020-01-19 00:38:49
【问题描述】:

我正在尝试使用 xgboost 进行多类分类,并使用此代码构建了它,

clf = xgb.XGBClassifier(max_depth=7, n_estimators=1000)

clf.fit(byte_train, y_train)
train1 = clf.predict_proba(train_data)
test1 = clf.predict_proba(test_data)

这给了我一些很好的结果。对于我的情况,我的对数损失低于 0.7。但是在浏览了几页之后,我发现我们必须在 XGBClassifier 中使用另一个目标来解决多类问题。以下是这些页面的推荐内容。

clf = xgb.XGBClassifier(max_depth=5, objective='multi:softprob', n_estimators=1000, 
                        num_classes=9)

clf.fit(byte_train, y_train)  
train1 = clf.predict_proba(train_data)
test1 = clf.predict_proba(test_data)

这段代码也可以工作,但与我的第一个代码相比,它需要很长时间才能完成。

为什么我的第一个代码也适用于多类案例?我已经检查过它的默认目标是二进制:逻辑用于二进制分类,但它对多类效果真的很好吗?如果两者都正确,我应该使用哪一个?

【问题讨论】:

  • 与不同的目标无关,但对于 softprob,与 n_jobs 的隐藏默认值相比,添加并行/线程参数 n_jobs=-1 是否会加快 fitter =1?

标签: python machine-learning scikit-learn xgboost


【解决方案1】:

默认情况下,XGBClassifier 使用objective='binary:logistic'。当您使用此目标时,它会采用以下任一策略:one-vs-rest(也称为 one-vs-all)和 one-vs-one。它可能不是您手头问题的正确选择。

当您使用objective='multi:softprob' 时,输出是数据点数 * 类数的向量。因此,代码的时间复杂度会增加。

尝试在您的代码中设置objective=multi:softmax。更适合多类分类任务。

【讨论】:

  • 谢谢,但是对于多类问题,哪个目标最常用/首选? binary:logistic 还是 multi:softmax?另外你能告诉我你为什么提到that it may not be the right choice for my problem吗?
【解决方案2】:

默认情况下,XGBClassifier 或许多分类器使用objective 作为binary,但它在内部做的是分类(一个 vs 休息),即如果你有 3 个类,它会给出结果为(0 vs 1&2)。如果您要处理的类别超过 2 个,则应始终使用 softmax。Softmax 将 logits 转换为总和为 1 的概率。在此基础上,它预测哪些类别的概率最高。正如您所见,Saurabh 在他的回答中提到了复杂性的增加,因此需要更多时间。

【讨论】:

  • 但是如果我们也可以使用 onevsrest 来实现结果,那么为什么要选择 softmax 目标呢?它总是比 onevsrest 方法提高准确性吗?
  • One Vs rest 将训练两个分类器,而 softmax 将训练 n 个类。假设您有 3 个类 x1,x2,x3 。在 one vs rest 中,它将 x1 作为一个类和 (x2,x3) 作为另一个类,它是一个二元分类器,但在 softmax 中它将训练 3 个不同的类。您将在其中获得 3 种不同的概率,而在 1 与休息中获得 2 种概率。
  • 这两个目标都返回了 n 类的概率,对吧?所以我们可以使用任何一种方法。不是吗?
  • 如果在 3 个类中你只对两个类感兴趣,比如说正面和负面,那么你可以使用一个 vs 休息,否则 softmax 是首选。假设你有五个类,正面,负面,有点正面,有点负面,中性。在这里,您可以选择 One Vs rest,因为您可以将正面和中性合并为一个并且可以进行预测,但是如果您想要所有类的概率,那么 softmax 是一种方法。我希望你得到它。:)
  • 但即使使用 OneVsRest,我们也可以使用 xgboost.predict_proba() 访问概率,不是吗?
【解决方案3】:

其实即使XGBClassifier的默认obj参数是binary:logistic,它内部也会判断标签y的类数。当类号大于2时,会将obj参数修改为multi:softmax

https://github.com/dmlc/xgboost/blob/master/python-package/xgboost/sklearn.py

class XGBClassifier(XGBModel, XGBClassifierBase):
    # pylint: disable=missing-docstring,invalid-name,too-many-instance-attributes
    def __init__(self, objective="binary:logistic", **kwargs):
        super().__init__(objective=objective, **kwargs)

    def fit(self, X, y, sample_weight=None, base_margin=None,
            eval_set=None, eval_metric=None,
            early_stopping_rounds=None, verbose=True, xgb_model=None,
            sample_weight_eval_set=None, callbacks=None):
        # pylint: disable = attribute-defined-outside-init,arguments-differ

        evals_result = {}
        self.classes_ = np.unique(y)
        self.n_classes_ = len(self.classes_)

        xgb_options = self.get_xgb_params()

        if callable(self.objective):
            obj = _objective_decorator(self.objective)
            # Use default value. Is it really not used ?
            xgb_options["objective"] = "binary:logistic"
        else:
            obj = None

        if self.n_classes_ > 2:
            # Switch to using a multiclass objective in the underlying
            # XGB instance
            xgb_options['objective'] = 'multi:softprob'
            xgb_options['num_class'] = self.n_classes_

【讨论】:

  • 目前,这是正确的答案。接受的答案具有误导性。
猜你喜欢
  • 1970-01-01
  • 2017-08-01
  • 2017-10-20
  • 2018-05-02
  • 2020-07-11
  • 2017-09-27
  • 2018-09-03
  • 1970-01-01
相关资源
最近更新 更多