xgboost predict 方法为所有行返回相同的预测值
Posted
技术标签:
【中文标题】xgboost predict 方法为所有行返回相同的预测值【英文标题】:xgboost predict method returns the same predicted value for all rows 【发布时间】:2016-02-01 21:57:21 【问题描述】:我在 Python 中创建了一个 xgboost 分类器:
train 是一个 pandas 数据框,有 100k 行和 50 个特征作为列。 目标是熊猫系列
xgb_classifier = xgb.XGBClassifier(nthread=-1, max_depth=3, silent=0,
objective='reg:linear', n_estimators=100)
xgb_classifier = xgb_classifier.fit(train, target)
predictions = xgb_classifier.predict(test)
但是,在训练之后,当我使用这个分类器来预测值时,整个结果数组是相同的数字。知道为什么会这样吗?
数据说明: ~50 个带有数字目标的数字特征
我也用相同的数据尝试过来自 sklearn 的RandomForestRegressor
,它确实给出了现实的预测。可能是 xgboost 实现中的一个合法错误?
【问题讨论】:
您的数据是什么样的?模型返回的“相同数字”是多少? 类似-0.1236788。它在预期结果的范围内,但不同的行应该有不同的预测值,这个数字填满了整个预测数组 ~ 1000 行 你能分享一下你如何调用训练函数以及如何填充训练矩阵的代码吗?训练集中有正面和负面的例子吗? 我已经添加了代码。是的,训练集中既有正值也有负值。 【参考方案1】:max_depth =3 不会太小,试着把它变大,如果我没记错的话,默认值为 7。并将silent设置为1,然后您可以监控每个epochs的错误是什么
【讨论】:
【参考方案2】:您需要发布一个可重现的示例以进行任何实际调查。您的响应目标很可能是高度不平衡的,并且您的训练数据不是超级预测,因此您总是(或几乎总是)得到一个预测的类。你有没有看过预测的概率,看看是否有任何差异?只是没有对分类标签使用正确的截止值吗?
既然您说 RF 给出了合理的预测,那么查看您的训练参数会很有用。乍一看,很好奇为什么您在 xgboost 调用中使用回归目标函数——这很可能就是您看到如此糟糕的性能的原因。尝试将您的目标更改为:'binary:logistic
。
【讨论】:
【参考方案3】:其中一个原因是您通过参数 gamma 提供了高惩罚。比较您的训练响应变量的平均值并检查预测是否接近此值。如果是,则模型对预测的限制过多,以使 train-rmse 和 val-rmse 尽可能接近。您的预测是最简单的,具有更高的 gamma 值。所以你会得到最简单的模型预测,比如训练集的平均值作为预测或朴素预测。
【讨论】:
【参考方案4】:此问题已收到多个回复,包括此主题以及 here 和 here。
我在使用 XGBoost 和 LGBM 时遇到了类似的问题。对我来说,解决方案是增加训练数据集的大小。
我在本地机器上使用大型稀疏数据集(200,000 行和 7000 列)的随机样本 (~0.5%) 进行训练,因为我没有足够的本地内存用于该算法。事实证明,对我来说,预测值数组只是目标变量平均值的数组。这向我表明该模型可能欠拟合。欠拟合模型的一种解决方案是在更多数据上训练模型,因此我尝试在具有更多内存的机器上进行分析,问题得到解决:我的预测数组不再是平均目标值数组。另一方面,问题可能只是我正在查看的预测值切片是根据训练数据预测的,信息非常少(例如 0 和 nan)。对于信息很少的训练数据,预测目标特征的平均值似乎是合理的。
我遇到的其他建议解决方案都对我没有帮助。总结一些建议的解决方案包括: 1)检查伽玛是否太高 2)确保您的目标标签不包含在您的训练数据集中 3) max_depth 可能太小了。
【讨论】:
在我的例子中,我在 y 变量中有一个空值;我刚刚使用了 .fillna(0) 并且它起作用了@Blane【参考方案5】:我已经尝试了此页面上的所有解决方案,但没有一个有效。
当我对时间序列进行分组时,某些频率会造成数据空白。 我通过填充所有 NaN 解决了这个问题。
【讨论】:
【参考方案6】:您使用的超参数可能会导致错误。尝试使用默认值。就我而言,这个问题是通过从 params 中删除 subsample
和 min_child_weight
超参数来解决的。
【讨论】:
【参考方案7】:您应该检查目标中没有 inf
值。
【讨论】:
【参考方案8】:尝试在 XGBoost 中增加(显着)min_child_weight
或在 LightGBM 中增加 min_data_in_leaf
:
min_data_in_leaf oof_rmse
20000 0.052998
2000 0.053001
200 0.053002
20 0.053015
2 0.054261
其实可能是过拟合掩蔽为欠拟合的情况。例如,在保险索赔频率模型的情况下,零膨胀目标就会发生这种情况。一种解决方案是通过将控制最小叶大小的超参数增加到一些相当大的值(例如上面示例中指定的值)来增加每个树叶中稀有目标级别(例如非零保险索赔)的表示/覆盖率。
【讨论】:
【参考方案9】:我刚刚遇到了这个问题并设法解决了它。问题是我在tree_method='gpu_hist'
上进行训练,它给出了所有相同的预测。如果我设置 tree_method='auto'
它可以正常工作,但运行时间更长。因此,如果我将tree_method='gpu_hist'
与base_score=0
一起设置,它就可以工作。我认为base_score
应该是您预测变量的平均值。
【讨论】:
以上是关于xgboost predict 方法为所有行返回相同的预测值的主要内容,如果未能解决你的问题,请参考以下文章
xgboost : TypeError: predict() got an unexpected keyword argument 'pred_contribs'
model.apply(x) 结果的 xgboost 总和不等于 model.predict(x)
使用 Scikit-Learn API 时如何调整 XGBoost 分类器中的概率阈值
ValueError: feature_names mismatch: in xgboost in the predict() function