XGBoost 中的相同预测

Identical predictions in XGBoost

当我过去使用 XGBoost 进行回归时,我得到了不同的预测,但是在这个数据集上使用 XGBClassifier 会导致所有情况都被预测为具有相同的值。测试数据的真实值是 221 个案例是 0,49 个案例是 1。XGBoost 似乎抓住了这种不平衡并预测全 0。我想弄清楚我可能需要在模型的参数中调整什么来解决这个问题。

这是我运行宁的代码:

import pyreadstat
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# Get data
dfloc = r"C:\Users\me\Desktop\Python practice\GBM_data.sav"
df, meta = pyreadstat.read_sav(dfloc, metadataonly=False)

# Filter data
df = df.dropna(subset=["Q31ar1"])
df = df.query("hgroup2==3")
IVs = ["Q35r1", "Q35r2", "Q35r3", "Q35r4", "Q35r5", "Q35r6", "Q35r7", "Q35r8", "Q35r9", "Q35r10", "Q35r11", "Q35r13", "Q35r14", "Q35r15", "Q35r16"]

# Separate samples
train, test = train_test_split(df, test_size=0.3, random_state=410)

train_features = train[IVs]
train_labels = train["Q31ar1"]
train_weight = train["WeightStack"]

test_features = test[IVs]
test_labels = test["Q31ar1"]
test_weight = test["WeightStack"]

# Set up model & params
model = XGBClassifier(objective = 'binary:logistic',
                     n_estimators = 1000,
                     learning_rate = .005,
                     subsample = .5,
                     max_depth = 4,
                     min_child_weight = 10,
                     tree_method = 'hist',
                     colsample_bytree = .5,
                     random_state = 410)

# Model
model.fit(train_features, train_labels, sample_weight = train_weight)
test_pred = model.predict(test_features)

通过一些相关问题,似乎有些人在他们的模型没有经过足够的提升迭代方面遇到了麻烦。我 运行 正在通过 1000,这在过去已经足够回归了。别人参数设置不对,我运行model.get_params()时,我的好像设置好了;这是输出:

{'base_score': 0.5,
 'booster': 'gbtree',
 'colsample_bylevel': 1,
 'colsample_bynode': 1,
 'colsample_bytree': 0.5,
 'gamma': 0,
 'learning_rate': 0.005,
 'max_delta_step': 0,
 'max_depth': 4,
 'min_child_weight': 10,
 'missing': None,
 'n_estimators': 1000,
 'n_jobs': 1,
 'nthread': None,
 'objective': 'binary:logistic',
 'random_state': 410,
 'reg_alpha': 0,
 'reg_lambda': 1,
 'scale_pos_weight': 1,
 'seed': None,
 'silent': None,
 'subsample': 0.5,
 'verbosity': 1,
 'tree_method': 'hist'}

其他人遇到缩放问题。我的预测变量都按照相同的方式缩放——它们是有序的评级尺度,值为 1、2、3、4 和 5。还有其他人遇到过 NaN 的问题,但我正在过滤我的数据以删除 NaN .

我想知道我是否需要不同的树方法或乱用 base_score 参数?

编辑:Per Dan 的评论,我尝试了一些事情:

  1. 我对我的 train/test 拆分进行了分层,它并没有发生实质性变化——219 个 0 和 51 个 1。训练样本有 507 个 0 和 120 个 1,因此它们的分布大致均匀。我知道这是一个小数据集,但我是一名调查研究员,所以这就是我所拥有的。
  2. 我尝试了逻辑回归,得到了相同的预测:全为 0。代码:
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression(random_state=0).fit(train_features, train_labels)
test_pred_log = clf.predict(test_features)
accuracy_log = clf.score(test_features, test_labels)
  1. 我查看了 XGBoost 模型对我的训练数据的预测,它们也都是 0,所以 ROC 曲线没有显示太多,但是查看训练预测是一个很好的建议.逻辑模型有相同的训练预测:都是0.
train_pred = model.predict(train_features)
fpr, tpr, thresholds = roc_curve(train_labels, train_pred, pos_label=1)
  1. 我不知道我可以获得概率估计,所以感谢你在 pred_proba 上的提示。我的概率估计 有区别的,太好了!属于 class 1 的概率都比较低——平均在 20% 左右,这是有道理的,因为大约 20% 的样本确实属于 class 1。问题是我不知道不知道如何调整预测的阈值。我想我可以使用 pred_proba 的结果手动完成,但是有没有办法将其用于估算器?

在统计部分找到答案:https://stats.stackexchange.com/questions/243207/what-is-the-proper-usage-of-scale-pos-weight-in-xgboost-for-imbalanced-datasets

scale_pos_weight 似乎是一个参数,您可以像这样调整以处理 类 中的不平衡。我的设置为默认值 1,这意味着负 (0) 和正 (1) 案例被假定为均匀显示。如果我将其更改为 4,这是我的负数与正数之比,我开始看到预测为 1 的案例。

我的准确性分数下降了,但这是有道理的:通过预测每个人都为 0,您可以使用此数据获得更高的准确性百分比,因为绝大多数情况下都是 0,但我想 运行 这个模型不是为了准确性而是关于每个预测变量的 importances/contributions 的信息,所以我想要不同的预测。

link 中的一个答案还建议通过将 scale_pos_weight 设置为比率的平方来更加保守,在本例中为 2。 2 比 4 的精度更高,所以这就是我要使用的,我计划在未来的分类模型中研究这个参数。

对于 multi-class 模型,您最好调整 case-level 权重以使 类 达到均匀表示,如下所述:https://datascience.stackexchange.com/questions/16342/unbalanced-multiclass-data-with-xgboost