使用来自H2O的超参数在Sklearn中重新构建XGBoost在Python中给出了不同的性能表现

7
使用H2O Python模块AutoML后,发现XGBoost位于排行榜的首位。然后我尝试从H2O XGBoost中提取超参数,并在XGBoost Sklearn API中进行复制。但是,这两种方法的性能不同:

from sklearn import datasets
from sklearn.model_selection import train_test_split, cross_val_predict
from sklearn.metrics import classification_report

import xgboost as xgb
import scikitplot as skplt
import h2o
from h2o.automl import H2OAutoML
import numpy as np
import pandas as pd

h2o.init()


iris = datasets.load_iris()
X = iris.data
y = iris.target

data = pd.DataFrame(np.concatenate([X, y[:,None]], axis=1)) 
data.columns = iris.feature_names + ['target']
data = data.sample(frac=1)
# data.shape

train_df = data[:120]
test_df = data[120:]

# Import a sample binary outcome train/test set into H2O
train = h2o.H2OFrame(train_df)
test = h2o.H2OFrame(test_df)

# Identify predictors and response
x = train.columns
y = "target"
x.remove(y)

# For binary classification, response should be a factor
train[y] = train[y].asfactor()
test[y] = test[y].asfactor()

aml = H2OAutoML(max_models=10, seed=1, nfolds = 3,
                keep_cross_validation_predictions=True,
                exclude_algos = ["GLM", "DeepLearning", "DRF", "GBM"])
aml.train(x=x, y=y, training_frame=train)
# View the AutoML Leaderboard
lb = aml.leaderboard
lb.head(rows=lb.nrows)

model_ids = list(aml.leaderboard['model_id'].as_data_frame().iloc[:,0])
m = h2o.get_model([mid for mid in model_ids if "XGBoost" in mid][0])
# m.params.keys()
  1. H2O Xgboost的性能
skplt.metrics.plot_confusion_matrix(test_df['target'], 
                                    m.predict(test).as_data_frame()['predict'], 
                                    normalize=False)

输入图像描述

  1. 在XGBoost Sklearn API中复制:
mapping_dict = {
        "booster": "booster",
        "colsample_bylevel": "col_sample_rate",
        "colsample_bytree": "col_sample_rate_per_tree",
        "gamma": "min_split_improvement",
        "learning_rate": "learn_rate",
        "max_delta_step": "max_delta_step",
        "max_depth": "max_depth",
        "min_child_weight": "min_rows",
        "n_estimators": "ntrees",
        "nthread": "nthread",
        "reg_alpha": "reg_alpha",
        "reg_lambda": "reg_lambda",
        "subsample": "sample_rate",
        "seed": "seed",

        # "max_delta_step": "score_tree_interval",
        #  'missing': None,
        #  'objective': 'binary:logistic',
        #  'scale_pos_weight': 1,
        #  'silent': 1,
        #  'base_score': 0.5,
}

parameter_from_water = {}
for item in mapping_dict.items():
    parameter_from_water[item[0]] = m.params[item[1]]['actual']
# parameter_from_water

xgb_clf = xgb.XGBClassifier(**parameter_from_water)
xgb_clf.fit(train_df.drop('target', axis=1), train_df['target'])
  1. Sklearn XGBoost的性能:
    (在我尝试的所有示例中,性能始终比H2O差.)
skplt.metrics.plot_confusion_matrix(test_df['target'], 
                                    xgb_clf.predict(test_df.drop('target', axis=1)  ), 
                                    normalize=False);

在此输入图片描述

是否有任何明显的遗漏?


我尝试了你的代码,每次都得到相同的结果。在使用H2O训练和XGBoost之前,你是否修改了train_dftest_df - Yuan JI
1个回答

6
当您使用以下代码行与H2O auto ml:

当您使用以下代码行与H2O自动机器学习:

aml = H2OAutoML(max_models=10, seed=1, nfolds = 3,
                keep_cross_validation_predictions=True,
                exclude_algos = ["GLM", "DeepLearning", "DRF", "GBM"])
aml.train(x=x, y=y, training_frame=train)

您使用选项nfolds = 3,这意味着每个算法将使用2/3的数据作为训练数据,1/3作为验证数据进行三次训练。这使得算法更加稳定,有时比您一次性提供整个训练数据集表现更好。
这是使用fit()训练XGBoost的方法。即使您具有相同的算法(XGBoost)和相同的超参数,您也不会像H2O那样使用训练集。因此,在混淆矩阵方面存在差异!
如果要在复制最佳模型时获得相同的性能,则可以更改参数H2OAutoML(..., nfolds = 0) 此外,H2O考虑了大约60个不同的参数,您在字典中错过了一些重要的参数,比如min_child_weight。因此,您的XGBoost与H2O不完全相同,这可能解释了性能差异。

非常感谢您指出训练步骤的差异。即使更改为 H2OAutoML(..., nfolds = 0),仍然存在轻微的性能差异。然而,更重要的是如何使 sklearn-xgboost 的训练步骤与 H2O 的类似,而不是将 H2O 降级为 sklearn 的样式。为了实现这一点,调用 xgb_clf.fit(train_df.drop('target', axis=1), train_df['target']) 三次是否足够? - B. Sun
三次拟合不起作用,因为在使用k折操作时,将训练集分成了三个部分。所以你必须得到与H2O相同的三个部分。你可以尝试选项keep_cross_validation_fold_assignment = True来保留它们。 - vlemaistre
你是否尝试将你的H2O xgboost模型的所有特征转移?@B.Sun。在你的示例中,你只转移了10个。 - vlemaistre
您能具体说明一下“传输特征”是指什么吗?您是指‘asfactor’吗? - B. Sun
抱歉我表达不够清晰,我的意思是将XGBoost中的所有参数都固定为与您的h2o模型相同。您已经对一些参数进行了调整,但并非全部。例如,在您的XGBoost模型中,您没有将“min_child_weight”参数固定为与您的h2o模型相同。 - vlemaistre
@B.Sun,你有没有尝试过vlemaistre的建议,将所有参数从h2o映射到sklearn? - HaveF

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接