使用来自 H2O 的超参数在 Sklearn 中重新构建 XGBoost 在 Python 中提供了不同的性能

Posted

技术标签:

【中文标题】使用来自 H2O 的超参数在 Sklearn 中重新构建 XGBoost 在 Python 中提供了不同的性能【英文标题】:Using Hyper-parameters from H2O to re-build XGBoost in Sklearn gives Difference Performance in Python 【发布时间】:2019-10-30 22:56:44 【问题描述】:

使用H2O Python Module AutoML后,发现XGBoost在Leaderboard的顶部。然后我想做的是从 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()
    H2O Xgboost 的性能
skplt.metrics.plot_confusion_matrix(test_df['target'], 
                                    m.predict(test).as_data_frame()['predict'], 
                                    normalize=False)

    在 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'])
    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 【参考方案1】:

当您通过以下代码行使用 H2O auto ml 时:

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,这意味着将使用三分之二的数据作为训练数据和三分之一作为验证数据对每个算法进行三次训练。与一次性提供整个训练数据集相比,这使算法更稳定,有时性能更好。

这就是您在使用 fit() 训练 XGBoost 时所做的事情。即使您有 same 算法 (XGBoost) 和 same 超参数,您也不会像 H2O 那样使用训练集。因此,您的混淆矩阵有所不同!

如果想在复制最佳模型时也有同样的性能,可以更改参数H2OAutoML(..., nfolds = 0)


此外,H2O 考虑了大约 60 个不同的参数,您错过了字典中的一些重要参数,例如 min_child_weight。因此,您的 xgboost 与您的 H2O 并不完全相同,这可以解释性能差异

【讨论】:

非常感谢您指出训练步骤的差异。即使更改为H2OAutoML(..., nfolds = 0) 后,仍然存在细微的性能差异。然而,更重要的是,如何让 sklearn-xgboost 的训练步骤与 H2O 相似,而不是像 sklearn 那样downgrade H2O。要做到这一点,调用xgb_clf.fit(train_df.drop('target', axis=1), train_df['target']) 三次就足够了吗? 拟合三次是行不通的,因为在使用 k-fold 操作时将训练集分成三份。所以你必须得到与 H2O 完全相同的三折。您可以尝试使用keep_cross_validation_fold_assignment = True 选项来保留它们。 您是否尝试转移您的 H2O xgboost 模型@B.Sun 的所有功能?在您的示例中,您只转移了 10 个 您介意更具体地了解“传输功能”吗?你是说'asfactor'吗? 对不起,我不是很清楚,我的意思是修复 XGBoost 中的所有参数,使其与您的 h2o 模型中的相同。您对某些参数进行了此操作,但并非针对所有参数。例如,您没有将 XGBoost 模型中的 min_child_weight 参数修复为与您的 h2o 模型相同

以上是关于使用来自 H2O 的超参数在 Sklearn 中重新构建 XGBoost 在 Python 中提供了不同的性能的主要内容,如果未能解决你的问题,请参考以下文章

StackingRegressor sklearn 的超参数调优

Sklearn:使用预训练的超参数高斯过程回归

网格搜索 SVM-anova 的超参数并在 Sklearn 中获得选择的特征

机器学习-kNN-寻找最好的超参数

随机森林中的超参数调整

有效地将 pandas 数据帧转换为 h2o 帧