集成决策树的一种简单技术涉及在训练数据集的子样本上训练树。可以采用训练数据中行的子集来训练称为袋装的单个树。在计算每个分割点时,如果还使用了训练数据的行} V # J l T的子集,则这称为] X Q A随机森林。这些技术也可以在称为随机梯度增强的技术中, G U l *用于梯度树增强模型。
在本文中,您将发现随机梯度增强以及如何使用XGBoost和Python中的scikit-learn来调整采_ k % p样参数。阅读这篇文章O M 7 G 0 G后,您将知道:
- 在数据子样本上训练树的原理以及如何将其用于梯度增强。
- 如何使h f Y用scikit-learn调整XGBoost中基于行的子采样。
- 如何在XGBoost中按树和拆分点调整基于列的子采样。d 3 ! O ! % I
随机梯度提升
梯度增强是一个贪婪的过程。将新的决策树添加到模型中,以更正现有模型的残差` b I | 9 . G *。使用贪婪搜索过程创建每个决策树,以选择最能最小化目标函数的分割点。这可能会导致树一次又一次使用相同的属性,甚至使用相同的分割点。
套袋是一种创建决策树集合r ` 4 G q的技术,每个决策树都来自训练数据中不同的随机行子集。效果是,由于样本的随机性允许创建略有不同的树木,因此从树的集合中获得了更好的性能,从而为集合的预测增加了方差。随机森林通过在选择分割点时对要素(列)进行二次采样,从而进一步扩大了这一步骤,从而进一步增加了树木的整体差异。这些相同的技术可以用于梯度提升中决策树的构建中,这种变化称为随机梯度提升– J . Z @ x O j d。通常使用训练数据的激进子样本,例如40%到80%。
教程概述
在本教程中,我们d J u / . .将研究不同的二次采样技术在梯度增强中的作用。我们将调整Python的XGBoost库= j C @ N ) K I所支持的三种不同2 y !的随机梯度增强方式,) n –特别是:
- 创建每棵/ O u f Y T j a树时,对数据集中的行进行二次采样。
- 创建每棵树时对数据集中的列进行二次采样。
- 创J / z 8建每个树时,数据集中每个拆分的列的子采样。b : B – : T
问题描述:Otto数据集
在本教程中,我们将使用“奥托| k | U F M @ = F集团产品分类挑战”数据集。该数据集可从Kaggle免费获得(您需要注册到Kagg1 ; L tle才能下载此数据集)。您可以从“数据”页面下载训练数据集traV : _ H $in.csv.zip并将解压缩后的train.csv文件放入您的工作目录中。该数据集描述了61,000多z * ; V 7 P t E \种产品的93个混淆细节,这些产品分为10个产品类别(例如,时尚,电子产品等)。输入属性是某种不同事件的计数。目标d z D是对新产品做出预测,将其作为10个类别中每一个类别的概率数组,并使用多类对数损失(也称为交叉熵)对模型进行评估。该竞赛已于2015年5月完成,并且由于示例数量不多,问题难度大,几乎不需要数据准备(除了将字符串类变量编码为整数)的事实. 5 T % + D p,该数据集对于XGBoost还是一个很8 7 $大的挑战。
在XGBoost中调整行二次采样A @ ~ F r d 2 x :
行二次抽样涉及选择训练数据集的随机样本而不进行替换。可以在subsample参数的XGBoost类的scikit-learn包装器中指定行子采样。默认值为1.0,该值不进行二次采样。我们可以使用scikit-learn中内置的网格搜索功能来评估从0.1到1.0的不R n ^ t | M同子样本值对Otto数据集的影响。
- [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,1.0]
子样本有9个变体,每个模型将使用10倍交叉验证进行评估,这意味着需要训练和测试910或90个模型。
下面提供了完整的代码清单。
- #XGBoostonOttodataset,tunesubsample
- frompandasimportread_csv
- fromxgboostimportXGBClassifier
- fromsklearn.model_selectionimportGridSearchCV
- fromsklearn.model_selectionimportStratifiedKFold
- fromsklearn.preprocessingimportLabelEncoder
- importmatplotlib
- matpm ( o | Jlotlib.use('Agg')
- frommatplotlibimportpyplotO A n l f
- #loaddata
- data=read_csv('traih % zn.csv')
- datadataset=data.values
- #splitda1 K ( ttaintoXandy
- X=dataset[:,0:94]
- y=dataset[:,94]
- #enU x 5 ; Z v w g 7codestringclassvaluesasintegers
- label_encod$ \ ] G W r Y [ed_y=LabelEncoder().fit_transform(y)c U M U q b
- #gridsearch
- model=XGBq D Q ` S KClassiz K - +fic f 2er()
- subsamN Q _ P # ` 3ple=[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,1.0]
- param_grid=dict(subsamplesubsam/ T m b )ple=subsample)
- kfold=SA g : k O h YtratifiedKFold(n_splits=10,shuffle=True,random_state=7Z # S l f)
- grid_search=GridSearchCV(model,param_grid,scoring="neg_log_loss",n_jobs=-1,cv=: a 7 3 @ H { W Dkfold)
- grid_result=gP g o j ; h +rid_search.fit(@ M \ B ` | X [ \X,label_encoded_y)
- #summarizeresults
- print("r 0 h 2 ) : 4Best:%fm 9 I c Yusing%s"%(grA ! vid_result.best_score_,grid_result.best_params_))
- meO p 3 ]ans=grid_result.cvO ; 3 ] - 2 + ._results_['mean_test_score']
- stds=grid_result.cv_resultsO Y , r ~_['std_test_score']
- params=grid_resultz 5 [ R.cv_results_['params']
- formeR b \ B j [ N !an,stdev,paraminzip(means,stds,params):
- print("%f(%f)with:%r"%(mean,stdev,pe M 9aram))
- #plot
- pyplot.errorbar(subsample,means,yerr=stds)
- pyplot.title("XGBoostsubsamplevsLogLoss")
- pyplot.xlabel('subsample')
- pyplot.ylabel('LogLoss')
- pyplot.savefig('subsample.png')
运行此示例将打印最佳配0 H e s – / z置以及每个测试配置的日志丢失。
注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能g E ! V \ U .会有所不同。考虑运行该示例几次并比较平均结果。
我们可以看到,获得的最佳结果是0.3,或者使用30%的训练数据v r 2 3集样本训练树。
- Best:-0.000647using{'subsample':0.3}
- -0.001156(0.000286)with:{'subsample':0.1}
- -0.000765(0.000434 3 1 } 40)with:{'subsample':0.2e y T h & ; S .}
- -0.000647(0.000471)with:{'subsample':0.3}
- -0.000659(0.000635)with:{'subsample':0.4}
- -0.000717(0.000849)F @ T c u 9 6 - 0with:{'subsample':0.5}
- -0.000773(0.0009u ; p v l W 598)with:{'subsample':0.6}
- -0.000877(0.001179)with:{'g [ R R R $ v x _subsample':0.7}
- -0.001007(0.001371)with:{'subsample':0.8}
- -0.001239(0.001730)with:{'x r - k wsubsample':1.0}
我们可以绘制这些均值和标准偏差对数损失值,以更好地了解性能如何A A i b随子样本值变化。
我们可以看到确实有30%的人具有最佳的平均表现,但是我们也可以看到,随着比率的增加,表现的差异会明显增加。有趣的是,所有子样本值的平均性能都优于不进行子抽样的平均性能(子样本= 1.0)。
在XGBoost中按树调整列二次采样
我们还可以在增强模型中创建每个决策树之前,创建要使用的特征(或列)的随机样本。在scikit-learn的XGBoo[ b ( \st包装器中,这由colsample_bytree参数控制。默认值为1.0,表示在每个决策树中使~ T N A } r 0用所有列。我们可以在0.1到1.0之间评估colsample_by^ c n X H *tree的值,以0.1为增量。
- [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,1.0]
完整实例如下:
- #XGBoostonOttodataset,tunecolsample_bytree
- frompandasimportread_csv
- fromxgboostimportXGBClassifie* d % r }r
- fromsklearn.model_selectionimportGridSearchCV
- fromsklearn.model_selectionimportStratifiedKFold
- fromsklearn.preprocessingimportLabelEncoder
- importmatplotlib
- matplotlib.use('A6 W ! o ( | 4 ugg')
- frommatplotlibimportpyplot
- #loaddata
- data=read_csvv l S W V d 5 G M('train.csv')
- datadataset=data.values
- #sH { - uplitdataintoXn t ` 1 ^andy
- X=dataset[:,0:94]
- y=dataset[:,94]
- #encodestringclassvaluesasintegers
- label_encoded_y=LabelEncoder().fit_transform(y)
- #gridseaT i z }rch
- model=XGb j Q $ 2 a s + xBClassifier()
- colsample_bytree=[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,1.0]
- param_grid=dict(colsample_bytreecolsample_bytree=colsample_bytree)
- kfold=e l R g N s lStratifiedKFold(n_splits=10,shuffle=True,random_state=7)
- grid_searcn - Q u gh=GridSeare T C @ \ Q \chCV(modelb 2 % c,param_grid,scoring="neg_log3 v : T b P q ~ }_loss",n_j0 ` x R d o Tobs=-1,cv=kfJ . S ~ 4 m l bold)
- grid_result=grid_search.fit(X,labe+ / r f i D v - #l_encoded_y)
- #summarizeresults
- print("Best:%0 ) 9 ] * n P \fusing%s"%(grid_result.best_score_,grid_result.best_params_))
- means/ j p u n=grid_4 ( ( o s f ] } oresult.cv_results_['mean_test_score']
- stds=grid_result.cv_results_['std_test_score']
- params=grid_result.cv_results_['params']
- formeanA ) & E H * .,stdev,paraminzip(means,stds,params):
- print- 5 g }("%f(%f)v l : [ ! 4with:%r"%(mean,stdev,para! y tm))
- #plot
- pyplot./ ~ A Q Lerrorbar(colsample_bytree,means,yerr=stds)
- pyplot.title("XGBoosh - { = ]tcolsample_bytreevsLogLoss")} k U ] 7
- pyplot.xlabeB - W W X J &l('colsample_bytree')
- py. ! Z ) Pplot.ylabel('LogLoss')
- pyplot.savefig('g x = 5 q ;colsample_bytree.png')
运行此示例将打, v 2 8 b g S印最佳配置以及每个测试配置的日志丢失。
注意:由于算法或评估程序的随机性,或数值精度的差异,您V & 2的结果可能会有所不同。
我们可以看到,模型的最佳性能是colsample_byY ] {tree = 1.0。这表明该问题进行二次采样不会增加价值。
- Best:-0.001239using{'colsample_bytree':1.0}
- -0.298955(0.002177)with:{'R ) c X g X d ! vcolsample_bytree':0.1}
- -0.092441(0.000798)with:{'colsample_bytree':0.2}
- -0.029993(0.000459)with:{'colsample_bytree':0.3}
- -0.010435(0.000669)with:{'colsample_bytree':0.4}
- -0.004176(0.000916)with:{'colsample_bytreeS W h t O j -':0.5}
- -0.002614(0.001062)with:{'colsample_bytree':0.6}
- -0.001694(0.001221)with:{'colsample_bytree':0.7}
- -0.001306(: } S0.001435)with:{'colsample_bytree':0.8}
- -0.00123Y a g H f } {9(0.001730)with:{'colsample& w S_bytree':1.0}
绘制结果,我们可以看到模型平稳段的} U (性能(至少在此比例下),值为0.5到1.0。
通过拆分在XGBoost中调整列二次采样
不必为每个树对列进行一次子采样,我们可以在决策树的每个拆分中对它们进行子采样。原则上~ i T _ G |,这是随机森林中使用的方法。我们可以在scikit-learn的XGBoost包装器类的colsample_bylevel参数中设置每个拆分所使用的列样本的大小。和以前一样,我们将比率从10%更改为默认值100%。
下面提供了完整的代码清单。
- #XGBoostonOttodataset,tunecolsample_bylevel
- frompandasimportread_csv
- fromxgboostimportXGBClassifier
- fromsklearnr W O d P V.model_selectionimportGridSearchCV
- fromsklearn.model_selectionimportStratifiedKFold
- fromsklearn.preprocessu l ,ingimportLabelEncoder
- importmatplotlib
- matplotlib.use3 M j = p 7('AggQ Y T')
- frommatplotlibimportpyplot
- #loaddata
- data=read_csv('train.csv')
- datadataset=data.values
- #splitdatail 6 X WntoXandy
- X=dataset[:,0:94]
- y=dataset[:,94]
- #encodestringclassvaluesasintU 0 z b c ` Kegers
- label_encoded_y=LabelEncoder().fit_transform(y)
- #gridsearch
- modet } c H C D W 4 El=XGBClass9 8 _ -ifier()
- colsample_bylevI u ~ Fel=[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,1.0]
- param_gridj r K 1 c j 1=dict(colsample_\ h E K B . A Ybyleu p C T E Wvelcolsample_bylevel=colsample_bs / { \ o { T , SylevE t %el)
- kfold=StratifiedKFold(n_splits=10,shuffle=True,random_s* o t X V M D R [tate=7)
- grid_search=GridSearchCV(model,param_grid,scoring="neg_log_loss",n_jobs=-1,cv=kf? P e Vold)
- grid_result=grid_search.fit(+ e b } q QX,label_encoded_y~ i A w W r L)
- #summarizeresults
- print("Best:%fusing%s"%S I s Q L } 3 y %(gri: 1 1d_result.best_score_,grid_result.best_params_))o { B
- means=grid_e B ! + x I r : =result.cv_results_['mean_test_score']
- stds=grid_result.cr ? \ ` - [ b }v_results_['std_test_score']
- params=grid_result.cv_re} ; # 3sults_['params']
- formean,stdev,paraminzip(means,sn Z N ! `tdsz h ] & M,params):
- print("%f(%f)with:%r"%(mean,stdev,param))
- #plok b Qt
- pyplot.errorbar(colsamph # w % L [ 2le_4 d 5 p V Q ;bylevel,m9 e ceans,yt ] p 9 = Rerr=stds)
- pyplot.title("XGBoostt y @ @ kcolsample_bylevelvsLogLoss")
- pyplot.xlabel('colsa) Y 1 5 + a [mple_bylevel')
- pyp) I )lot.ylabel('LogLoss')X 1 = q ,
- pyplot.savefig('colsample_bylevel.png'# O 6 ? +)
运行此示F + ` u ? 1 W {例将打印] X E U M最佳配置以及每个测试配置的日志丢失^ n 2 &。
注意:由于算法或评估程序的随机性,h x Q 0 :或者数值精度的差异,您的结果可能会有所不同。考虑运行该示例几次并比较平均结果。
我们可以看到,通过将colsample_bylevel设置为70%可获得最佳结果,导致(倒置)对数损失为-0.001062,这比将每棵树的列H ] G采样设置为100%时看到的-0.001239好。
如果每棵树的[ m M结果建议使用100%的列,则? / M S )建议不要放弃列二次采样,而应尝试按拆分的列二次采样。
- Best:-0.001062using{'colsample_bylevel':0.7}
- -0.159455(0.007028)with:{E W \'colsample_byleveE R } z u U . *l':0.1}
- -0.% y :034391(0.003533)withk e p:{'colsample_bylevel':0.2}
- -0.007619(0.X 3 % y U $000451)with:{'colsample_bylevel':0.3}
- -0.002982(0.000726)with:{'cov 0 u 5 Z W -lsample_bylevel':0.4}
- -0.001f K G Q h410(0.000946)with:{'colsample_bylevel':0.5}
- -0.001182(0.001144)wi: = G h u ^th:{'N A r Zcolsample_bylevel':0.6}
- -0.001062(0.001221)with:{'colsample_bylevel':0.7}
- -0.001071(0.001427)with:{'colsample_bylevel':0.8}
- -0.001239(0.001730)with:{'coG W llsample_bylevel':1.0}
我们可以绘制每个colsample_bylevel变化的性能。结果表明,在此~ $ l f ! \比例下的值为0.3后,方差相J ! R对较低,并且性能似乎处于平稳状态。
点赞 0