溫度預(yù)測示例&參數(shù)優(yōu)化工具RandomizedSearchCV

一般情況下,我們做數(shù)據(jù)挖掘任務(wù)都是按照“數(shù)據(jù)預(yù)處理 - 特征工程 - 構(gòu)建模型(使用默認(rèn)參數(shù)或經(jīng)驗參數(shù)) - 模型評估 - 參數(shù)優(yōu)化 - 模型固定”這樣一個流程來處理問題。這一小節(jié),我們要討論的主題就是參數(shù)優(yōu)化,前面我們討論過GridSearchCV(網(wǎng)格搜索)這個工具,它是對我們的參數(shù)進(jìn)行組合,選取效果最好的那組參數(shù)。


data mining.jpg

這一節(jié),我們探索下參數(shù)優(yōu)化當(dāng)中的另一個工具RandomizedSearchCV(隨機(jī)搜索),這名字咋一聽感覺有點不太靠譜,對,它是有點不太靠譜,但為什么我們還要用它呢?因為它的效率高,它可以快速地幫助我們確定一個參數(shù)的大概范圍,然后我們再使用網(wǎng)格搜索確定參數(shù)的精確值。就像警察抓犯人一樣,先得快速地確認(rèn)罪犯的活動區(qū)域,然后在該區(qū)域內(nèi)展開地毯式搜索,這樣效率更高。

這一小節(jié),我們以隨機(jī)森林模型作為例子,通過演示一個完整的建模過程,來說明RandomizedSearchCV的用法。當(dāng)然這個工具不是隨機(jī)森林特有的,它可以應(yīng)用于任何模型的參數(shù)優(yōu)化當(dāng)中。

隨機(jī)森林模型:
官方文檔:https://scikitlearn.org/stable/modules/generated/sklearn.ensemble.RandomForestRegressor.html?highlight=randomforestr#sklearn.ensemble.RandomForestRegressor

RandomForestRegressor.png

從上圖可以看出隨機(jī)森林模型有很多參數(shù),如:n_estimators, max_depth, min_samples_split, min_samples_leaf,max_features,bootstrap等。每一個參數(shù)都會對最終結(jié)果產(chǎn)生影響,同時每一個參數(shù)又有著眾多的取值,我們的目標(biāo)是找到最優(yōu)的參數(shù)組合,使得我們的模型效果最好。

RandomizedSearchCV工具:
官方文檔:
https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RandomizedSearchCV.html?highlight=randomized#sklearn.model_selection.RandomizedSearchCV

RandomizedSearchCV.png

RandomizedSearchCV參數(shù)說明:

  • estimator:我們要傳入的模型,如KNN,LogisticRegression,RandomForestRegression等。
  • params_distributions:參數(shù)分布,字典格式。將我們所傳入模型當(dāng)中的參數(shù)組合為一個字典。
  • n_iter:隨機(jī)尋找參數(shù)組合的數(shù)量,默認(rèn)值為10。
  • scoring:模型的評估方法。在分類模型中有accuracy,precision,recall_score,roc_auc_score等,在回歸模型中有MSE,RMSE等。
  • n_jobs:并行計算時使用的計算機(jī)核心數(shù)量,默認(rèn)值為1。當(dāng)n_jobs的值設(shè)為-1時,則使用所有的處理器。
  • iid:bool變量,默認(rèn)為deprecated,返回值為每折交叉驗證的值。當(dāng)iid = True時,返回的是交叉驗證的均值。
  • cv:交叉驗證的折數(shù),最新的sklearn庫默認(rèn)為5。

接下來,我們采用溫度數(shù)據(jù)集作為例子,來演示RandomizedSearchCV的用法。我們將進(jìn)行一個完整的數(shù)據(jù)建模過程:數(shù)據(jù)預(yù)處理 - 模型搭建 - RandomizedSearchCV參數(shù)優(yōu)化 - GridSearchCV參數(shù)優(yōu)化 - 確定最優(yōu)參數(shù),確定模型。

