【问题标题】:Manually replicating cross_val_score leads to strange resutls when training a toy Xgboost model在训练玩具 Xgboost 模型时,手动复制 cross_val_score 会导致奇怪的结果
【发布时间】:2021-07-29 02:34:13
【问题描述】:

在超调 XGboost 玩具模型时,我尝试复制 cross_val_score() 的结果。

我使用代码 NO.1 进行交叉验证,其结果用作基准,然后使用代码 NO.2 和 NO.3 通过手动编程交叉验证循环来复制 CV 结果。

代码 NO.2 和代码 NO.3 的主要区别在于,我将 XGboost 分类器的初始化放在了代码 NO.3 的 for 循环之外,但 放在了内部代码 NO.2 中的 for 循环。我预计只有代码 NO.2(循环内版本)产生的结果与自动 cross_val_score 得到的结果相同。令我惊讶的是,所有三个版本的代码共享相同的结果。

我的问题是:我们不应该像cross_val_score 的源代码中提到的那样为每个验证克隆模型吗?在代码 NO.3 中,经过训练的 Xgboost 模型在验证过程中不是独立的,对吧?在交叉验证的精神中,非独立性是NOT,不是吗?但是为什么我从他们那里得到了相同的结果呢?

代码 NO.1

params = {
    'objective': 'binary:logistic',
    'eval_metric': 'auc'
}
model = XGBClassifier(**params)
kfold = StratifiedKFold(n_splits=N_SPLITS, random_state=SEED)
results = cross_val_score(model, X, Y, scoring='accuracy', cv=kfold) # only a single metric is permitted. model is cloned not relay across folds.
print(f'Accuracy: {results.mean()*100:.4f}% ({results.std()*100:.3f})')

代码 NO.2

x_train = all_df.drop('Survived', axis=1).iloc[:train_rows].values 
y_train = train_label.iloc[:train_rows].values
y_oof = np.zeros(x_train.shape[0])
acc_scores = []
kfold = StratifiedKFold(n_splits=N_SPLITS, random_state=SEED)
for i, (train_index, valid_index) in enumerate(kfold.split(x_train, y_train)):
    model = XGBClassifier(**params) # <=======================================
    X_A, X_B = x_train[train_index, :], x_train[valid_index, :]
    y_A, y_B = y_train[train_index], y_train[valid_index]
    model.fit(X_A, y_A, eval_set=[(X_B, y_B)])
    y_oof[valid_index] = model.predict(X_B)
    acc_scores.append(accuracy_score(y_B, y_oof[valid_index]))

代码 NO.3

x_train = all_df.drop('Survived', axis=1).iloc[:train_rows].values 
y_train = train_label.iloc[:train_rows].values
y_oof = np.zeros(x_train.shape[0])
acc_scores = []
kfold = StratifiedKFold(n_splits=N_SPLITS, random_state=SEED)
model = XGBClassifier(**params) # <=======================================
for i, (train_index, valid_index) in enumerate(kfold.split(x_train, y_train)):
    X_A, X_B = x_train[train_index, :], x_train[valid_index, :]
    y_A, y_B = y_train[train_index], y_train[valid_index]
    model.fit(X_A, y_A, eval_set=[(X_B, y_B)])
    y_oof[valid_index] = model.predict(X_B)
    acc_scores.append(accuracy_score(y_B, y_oof[valid_index]))

【问题讨论】:

    标签: python scikit-learn cross-validation xgboost


    【解决方案1】:

    当您在 XGBClassifier 实例(或理想情况下,任何与 sklearn 兼容的估计器)上调用 fit 时,学习从头开始,因此模型在验证中确实是独立的。

    当然,重新初始化或克隆模型会稍微安全一些,尤其是在您不确定实现是否保留任何信息以供使用时。 cross_val_scorecross_validate 的包装,实际上需要克隆,以防return_estimator=True,以便保存模型的各种副本。

    【讨论】:

      猜你喜欢
      • 2016-03-15
      • 2019-11-04
      • 2023-03-20
      • 1970-01-01
      • 2021-08-03
      • 2019-09-22
      • 1970-01-01
      • 2010-11-14
      • 1970-01-01
      相关资源
      最近更新 更多