溫度預測示例&參數優化工具RandomizedSearchCV

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


data mining.jpg

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

這一小節,我們以隨機森林模型作為例子,通過演示一個完整的建模過程,來說明RandomizedSearchCV的用法。當然這個工具不是隨機森林特有的,它可以應用于任何模型的參數優化當中。

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

RandomForestRegressor.png

從上圖可以看出隨機森林模型有很多參數,如:n_estimators, max_depth, min_samples_split, min_samples_leaf,max_features,bootstrap等。每一個參數都會對最終結果產生影響,同時每一個參數又有著眾多的取值,我們的目標是找到最優的參數組合,使得我們的模型效果最好。

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

RandomizedSearchCV.png

RandomizedSearchCV參數說明:

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

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

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

任務目標:基于昨天和前天的一些歷史天氣數據,建立模型,預測當天的最高的真實溫度。

數據集中主要特征說明:

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

建模完整過程演示:

#導入數據分析的兩大工具包
import numpy as np
import pandas as pd

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

1.數據預處理

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

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

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

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

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

2.數據切分

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

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

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

print('訓練特征的規模:',train_features.shape)
print('訓練標簽的規模:',train_labels.shape)
print('測試特征的規模:',test_features.shape)
print('測試標簽的規模:',test_labels.shape)

#切分之后的結果
訓練特征的規模: (1533, 6)
訓練標簽的規模: (1533,)
測試特征的規模: (658, 6)
測試標簽的規模: (658,)

3.建立初始隨機森林模型

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

from sklearn.ensemble import RandomForestRegressor

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

4.模型評估

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


MSE.png

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

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

5.RandomizdSearchCV參數優化

from sklearn.model_selection import RandomizedSearchCV

RF = RandomForestRegressor()
#設置初始的參數空間
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]
#將參數整理為字典格式
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)
#使用該模型訓練數據
random_model.fit(train_features,train_labels)
Random_model fit process.png

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

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

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

將得出的最優參數,傳給RF模型,再次訓練參數,并進行結果預測??梢钥吹浇涍^參數優化后,模型的效果提升了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('模型預測誤差:',RMSE)
print('模型的提升效果:{}'.format(round(100*(5.06-4.96)/5.06),2),'%')

模型預測誤差: 4.966401154246091
模型的提升效果:2 %

6.使用GridSearhCV對參數進行進一步優化

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

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('模型訓練用時:{}'.format(end_time - start_time))
模型訓練用時:534.4072196483612

獲得grid模型最好的參數

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

將最好的模型參數傳給RF模型,再次對數據進行訓練并作出預測。

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('模型預測誤差:',RMSE)
模型預測誤差: 4.969890784882202

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


prediction result.png

7.總結

  • 1.隨機參數選擇模型(RandomizedSearchCV)可以幫助我們快速的確定參數的范圍。
  • 2.對于隨機參數選擇模型而言,初始的特征空間選擇特別重要。如果出事的特征空間選擇不對,則后面的調參工作都可能是徒勞。我們可參考一些經驗值或者做一些對比試驗,來確定模型的參數空間。
  • 3.RandomizedSearchCV和GridSearchCV搭配使用,先找大致范圍,再精確搜索。
  • 4.通過優化模型參數,雖然每次的提升幅度不是很大,但是通過多次的優化,這些小的提升累加在一起就是很大的提升。
  • 5.遇到不懂的問題,多查看sklearn官方文檔,這是一個逐漸積累和提升的過程。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374