溫度數(shù)據(jù)集:鏈接:https://pan.baidu.com/s/1q10_Vz7ujuu8oCOqysNU7A
提取碼:bxcr

任務(wù)目標(biāo):基于昨天和前天的一些歷史天氣數(shù)據(jù),建立模型,預(yù)測當(dāng)天的最高的真實溫度。

數(shù)據(jù)集中主要特征說明:

  • ws_1:昨天的風(fēng)速。
  • prcp_1:昨天的降水量。
  • snwd_1:昨天的降雪厚度。
  • temp_1:昨天的最高溫度。
  • temp_2:前天的最高溫度。
  • average:歷史中這一天的平均最高溫度。
  • actual:當(dāng)天的真實最高溫度。

建模完整過程演示:

#導(dǎo)入數(shù)據(jù)分析的兩大工具包
import numpy as np
import pandas as pd

#讀取數(shù)據(jù)
df = pd.read_csv('D:\\Py_dataset\\temps_extended.csv')
df.head()
#查看數(shù)據(jù)的規(guī)模
df.shape
(2191, 12)#該數(shù)據(jù)集有2191個樣本,每個樣本有12個特征。

1.數(shù)據(jù)預(yù)處理

該數(shù)據(jù)集整體上是比較干凈的,沒有缺失值和異常值。這一步我們熟悉下數(shù)據(jù)預(yù)處理的基本過程。

# 1.查看數(shù)據(jù)集的基本信息
df.info()
df info.png

從上述結(jié)果可以看出這份數(shù)據(jù)集的整體情況。一共2191個樣本,索引從0開始,截止于2190。一共12個特征,每個特征的數(shù)量為2191,缺失值情況(non-null),類型(int64 or object or float64),內(nèi)存使用205.5KB。

由于數(shù)據(jù)沒有缺失值,所以我們不需要做缺失值處理。接下來我們看數(shù)據(jù)類型,由于計算機(jī)只能識別數(shù)值型數(shù)據(jù),所以我們必須將數(shù)據(jù)集中的非數(shù)值型數(shù)據(jù)轉(zhuǎn)化為數(shù)值型數(shù)據(jù)。該數(shù)據(jù)集中只有"weekday"是object類型,由于我們要預(yù)測的是今天的溫度值,所以日期數(shù)據(jù)(如昨天是幾號,星期幾)對我們的結(jié)果沒有什么影響,將這些日期數(shù)據(jù)刪掉。數(shù)據(jù)集中有一個"friend"特征,該值的意思可能是朋友的猜測結(jié)果,在建模過程中,我們暫不關(guān)注這個特征,所以將"friend"特征也刪掉。

df = df.drop(['year','month','day','weekday','friend'],axis = 1)
df.head()
clean-data.png

2.數(shù)據(jù)切分

當(dāng)我們完成了數(shù)據(jù)集清洗之后,接下來就是將原始數(shù)據(jù)集切分為特征(features)和標(biāo)簽(labels)。接著將特征和標(biāo)簽再次切分為訓(xùn)練特征,測試特征,訓(xùn)練標(biāo)簽和測試標(biāo)簽。

#導(dǎo)入數(shù)據(jù)切分模塊
from sklearn.model_selection import train_test_split
#提取數(shù)據(jù)標(biāo)簽
labels = df['actual']
#提取數(shù)據(jù)特征
features = df.drop('actual',axis = 1)

#將數(shù)據(jù)切分為訓(xùn)練集和測試集
train_features,test_features,train_labels,test_labels = train_test_split(features,labels,
test_size = 0.3,random_state = 0)

print('訓(xùn)練特征的規(guī)模:',train_features.shape)
print('訓(xùn)練標(biāo)簽的規(guī)模:',train_labels.shape)
print('測試特征的規(guī)模:',test_features.shape)
print('測試標(biāo)簽的規(guī)模:',test_labels.shape)

