XGBoost 用于多标签分类?
Posted
技术标签:
【中文标题】XGBoost 用于多标签分类?【英文标题】:XGBoost for multilabel classification? 【发布时间】:2017-04-16 11:06:37 【问题描述】:是否可以使用 XGBoost 进行多标签分类?现在我从sklearn
使用OneVsRestClassifier
而不是GradientBoostingClassifier
。它可以工作,但只使用我 CPU 的一个内核。在我的数据中,我有大约 45 个特征,任务是用二进制(布尔)数据预测大约 20 列。指标是平均平均精度(map@7)。如果你有一个简短的代码示例要分享,那就太好了。
【问题讨论】:
你能解决这个问题吗?如果有,请提供解决方案。 【参考方案1】:一种可能的方法是使用sklearn.multioutput
模块中的MultiOutputClassifier
,而不是使用用于多类任务的OneVsRestClassifier
。
下面是一个小的可重现示例代码,其中包含 OP 请求的输入特征和目标输出的数量
import xgboost as xgb
from sklearn.datasets import make_multilabel_classification
from sklearn.model_selection import train_test_split
from sklearn.multioutput import MultiOutputClassifier
from sklearn.metrics import accuracy_score
# create sample dataset
X, y = make_multilabel_classification(n_samples=3000, n_features=45, n_classes=20, n_labels=1,
allow_unlabeled=False, random_state=42)
# split dataset into training and test set
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=123)
# create XGBoost instance with default hyper-parameters
xgb_estimator = xgb.XGBClassifier(objective='binary:logistic')
# create MultiOutputClassifier instance with XGBoost model inside
multilabel_model = MultiOutputClassifier(xgb_estimator)
# fit the model
multilabel_model.fit(X_train, y_train)
# evaluate on test data
print('Accuracy on test data: :.1f%'.format(accuracy_score(y_test, multilabel_model.predict(X_test))*100))
【讨论】:
先生,如果提供给 XGBoost 模型的数据包含缺失值怎么办?虽然我知道 xgboost 可以很好地用于二进制分类,即使数据包含缺失值,但初步尝试表明它不适用于多标签分类,当数据包含缺失值时。 恐怕无法具体帮助您。但是,我建议您在训练模型之前估算缺失值【参考方案2】:有几种方法可以做到这一点,其中一种是您已经建议的方法:
1.
from xgboost import XGBClassifier
from sklearn.multiclass import OneVsRestClassifier
# If you want to avoid the OneVsRestClassifier magic switch
# from sklearn.multioutput import MultiOutputClassifier
clf_multilabel = OneVsRestClassifier(XGBClassifier(**params))
clf_multilabel
将适合每个类一个二进制分类器,并且它将使用您在params
中指定的任意数量的内核(仅供参考,您也可以在OneVsRestClassifier
中指定n_jobs
,但这会占用更多内存)。
2。
如果您首先通过对具有k
正确标签的每个数据点制作k
副本来稍微修改您的数据,您可以破解更简单的多类问题。到时候,就
clf = XGBClassifier(**params)
clf.fit(train_data)
pred_proba = clf.predict_proba(test_data)
获取每个类别的分类边距/概率,并确定您想要预测标签的阈值。
请注意,此解决方案并不精确:如果产品具有标签 (1, 2, 3)
,则您人为地为每个类别引入了两个负样本。
【讨论】:
应该注意的是,如果你有很多标签,这可能会非常昂贵,因为它会为每个标签训练一个模型。我使用xgboost.XGBClassifier
作为底层分类器,使用 5 折交叉验证进行训练需要数小时。 @marco_ccc 谢谢你,这很有帮助。【参考方案3】:
您可以为要预测的每个类别添加标签。 例如,如果这是您的数据:
X1 X2 X3 X4 Y1 Y2 Y3
1 3 4 6 7 8 9
2 5 5 5 5 3 2
您可以根据输出通过向输入添加标签来简单地重塑数据,xgboost
应该学习如何相应地处理它,如下所示:
X1 X2 X3 X4 X_label Y
1 3 4 6 1 7
2 5 5 5 1 5
1 3 4 6 2 8
2 5 5 5 2 3
1 3 4 6 3 9
2 5 5 5 3 2
这样您将拥有一维Y
,但您仍然可以预测许多标签。
【讨论】:
这里的想法是,在测试期间,您将创建每个输入行的副本,更改 X_lable 字段并将该预测作为与 X_label 对应的标签?以上是关于XGBoost 用于多标签分类?的主要内容,如果未能解决你的问题,请参考以下文章
哪些损失函数和指标用于具有非常高的负数与正数比率的多标签分类?