前言
本次練習(xí)主要致力于xgboost回歸模型(XGBRegressor)的簡(jiǎn)單的數(shù)據(jù)處理與模型調(diào)參含滴,數(shù)據(jù)與標(biāo)桿模型來(lái)自公共自行車使用量預(yù)測(cè)的一個(gè)競(jìng)賽。
(http://sofasofa.io/competition.php?id=1#c1)
結(jié)果要求RMSE的最小源哩,本文最終處理結(jié)果為RMSE:14.835鸦做,排名47。
1 xgboost模型概述
1.1 XGBoost的核心算法思想
①不斷地添加樹(shù)泼诱,不斷地進(jìn)行特征分裂來(lái)生長(zhǎng)一棵樹(shù),每次添加一個(gè)樹(shù)屉栓,其實(shí)是學(xué)習(xí)一個(gè)新函數(shù)f(x)友多,去擬合上次預(yù)測(cè)的殘差。
②當(dāng)我們訓(xùn)練完成得到k棵樹(shù)纵柿,我們要預(yù)測(cè)一個(gè)樣本的分?jǐn)?shù)启绰,其實(shí)就是根據(jù)這個(gè)樣本的特征,在每棵樹(shù)中會(huì)落到對(duì)應(yīng)的一個(gè)葉子節(jié)點(diǎn)渊跋,每個(gè)葉子節(jié)點(diǎn)就對(duì)應(yīng)一個(gè)分?jǐn)?shù)着倾。
③最后只需要將每棵樹(shù)對(duì)應(yīng)的分?jǐn)?shù)加起來(lái)就是該樣本的預(yù)測(cè)值卡者。
目標(biāo)是要使得樹(shù)群的預(yù)測(cè)值盡量接近真實(shí)值,而且有盡量大的泛化能力蟋软。
1.2 XGBoost的優(yōu)點(diǎn)
①使用許多策略去防止過(guò)擬合嗽桩,如:正則化項(xiàng)、Shrinkage and Column Subsampling等湿痢。
②目標(biāo)函數(shù)優(yōu)化利用了損失函數(shù)關(guān)于待求函數(shù)的二階導(dǎo)數(shù)扑庞。
③支持并行化罐氨,這是XGBoost的閃光點(diǎn),雖然樹(shù)與樹(shù)之間是串行關(guān)系塔嬉,但是同層級(jí)節(jié)點(diǎn)可并行。具體的對(duì)于某個(gè)節(jié)點(diǎn)恩袱,節(jié)點(diǎn)內(nèi)選擇最佳分裂點(diǎn)胶哲,候選分裂點(diǎn)計(jì)算增益用多線程并行。訓(xùn)練速度快澈吨。
④添加了對(duì)稀疏數(shù)據(jù)的處理碾盟。
⑤交叉驗(yàn)證冰肴,early stop榔组,當(dāng)預(yù)測(cè)結(jié)果已經(jīng)很好的時(shí)候可以提前停止建樹(shù),加快訓(xùn)練速度检痰。
⑥支持設(shè)置樣本權(quán)重锨推,該權(quán)重體現(xiàn)在一階導(dǎo)數(shù)g和二階導(dǎo)數(shù)h换可,通過(guò)調(diào)整權(quán)重可以去更加關(guān)注一些樣本。
1.3 XGBoost的參數(shù)
通用參數(shù):宏觀函數(shù)控制慨飘。
booster:我們有兩種參數(shù)選擇译荞,gbtree和gblinear吞歼。gbtree是采用樹(shù)的結(jié)構(gòu)來(lái)運(yùn)行數(shù)據(jù),而gblinear是基于線性模型篙骡。默認(rèn)使用gbtree就可以了,不需要調(diào)參老虫。
silent:靜默模式茫多,為1時(shí)模型運(yùn)行不輸出。
nthread: 使用線程數(shù)夺欲,一般我們?cè)O(shè)置成-1,使用所有線程今膊。如果有需要斑唬,我們?cè)O(shè)置成多少就是用多少線程。
Booster參數(shù):控制每一步的booster(tree/regression)缤谎。booster參數(shù)一般可以調(diào)控模型的效果和計(jì)算代價(jià)褐着。我們所說(shuō)的調(diào)參,很這是大程度上都是在調(diào)整booster參數(shù)频敛。
n_estimator: 也作num_boosting_rounds
這是生成的最大樹(shù)的數(shù)目斟赚,也是最大的迭代次數(shù)岂嗓。learning_rate: 有時(shí)也叫作eta,系統(tǒng)默認(rèn)值為0.3
每一步迭代的步長(zhǎng)食绿,很重要公罕。太大了運(yùn)行準(zhǔn)確率不高楼眷,太小了運(yùn)行速度慢熊尉。我們一般使用比默認(rèn)值小一點(diǎn)掌腰,0.1左右就很好齿梁。gamma:系統(tǒng)默認(rèn)為0,我們也常用0。
在節(jié)點(diǎn)分裂時(shí)创南,只有分裂后損失函數(shù)的值下降了省核,才會(huì)分裂這個(gè)節(jié)點(diǎn)。gamma指定了節(jié)點(diǎn)分裂所需的最小損失函數(shù)下降值邻储。 這個(gè)參數(shù)的值越大芥备,算法越保守舌菜。因?yàn)間amma值越大的時(shí)候亦镶,損失函數(shù)下降更多才可以分裂節(jié)點(diǎn)缤骨。所以樹(shù)生成的時(shí)候更不容易分裂節(jié)點(diǎn)。范圍: [0,∞]subsample:系統(tǒng)默認(rèn)為1精拟。
這個(gè)參數(shù)控制對(duì)于每棵樹(shù)虱歪,隨機(jī)采樣的比例笋鄙。減小這個(gè)參數(shù)的值,算法會(huì)更加保守践美,避免過(guò)擬合。但是敛滋,如果這個(gè)值設(shè)置得過(guò)小兴革,它可能會(huì)導(dǎo)致欠擬合帖旨。 典型值:0.5-1,0.5代表平均采樣落竹,防止過(guò)擬合. 范圍: (0,1]货抄,注意不可取0colsample_bytree:系統(tǒng)默認(rèn)值為1蟹地。我們一般設(shè)置成0.8左右。
用來(lái)控制每棵隨機(jī)采樣的列數(shù)的占比(每一列是一個(gè)特征)夺刑。 典型值:0.5-1范圍: (0,1]colsample_bylevel:默認(rèn)為1,我們也設(shè)置為1.
這個(gè)就相比于前一個(gè)更加細(xì)致了分别,它指的是每棵樹(shù)每次節(jié)點(diǎn)分裂的時(shí)候列采樣的比例max_depth: 系統(tǒng)默認(rèn)值為6
我們常用3-10之間的數(shù)字耘斩。這個(gè)值為樹(shù)的最大深度。這個(gè)值是用來(lái)控制過(guò)擬合的坞笙。max_depth越大荚虚,模型學(xué)習(xí)的更加具體曲管。設(shè)置為0代表沒(méi)有限制,范圍: [0,∞]max_delta_step:默認(rèn)0,我們常用0.
這個(gè)參數(shù)限制了每棵樹(shù)權(quán)重改變的最大步長(zhǎng)腊徙,如果這個(gè)參數(shù)的值為0,則意味著沒(méi)有約束撬腾。如果他被賦予了某一個(gè)正值,則是這個(gè)算法更加保守胰默。通常漓踢,這個(gè)參數(shù)我們不需要設(shè)置,但是當(dāng)個(gè)類別的樣本極不平衡的時(shí)候奴迅,這個(gè)參數(shù)對(duì)邏輯回歸優(yōu)化器是很有幫助的取具。min_child_weight: 默認(rèn)為0
孩子節(jié)點(diǎn)中最小的樣本權(quán)重和扁耐。如果一個(gè)葉子節(jié)點(diǎn)的樣本權(quán)重和小于min_child_weight則拆分過(guò)程結(jié)束婉称。在現(xiàn)行回歸模型中,這個(gè)參數(shù)是指建立每個(gè)模型所需要的最小樣本數(shù)榨乎。該成熟越大算法越conservative瘫筐。即調(diào)大這個(gè)參數(shù)能夠控制過(guò)擬合策肝。取值范圍為: [0,∞]lambda:也稱reg_lambda,默認(rèn)值為0隐绵。
權(quán)重的L2正則化項(xiàng)依许。(和Ridge regression類似)。這個(gè)參數(shù)是用來(lái)控制XGBoost的正則化部分的膘婶。這個(gè)參數(shù)在減少過(guò)擬合上很有幫助悬襟。alpha:也稱reg_alpha默認(rèn)為0,
權(quán)重的L1正則化項(xiàng)。(和Lasso regression類似)逝段。 可以應(yīng)用在很高維度的情況下割捅,使得算法的速度更快亿驾。scale_pos_weight:默認(rèn)為1
在各類別樣本十分不平衡時(shí),把這個(gè)參數(shù)設(shè)定為一個(gè)正值参淹,可以使算法更快收斂浙值。通抽菪。可以將其設(shè)置為負(fù)樣本的數(shù)目與正樣本數(shù)目的比值。
學(xué)習(xí)目標(biāo)參數(shù):控制訓(xùn)練目標(biāo)的表現(xiàn)筐付。我們對(duì)于問(wèn)題的劃分主要體現(xiàn)在學(xué)習(xí)目標(biāo)參數(shù)上瓦戚。比如我們要做分類還是回歸丛塌,做二分類還是多分類赴邻,這都是目標(biāo)參數(shù)所提供的。
**objective **:在回歸問(wèn)題objective一般使用reg:squarederror 奸焙,即MSE均方誤差与帆。
eval_metric :校驗(yàn)數(shù)據(jù)所需要的評(píng)價(jià)指標(biāo),不同的目標(biāo)函數(shù)將會(huì)有缺省的評(píng)價(jià)指標(biāo)揍拆。
2 數(shù)據(jù)處理
2.1 數(shù)據(jù)可視化
查看各個(gè)變量的相關(guān)性:
sns.heatmap(train.corr())
plt.show()
考慮到不同城市有不同情況,我們?cè)賮?lái)查看不同城市下贮喧,其變量與y的聯(lián)系:
sns.barplot(data = train, x='hour', y= 'y', hue='city',ci=None)
plt.show()
同理箱沦,其他變量也表示出節(jié)假日,氣溫適宜灶伊,天氣和煦聘萨,風(fēng)俗適中時(shí)童太,出行借車的人較多书释,比較符合我們的現(xiàn)實(shí)經(jīng)驗(yàn)。
目前判斷——特征數(shù)量不多狸页,且在不同城市下检激,都與y相關(guān)叔收,暫時(shí)都保留傲隶。
2.2 特征處理
在xgboost標(biāo)桿模型上跺株,使用其默認(rèn)參數(shù),在三折交叉驗(yàn)證下查看不同特征處理下RMSE的變化巧颈。
RMSE數(shù)值為:19.26933449074207
使用的時(shí)間為: 1.4850318431854248
2.2.1 標(biāo)準(zhǔn)化處理(連續(xù)特征)
將數(shù)據(jù)按比例縮放砸泛,使之落入一個(gè)小的特定區(qū)間。
columns=['temp_1','temp_2']
for i in columns:
train[i]=(train[i] - train[i].min()) / (train[i].max() - train[i].min()) # Min-max 標(biāo)準(zhǔn)化
train[i] = (train[i] - train[i].mean()) / (train[i].std()) # z-score 標(biāo)準(zhǔn)化
Min-max 標(biāo)準(zhǔn)化:19.282205008176323
使用的時(shí)間為:1.4032714366912842
z-score 標(biāo)準(zhǔn)化:19.0416315493435
使用的時(shí)間為: 1.4032535552978516
可看出并未有什么改變,這是因?yàn)?strong>數(shù)值縮放不影響分裂點(diǎn)位置盏筐,對(duì)樹(shù)模型的結(jié)構(gòu)不造成影響琢融,(樹(shù)形結(jié)構(gòu)為什么不用歸一化漾抬?)
2.2.3 'one-hot'處理(離散特征)
首先要求將分類值映射到整數(shù)值。然后她混,每個(gè)整數(shù)值被表示為二進(jìn)制向量泊碑,除了整數(shù)的索引之外馒过,它都是零值腹忽,它被標(biāo)記為1。
columns=['city','is_workday','weather','wind','hour']
for i in columns:
get_dummy_feature=pd.get_dummies(train[i], prefix= i)
train=pd.concat([train, get_dummy_feature],axis=1) #將user_id'和movie_id垂直拼接
train=train.drop(i, axis=1)
RMSE數(shù)值為:22.964568418562475
使用的時(shí)間為: 2.29085636138916
可看出one-hot處理后嘹锁,得分變低且時(shí)間變多领猾,這是因?yàn)?strong>對(duì)于決策樹(shù)來(lái)說(shuō),one-hot 的本質(zhì)是增加樹(shù)的深度面粮,tree-model 是在動(dòng)態(tài)的過(guò)程中生成類似 One-Hot + Feature Crossing 的機(jī)制****(樹(shù)形結(jié)構(gòu)為什么不用one-hot熬苍?)
2.2.4 等距分桶(連續(xù)特征)
分桶是離散化的常用方法袁翁,將連續(xù)型特征離線化為一系列 0/1 的離散特征梦裂。
train['temp_1']=np.floor_divide(train['temp_1'], 1)
train['temp_2']=np.floor_divide(train['temp_2'], 1)
RMSE數(shù)值為:19.286424187165196
使用的時(shí)間為: 1.4750919342041016
可看出等距分桶后并未有什么變化年柠,是因?yàn)閄GBoost本身使用的是pre-sorted算法(對(duì)所有特征都按照特征的數(shù)值進(jìn)行預(yù)排序,找到最好分割點(diǎn)將數(shù)據(jù)分裂成左右子節(jié)點(diǎn))與分桶相似答憔。(xgboost gbdt特征點(diǎn)分烈點(diǎn))
2.2.5 特征交叉
通過(guò)將單獨(dú)的特征進(jìn)行組合(相乘或求笛卡爾積)而形成的合成特征虐拓。
columns=['hour','temp_1','temp_2','city','is_workday','weather','wind']
for iin columns:
for jin columns:
name ='{}*{}'.format(i,j)
train[name]=train[i].mul(train[j])
RMSE數(shù)值為:17.40209548555587
使用的時(shí)間為: 3.1934659481048584
可看出雖然時(shí)間變多傲武,但數(shù)值有明顯提升揪利,是因?yàn)?strong>特征組合有助于表示非線性關(guān)系疟位。(特征組合&特征交叉 (Feature Crosses))
3 調(diào)參
3.1 girdSearchCV(網(wǎng)格搜索)
我們特征處理先暫時(shí)不采取特征交叉(特征交叉調(diào)參會(huì)花費(fèi)巨大時(shí)間),直接使用原始數(shù)據(jù)通過(guò)gridSearchCV(網(wǎng)格搜索)對(duì)Booster參數(shù)調(diào)參绍撞。
from sklearn.model_selectionimport GridSearchCV
cv_params ={} # 輸入所調(diào)參的范圍
other_params ={} # 初始參數(shù)
model = XGBRegressor(**other_params)
reg = GridSearchCV(estimator=model,param_grid=cv_params,scoring='neg_mean_squared_error',verbose=1,n_jobs=4,cv=3)
reg.fit(train_x, train_y)
# 查看結(jié)果
evalute_result = reg.cv_results_
print('每輪迭代運(yùn)行結(jié)果:{0}'.format(evalute_result))
print('RMSE數(shù)值為:{0}'.format(reg.best_params_))
print('RMSE數(shù)值為:{0}'.format(np.sqrt(abs(reg.best_score_))))
3.2 迭代次數(shù):n_estimators
cv_params ={'n_estimators':[400,500,600,700,800]}
other_params ={'objective':'reg:squarederror'}
# 'objective':'reg:squarederror'是解決WARNING: src/objective/regression_obj.cu:152: reg:linear is now deprecated in favor of reg:squarederror.
參數(shù)的最佳取值:{'n_estimators': 800}
RMSE數(shù)值為:15.74321267404705
使用的時(shí)間為: 11.980980634689331
3.3 min_child_weight以及max_depth
cv_params ={'max_depth': [3, 4, 5, 6, 7, 8, 9, 10],'min_child_weight': [1, 2, 3, 4, 5, 6]}
other_params = {'n_estimators':800}
參數(shù)的最佳取值:{'max_depth': 4, 'min_child_weight': 6,'objective':'reg:squarederror'}
RMSE數(shù)值為:15.216376799573485
使用的時(shí)間為: 224.291574716568
3.4 gamma
cv_params ={'gamma': [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]}
other_params = {'n_estimators':800,'max_depth': 4, 'min_child_weight': 6,'objective':'reg:squarederror'}
參數(shù)的最佳取值:{'gamma': 0.2}
RMSE數(shù)值為:15.300038541244316
使用的時(shí)間為: 21.902464628219604
3.5 subsample以及colsample_bytree
cv_params = {'subsample': [0.6, 0.7, 0.8, 0.9],'colsample_bytree': [0.6, 0.7, 0.8, 0.9]}
other_params = {'n_estimators':800,'max_depth':4,'min_child_weight':6,'gamma':0.2,'objective':'reg:squarederror'}
參數(shù)的最佳取值:{'colsample_bytree': 0.9, 'subsample': 0.9}
RMSE數(shù)值為:15.075942336446541
使用的時(shí)間為: 51.692848443984985
3.6 reg_alpha以及reg_lambda
cv_params = {'reg_alpha': [0.05, 0.1, 1, 2, 3],'reg_lambda': [0.05, 0.1, 1, 2, 3]}
other_params = {'n_estimators':800,'max_depth':4,'min_child_weight':6,'gamma':0.2,'colsample_bytree': 0.9, 'subsample': 0.9,'objective':'reg:squarederror'}
參數(shù)的最佳取值:{'reg_alpha': 3, 'reg_lambda': 3}
RMSE數(shù)值為:15.052545276896213
使用的時(shí)間為: 84.78042197227478
3.7 learning_rate
cv_params = {'learning_rate': [0.01,0.02,0.03,0.04,0.05,0.06]}
other_params = {'n_estimators':800,'max_depth':4,'min_child_weight':6,'gamma':0.2,'colsample_bytree':0.9,
'subsample':0.9,'reg_alpha':3,'reg_lambda':3,'objective':'reg:squarederror'}
參數(shù)的最佳取值:{'learning_rate': 0.06}
RMSE數(shù)值為:14.838008021573847
使用的時(shí)間為: 21.34994149208069
3.8 最佳參數(shù)
回顧以上調(diào)參結(jié)果祥绞,我們不難發(fā)現(xiàn)n_estimators就谜、max_depth怪蔑、learning_rate的調(diào)參對(duì)數(shù)值改變最大,于是對(duì)n_estimators耍鬓、max_depth熙掺、learning_rate再調(diào)整
cv_params = {'n_estimators': [400,500,600,700,800],'max_depth': [4,5,6,7],'learning_rate': [0.02,0.04,0.06,0.08]}
other_params = {'n_estimators':800,'max_depth':4,'min_child_weight':6,'gamma':0.2,'colsample_bytree':0.9,
'subsample':0.9,'reg_alpha':3,'reg_lambda':3,'learning_rate':0.06,'objective':'reg:squarederror'}
參數(shù)的最佳取值:{'learning_rate': 0.02, 'max_depth': 6, 'n_estimators': 600}
RMSE數(shù)值為:14.769918846838962
使用的時(shí)間為: 134.6865828037262
3.9 嘗試特征處理
因?yàn)榭紤]到之前默認(rèn)參數(shù)不一定為特征處理后的最佳參數(shù)畴蒲,我們?cè)谝陨献罴褏?shù)下特征處理,再對(duì)n_estimators弓坞、max_depth、learning_rate再調(diào)整
結(jié)果發(fā)現(xiàn)在'one-hot'處理和特征交叉不僅花費(fèi)巨大時(shí)間還降低了RMSE的數(shù)值车荔,而等距分桶和標(biāo)準(zhǔn)化處理所得最佳參數(shù)沒(méi)變渡冻,數(shù)值和時(shí)間也沒(méi)什么變化,所以決定不進(jìn)行特征處理族吻。
確定最終參數(shù)為:
other_params = {'n_estimators':600,'max_depth':6,'min_child_weight':6,'gamma':0.2,'colsample_bytree':0.9,
'subsample':0.9,'reg_alpha':3,'reg_lambda':3,'learning_rate':0.02,'objective':'reg:squarederror'}
以上所有調(diào)參可縮小參數(shù)范圍,進(jìn)行多次遍歷珠增。
3.10 提交結(jié)果
由于交叉驗(yàn)證的存在超歌,使得相同參數(shù)下的預(yù)測(cè)會(huì)有所不同,我們需要多次提交蒂教。最終最佳結(jié)果為RMSE:14.835巍举,排名47。
小結(jié)
①在簡(jiǎn)單的數(shù)據(jù)下凝垛,xgboost更適合直接使用原數(shù)據(jù)懊悯,因?yàn)槠浔旧砭哂幸欢ǖ?strong>處理數(shù)據(jù)能力。
②將不同特征化處理的數(shù)據(jù)進(jìn)行逐步調(diào)參會(huì)花費(fèi)大量時(shí)間梦皮,可以先進(jìn)行簡(jiǎn)單的調(diào)參再代入特征化處理炭分。
③本次僅僅針對(duì)簡(jiǎn)單的特征處理和調(diào)參,要想再提高模型擬合能力還需要數(shù)據(jù)清洗届氢,特征選擇欠窒,特征融合,模型融合等手段來(lái)進(jìn)行改進(jìn)退子。
④調(diào)參順序很重要岖妄,不同參數(shù)有不同的聯(lián)系和影響程度,了解參數(shù)就能了解模型構(gòu)造寂祥。