#切分之后的結(jié)果
訓(xùn)練特征的規(guī)模: (1533, 6)
訓(xùn)練標(biāo)簽的規(guī)模: (1533,)
測試特征的規(guī)模: (658, 6)
測試標(biāo)簽的規(guī)模: (658,)

3.建立初始隨機(jī)森林模型

建立初始模型,基本上都使用模型的默認(rèn)參數(shù),建立RF(RandomForestRegressor)模型,我們唯一指定了一個n_estimators參數(shù)。

from sklearn.ensemble import RandomForestRegressor

#建立初始模型
RF = RandomForestRegressor(n_estimators = 100,random_state = 0)
#訓(xùn)練數(shù)據(jù)
RF.fit(train_features,train_labels)
#預(yù)測數(shù)據(jù)
predictions = RF.predict(test_features)

4.模型評估

該例子我們使用的是回歸模型,預(yù)測結(jié)果是一個準(zhǔn)確的數(shù)值。我們的目標(biāo)是希望我們的預(yù)測結(jié)果與真實數(shù)據(jù)的誤差越好。所以我們在此選用的模型評估方法為均方誤差(mean_squared_error)和均方根誤差(root_mean_squared_error)。下式分別是MSE和RMSE的計算公式,其中Yi為真實值,Yi^為預(yù)測值。


MSE.png

RMSE.png
from sklearn.metrics import mean_squared_error
#傳入真實值,預(yù)測值
MSE = mean_squared_error(test_labels,predictions)

RMSE = np.sqrt(MSE)
print('模型預(yù)測誤差:',RMSE)
模型預(yù)測誤差: 5.068073484568353

5.RandomizdSearchCV參數(shù)優(yōu)化

from sklearn.model_selection import RandomizedSearchCV

RF = RandomForestRegressor()
#設(shè)置初始的參數(shù)空間
n_estimators = [int(x) for x in np.linspace(start = 200,stop = 2000,num = 10)]
min_samples_split = [2,5,10]
min_samples_leaf = [1,2,4]
max_depth = [5,8,10]
max_features = ['auto','sqrt']
bootstrap = [True,False]
#將參數(shù)整理為字典格式
random_params_group = {'n_estimators':n_estimators,
                      'min_samples_split':min_samples_split,
                      'min_samples_leaf':min_samples_leaf,
                      'max_depth':max_depth,
                      'max_features':max_features,
                      'bootstrap':bootstrap}
#建立RandomizedSearchCV模型
random_model =RandomizedSearchCV(RF,param_distributions = random_params_group,n_iter = 100,
scoring = 'neg_mean_squared_error',verbose = 2,n_jobs = -1,cv = 3,random_state = 0)
#使用該模型訓(xùn)練數(shù)據(jù)
random_model.fit(train_features,train_labels)
Random_model fit process.png

我們觀察下模型的訓(xùn)練過程,我們設(shè)置了n_iter=100,由于交叉驗證的折數(shù)=3,所以該模型要迭代300次。第二層顯示的是訓(xùn)練過程的用時,訓(xùn)練完成總共用了6.2min。第三層顯示的是參與訓(xùn)練的參數(shù)。

使用集成算法的屬性,獲得Random_model最好的參數(shù)

random_model.best_params_
{'n_estimators': 1200,
 'min_samples_split': 5,
 'min_samples_leaf': 4,
 'max_features': 'auto',
 'max_depth': 5,
 'bootstrap': True}

將得出的最優(yōu)參數(shù),傳給RF模型,再次訓(xùn)練參數(shù),并進(jìn)行結(jié)果預(yù)測??梢钥吹浇?jīng)過參數(shù)優(yōu)化后,模型的效果提升了2%。

RF = RandomForestRegressor(n_estimators = 1200,min_samples_split = 5,
                           min_samples_leaf = 4,max_features = 'auto',max_depth = 5,bootstrap = True)
