Python中用XGBoost和scikit-learn进行随机梯度增强

开发 后端
在本文中,您将发现随机梯度增强以及如何使用XGBoost和Python中的scikit-learn来调整采样参数。

[[399020]]

 集成决策树的一种简单技术涉及在训练数据集的子样本上训练树。可以采用训练数据中行的子集来训练称为袋装的单个树。在计算每个分割点时,如果还使用了训练数据的行的子集,则这称为随机森林。这些技术也可以在称为随机梯度增强的技术中用于梯度树增强模型。

在本文中,您将发现随机梯度增强以及如何使用XGBoost和Python中的scikit-learn来调整采样参数。阅读这篇文章后,您将知道:

  •  在数据子样本上训练树的原理以及如何将其用于梯度增强。
  •  如何使用scikit-learn调整XGBoost中基于行的子采样。
  •  如何在XGBoost中按树和拆分点调整基于列的子采样。

随机梯度提升

梯度增强是一个贪婪的过程。将新的决策树添加到模型中,以更正现有模型的残差。使用贪婪搜索过程创建每个决策树,以选择最能最小化目标函数的分割点。这可能会导致树一次又一次使用相同的属性,甚至使用相同的分割点。

套袋是一种创建决策树集合的技术,每个决策树都来自训练数据中不同的随机行子集。效果是,由于样本的随机性允许创建略有不同的树木,因此从树的集合中获得了更好的性能,从而为集合的预测增加了方差。随机森林通过在选择分割点时对要素(列)进行二次采样,从而进一步扩大了这一步骤,从而进一步增加了树木的整体差异。这些相同的技术可以用于梯度提升中决策树的构建中,这种变化称为随机梯度提升。通常使用训练数据的激进子样本,例如40%到80%。

教程概述

在本教程中,我们将研究不同的二次采样技术在梯度增强中的作用。我们将调整Python的XGBoost库所支持的三种不同的随机梯度增强方式,特别是:

  •  创建每棵树时,对数据集中的行进行二次采样。
  •  创建每棵树时对数据集中的列进行二次采样。
  •  创建每个树时,数据集中每个拆分的列的子采样。

问题描述:Otto数据集

在本教程中,我们将使用“奥托集团产品分类挑战”数据集。该数据集可从Kaggle免费获得(您需要注册到Kaggle才能下载此数据集)。您可以从“数据”页面下载训练数据集train.csv.zip并将解压缩后的train.csv文件放入您的工作目录中。该数据集描述了61,000多种产品的93个混淆细节,这些产品分为10个产品类别(例如,时尚,电子产品等)。输入属性是某种不同事件的计数。目标是对新产品做出预测,将其作为10个类别中每一个类别的概率数组,并使用多类对数损失(也称为交叉熵)对模型进行评估。该竞赛已于2015年5月完成,并且由于示例数量不多,问题难度大,几乎不需要数据准备(除了将字符串类变量编码为整数)的事实,该数据集对于XGBoost还是一个很大的挑战。

在XGBoost中调整行二次采样

行二次抽样涉及选择训练数据集的随机样本而不进行替换。可以在subsample参数的XGBoost类的scikit-learn包装器中指定行子采样。默认值为1.0,该值不进行二次采样。我们可以使用scikit-learn中内置的网格搜索功能来评估从0.1到1.0的不同子样本值对Otto数据集的影响。 

  1. [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.0] 

子样本有9个变体,每个模型将使用10倍交叉验证进行评估,这意味着需要训练和测试9×10或90个模型。

