競(jìng)賽練習(xí)—公共自行車使用量預(yù)測(cè)

前言

本次練習(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],注意不可取0

colsample_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ù)處理

image

2.1 數(shù)據(jù)可視化

查看各個(gè)變量的相關(guān)性:

sns.heatmap(train.corr())

plt.show()
image

考慮到不同城市有不同情況,我們?cè)賮?lái)查看不同城市下,其變量與y的聯(lián)系:

sns.barplot(data = train, x='hour', y= 'y', hue='city',ci=None)

plt.show()
image

同理,其他變量也表示出節(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)造。

代碼與數(shù)據(jù)在我的碼云里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容