RF.fit(train_features,train_labels)
predictions = RF.predict(test_features)

RMSE = np.sqrt(mean_squared_error(test_labels,predictions))

print('模型預(yù)測誤差:',RMSE)
print('模型的提升效果:{}'.format(round(100*(5.06-4.96)/5.06),2),'%')

模型預(yù)測誤差: 4.966401154246091
模型的提升效果:2 %

6.使用GridSearhCV對參數(shù)進(jìn)行進(jìn)一步優(yōu)化

上一步基本上確定了參數(shù)的大概范圍,這一步我們在該范圍,進(jìn)行更加細(xì)致的搜索。網(wǎng)格搜索的效率比較低,這里我只選擇了少數(shù)的幾個參數(shù),但是用時也達(dá)到了9分鐘。如果參數(shù)增加,模型訓(xùn)練的時間將會大幅增加。

from sklearn.model_selection import GridSearchCV
import time

param_grid = {'n_estimators':[1100,1200,1300],
             'min_samples_split':[4,5,6,7],
             'min_samples_leaf':[3,4,5],
             'max_depth':[4,5,6,7]}
RF = RandomForestRegressor()
grid = GridSearchCV(RF,param_grid = param_grid,scoring = 'neg_mean_squared_error',cv = 3,n_jobs = -1)
start_time = time.time()
grid.fit(train_features,train_labels)
end_time = time.time()
print('模型訓(xùn)練用時:{}'.format(end_time - start_time))
模型訓(xùn)練用時:534.4072196483612

獲得grid模型最好的參數(shù)

grid.best_params_
{'max_depth': 5,
 'min_samples_leaf': 5,
 'min_samples_split': 6,
 'n_estimators': 1100}

將最好的模型參數(shù)傳給RF模型,再次對數(shù)據(jù)進(jìn)行訓(xùn)練并作出預(yù)測。

RF = RandomForestRegressor(n_estimators = 1100,min_samples_split = 6,
                           min_samples_leaf = 5,max_features = 'auto',max_depth = 5,bootstrap = True)
RF.fit(train_features,train_labels)
predictions = RF.predict(test_features)

RMSE = np.sqrt(mean_squared_error(test_labels,predictions))

print('模型預(yù)測誤差:',RMSE)
模型預(yù)測誤差: 4.969890784882202

從結(jié)果來看,模型效果并沒有什么提升,說明在隨機(jī)搜索的過程中,已經(jīng)找到了最優(yōu)參數(shù)。最終結(jié)果模型預(yù)測的溫度與實際溫度相差4.96華氏度(2.75℃)。我們以該數(shù)據(jù)集作為一個示例,總結(jié)數(shù)據(jù)挖掘的全過程以及RandomizedSearchCV工具,在具體的調(diào)參工作中也是通過一步一步去優(yōu)化參數(shù),不斷縮小預(yù)測值與真實值之間的誤差。


prediction result.png

7.總結(jié)

  • 1.隨機(jī)參數(shù)選擇模型(RandomizedSearchCV)可以幫助我們快速的確定參數(shù)的范圍。
  • 2.對于隨機(jī)參數(shù)選擇模型而言,初始的特征空間選擇特別重要。如果出事的特征空間選擇不對,則后面的調(diào)參工作都可能是徒勞。我們可參考一些經(jīng)驗值或者做一些對比試驗,來確定模型的參數(shù)空間。
  • 3.RandomizedSearchCV和GridSearchCV搭配使用,先找大致范圍,再精確搜索。
  • 4.通過優(yōu)化模型參數(shù),雖然每次的提升幅度不是很大,但是通過多次的優(yōu)化,這些小的提升累加在一起就是很大的提升。
  • 5.遇到不懂的問題,多查看sklearn官方文檔,這是一個逐漸積累和提升的過程。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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