下面提供了完整的代码清单。 

  1. # XGBoost on Otto dataset, tune subsample  
  2. from pandas import read_csv  
  3. from xgboost import XGBClassifier  
  4. from sklearn.model_selection import GridSearchCV  
  5. from sklearn.model_selection import StratifiedKFold  
  6. from sklearn.preprocessing import LabelEncoder  
  7. import matplotlib  
  8. matplotlib.use('Agg')  
  9. from matplotlib import pyplot  
  10. # load data  
  11. data = read_csv('train.csv')  
  12. datadataset = data.values  
  13. # split data into X and y  
  14. X = dataset[:,0:94]  
  15. y = dataset[:,94]  
  16. # encode string class values as integers  
  17. label_encoded_y = LabelEncoder().fit_transform(y)  
  18. # grid search  
  19. model = XGBClassifier()  
  20. subsample = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.0]  
  21. param_grid = dict(subsamplesubsample=subsample)  
  22. kfold = StratifiedKFold(n_splits=10shuffle=Truerandom_state=7 
  23. grid_search = GridSearchCV(model, param_grid, scoring="neg_log_loss"n_jobs=-1, cv=kfold 
  24. grid_result = grid_search.fit(X, label_encoded_y)  
  25. # summarize results  
  26. print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))  
  27. means = grid_result.cv_results_['mean_test_score']  
  28. stds = grid_result.cv_results_['std_test_score']  
  29. params = grid_result.cv_results_['params']  
  30. for mean, stdev, param in zip(means, stds, params):  
  31.  print("%f (%f) with: %r" % (mean, stdev, param))  
  32. # plot  
  33. pyplot.errorbar(subsample, means, yerr=stds 
  34. pyplot.title("XGBoost subsample vs Log Loss")  
  35. pyplot.xlabel('subsample')  
  36. pyplot.ylabel('Log Loss')  
  37. pyplot.savefig('subsample.png') 

运行此示例将打印最佳配置以及每个测试配置的日志丢失。

注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能会有所不同。考虑运行该示例几次并比较平均结果。

我们可以看到,获得的最佳结果是0.3,或者使用30%的训练数据集样本训练树。 

  1. Best: -0.000647 using {'subsample': 0.3}  
  2. -0.001156 (0.000286) with: {'subsample': 0.1}  
  3. -0.000765 (0.000430) with: {'subsample': 0.2}  
  4. -0.000647 (0.000471) with: {'subsample': 0.3}  
  5. -0.000659 (0.000635) with: {'subsample': 0.4}  
  6. -0.000717 (0.000849) with: {'subsample': 0.5}  
  7. -0.000773 (0.000998) with: {'subsample': 0.6}  
  8. -0.000877 (0.001179) with: {'subsample': 0.7}  
  9. -0.001007 (0.001371) with: {'subsample': 0.8}  
  10. -0.001239 (0.001730) with: {'subsample': 1.0} 

我们可以绘制这些均值和标准偏差对数损失值,以更好地了解性能如何随子样本值变化。

我们可以看到确实有30%的人具有最佳的平均表现,但是我们也可以看到,随着比率的增加,表现的差异会明显增加。有趣的是,所有子样本值的平均性能都优于不进行子抽样的平均性能(子样本= 1.0)。

在XGBoost中按树调整列二次采样

我们还可以在增强模型中创建每个决策树之前,创建要使用的特征(或列)的随机样本。在scikit-learn的XGBoost包装器中,这由colsample_bytree参数控制。默认值为1.0,表示在每个决策树中使用所有列。我们可以在0.1到1.0之间评估colsample_bytree的值,以0.1为增量。 

  1. [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.0] 

完整实例如下: 

  1. # XGBoost on Otto dataset, tune colsample_bytree  
  2. from pandas import read_csv  
  3. from xgboost import XGBClassifier  
  4. from sklearn.model_selection import GridSearchCV  
  5. from sklearn.model_selection import StratifiedKFold  
  6. from sklearn.preprocessing import LabelEncoder  
  7. import matplotlib  
  8. matplotlib.use('Agg')  
  9. from matplotlib import pyplot  
  10. # load data  
  11. data = read_csv('train.csv')  
  12. datadataset = data.values  
  13. # split data into X and y  
  14. X = dataset[:,0:94]  
  15. y = dataset[:,94]  
  16. # encode string class values as integers  
  17. label_encoded_y = LabelEncoder().fit_transform(y)  
  18. # grid search  
  19. model = XGBClassifier()  
  20. colsample_bytree = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.0]  
  21. param_grid = dict(colsample_bytreecolsample_bytree=colsample_bytree)  
  22. kfold = StratifiedKFold(n_splits=10shuffle=Truerandom_state=7 
  23. grid_search = GridSearchCV(model, param_grid, scoring="neg_log_loss"n_jobs=-1, cv=kfold 
  24. grid_result = grid_search.fit(X, label_encoded_y)  
  25. # summarize results  
  26. print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))  
  27. means = grid_result.cv_results_['mean_test_score']  
  28. stds = grid_result.cv_results_['std_test_score']  
  29. params = grid_result.cv_results_['params']  
  30. for mean, stdev, param in zip(means, stds, params):  
  31.  print("%f (%f) with: %r" % (mean, stdev, param))  
  32. # plot  
  33. pyplot.errorbar(colsample_bytree, means, yerr=stds 
  34. pyplot.title("XGBoost colsample_bytree vs Log Loss")  
  35. pyplot.xlabel('colsample_bytree')  
  36. pyplot.ylabel('Log Loss')  
  37. pyplot.savefig('colsample_bytree.png') 

运行此示例将打印最佳配置以及每个测试配置的日志丢失。

注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能会有所不同。

我们可以看到,模型的最佳性能是colsample_bytree = 1.0。这表明该问题进行二次采样不会增加价值。 

  1. Best: -0.001239 using {'colsample_bytree': 1.0}  
  2. -0.298955 (0.002177) with: {'colsample_bytree': 0.1}  
  3. -0.092441 (0.000798) with: {'colsample_bytree': 0.2}  
  4. -0.029993 (0.000459) with: {'colsample_bytree': 0.3}  
  5. -0.010435 (0.000669) with: {'colsample_bytree': 0.4}  
  6. -0.004176 (0.000916) with: {'colsample_bytree': 0.5}  
  7. -0.002614 (0.001062) with: {'colsample_bytree': 0.6}  
  8. -0.001694 (0.001221) with: {'colsample_bytree': 0.7}  
  9. -0.001306 (0.001435) with: {'colsample_bytree': 0.8}  
  10. -0.001239 (0.001730) with: {'colsample_bytree': 1.0} 

绘制结果,我们可以看到模型平稳段的性能(至少在此比例下),值为0.5到1.0。

通过拆分在XGBoost中调整列二次采样

不必为每个树对列进行一次子采样,我们可以在决策树的每个拆分中对它们进行子采样。原则上,这是随机森林中使用的方法。我们可以在scikit-learn的XGBoost包装器类的colsample_bylevel参数中设置每个拆分所使用的列样本的大小。和以前一样,我们将比率从10%更改为默认值100%。

下面提供了完整的代码清单。 

  1. # XGBoost on Otto dataset, tune colsample_bylevel  
  2. from pandas import read_csv  
  3. from xgboost import XGBClassifier  
  4. from sklearn.model_selection import GridSearchCV  
  5. from sklearn.model_selection import StratifiedKFold  
  6. from sklearn.preprocessing import LabelEncoder  
  7. import matplotlib  
  8. matplotlib.use('Agg')  
  9. from matplotlib import pyplot  
  10. # load data  
  11. data = read_csv('train.csv')  
  12. datadataset = data.values  
  13. # split data into X and y  
  14. X = dataset[:,0:94]  
  15. y = dataset[:,94]  
  16. # encode string class values as integers  
  17. label_encoded_y = LabelEncoder().fit_transform(y)  
  18. # grid search  
  19. model = XGBClassifier()  
  20. colsample_bylevel = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1.0]  
  21. param_grid = dict(colsample_bylevelcolsample_bylevel=colsample_bylevel)  
  22. kfold = StratifiedKFold(n_splits=10shuffle=Truerandom_state=7 
  23. grid_search = GridSearchCV(model, param_grid, scoring="neg_log_loss"n_jobs=-1, cv=kfold 
  24. grid_result = grid_search.fit(X, label_encoded_y)  
  25. # summarize results  
  26. print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))  
  27. means = grid_result.cv_results_['mean_test_score']  
  28. stds = grid_result.cv_results_['std_test_score']  
  29. params = grid_result.cv_results_['params']  
  30. for mean, stdev, param in zip(means, stds, params):  
  31.  print("%f (%f) with: %r" % (mean, stdev, param))  
  32. # plot  
  33. pyplot.errorbar(colsample_bylevel, means, yerr=stds 
  34. pyplot.title("XGBoost colsample_bylevel vs Log Loss")  
  35. pyplot.xlabel('colsample_bylevel')  
  36. pyplot.ylabel('Log Loss')  
  37. pyplot.savefig('colsample_bylevel.png') 

运行此示例将打印最佳配置以及每个测试配置的日志丢失。

注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能会有所不同。考虑运行该示例几次并比较平均结果。

我们可以看到,通过将colsample_bylevel设置为70%可获得最佳结果,导致(倒置)对数损失为-0.001062,这比将每棵树的列采样设置为100%时看到的-0.001239好。

如果每棵树的结果建议使用100%的列,则建议不要放弃列二次采样,而应尝试按拆分的列二次采样。 

  1. Best: -0.001062 using {'colsample_bylevel': 0.7}  
  2. -0.159455 (0.007028) with: {'colsample_bylevel': 0.1}  
  3. -0.034391 (0.003533) with: {'colsample_bylevel': 0.2}  
  4. -0.007619 (0.000451) with: {'colsample_bylevel': 0.3}  
  5. -0.002982 (0.000726) with: {'colsample_bylevel': 0.4}  
  6. -0.001410 (0.000946) with: {'colsample_bylevel': 0.5}  
  7. -0.001182 (0.001144) with: {'colsample_bylevel': 0.6}  
  8. -0.001062 (0.001221) with: {'colsample_bylevel': 0.7}  
  9. -0.001071 (0.001427) with: {'colsample_bylevel': 0.8}  
  10. -0.001239 (0.001730) with: {'colsample_bylevel': 1.0} 

我们可以绘制每个colsample_bylevel变化的性能。结果表明,在此比例下的值为0.3后,方差相对较低,并且性能似乎处于平稳状态。 

 

责任编辑:庞桂玉 来源: Python中文社区 (ID:python-china)
相关推荐

2015-07-22 16:16:47

PythonScikit-Lear机器学习

2018-09-06 08:00:00

深度学习TensorFlowPython

2023-02-13 15:00:13

机器学习scikit-leaPyTorch

2018-10-15 09:10:09

Python编程语言数据科学

2023-05-26 12:45:22

predict​方法数据

2017-07-20 10:23:20

pythonscikit-lear垃圾邮件过滤

2023-11-13 18:05:53

处理数据搭建模型

2018-04-06 05:10:04

K-NN数据集算法

2017-01-05 10:07:33

大数据TheanoCaffe

2024-02-01 09:43:32

模型人工智能

2018-05-15 08:27:20

Scikit-lear机器学习Python

2017-11-03 12:57:06

机器学习文本数据Python

2017-04-21 09:59:11

开源机器学习框架

2022-04-15 10:11:03

机器学习scikit-lea

2016-12-20 16:07:13

Python数据预处理

2016-12-18 15:03:57

Python Scikit Lea数据

2023-03-27 07:34:28

XGBoostInluxDB时间序列

2021-04-16 20:46:21

PythonXGBoost 特征

2021-04-07 10:02:00

XGBoostPython代码

2023-08-11 10:58:04

深度学习自然语言检索增强
点赞
收藏

51CTO技术栈公众号