【實戰(zhàn)篇】隨機森林預測氣溫(三)

本篇文章是隨機森林氣溫預測任務的最后一篇文章啦袋哼,本文我們的主要內容就是 調參。前面在介紹隨機森林算法的時候第焰,我們知道在建立樹模型的時候果录,我們通常會使用預剪枝策略上枕,邊建立決策樹邊限制樹的復雜度,以防止樹模型出現(xiàn)過擬合的現(xiàn)象弱恒。

接下來辨萍,我們調參的參數(shù)大部分都是和預剪枝策略相關的,比如樹的深度返弹、葉子節(jié)點的個數(shù)锈玉、切分的最小樣本數(shù)、葉子節(jié)點最小樣本個數(shù)等等义起。話不多說拉背,一起來開始今天的學習吧~

數(shù)據(jù)集讀取、預處理和切分

讀取數(shù)據(jù)集:

import pandas as pd
import os

df = pd.read_csv("data" + os.sep + "temps_extended.csv")
df.head()

數(shù)據(jù)特征這里就不介紹了默终,前面的文章我們已經(jīng)詳細地討論過特征啦~

進行度熱編碼椅棺、數(shù)據(jù)集切分:

import numpy as np
from sklearn.model_selection import train_test_split


def get_train_test(df):
    data = pd.get_dummies(df)
    y = data.actual
    X = data.drop('actual',axis=1)
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=0)
    
    return X_train, X_test, y_train, y_test

X_train, X_test, y_train, y_test = get_train_test(df)

訓練集和測試集樣本情況:

>> X_train.shape, X_test.shape
((1643, 17), (548, 17))

在開始調參前,我們需要先看看隨機森林 RandomForestRegressor 有哪些參數(shù):

>> from sklearn.ensemble import RandomForestRegressor
>> rfr = RandomForestRegressor(random_state=0)
>> rfr.get_params()
{'bootstrap': True,
 'ccp_alpha': 0.0,
 'criterion': 'squared_error',
 'max_depth': None,
 'max_features': 'auto',
 'max_leaf_nodes': None,
 'max_samples': None,
 'min_impurity_decrease': 0.0,
 'min_samples_leaf': 1,
 'min_samples_split': 2,
 'min_weight_fraction_leaf': 0.0,
 'n_estimators': 100,
 'n_jobs': None,
 'oob_score': False,
 'random_state': 0,
 'verbose': 0,
 'warm_start': False}

我們接下來的調參主要選擇其中比較重要的幾個:

  • max_depth:樹的深度
  • max_features:選取的特征個數(shù)
  • min_samples_leaf:葉子節(jié)點包含的最少樣本數(shù)
  • min_samples_split:切分節(jié)點時的最少樣本數(shù)
  • n_estimators:隨機森林中樹的個數(shù)

下面的調參工作齐蔽,小魚也將圍繞這 5 個特征展開两疚。

RandomizedSearchCV 隨機搜索

在開始任務之前,首先選擇一個大致的合適區(qū)間作為參數(shù)空間:

n_estimators = [int(x) for x in np.linspace(50, 1000, 5)]
max_depth = [int(x) for x in np.linspace(10, 30, 5)]
max_features = [6, 8, 10, 12, 16]
min_samples_split = [2, 5, 9, 13, 17]
min_samples_leaf = [1, 4, 7, 10, 13]

random_grid = {
    "n_estimators": n_estimators,
    "max_depth": max_depth,
    "min_samples_split": min_samples_split,
    "min_samples_leaf": min_samples_leaf,
    "max_features": max_features
}

輸出:

>> random_grid
{'n_estimators': [50, 287, 525, 762, 1000],
 'max_depth': [10, 15, 20, 25, 30],
 'min_samples_split': [2, 5, 9, 13, 17],
 'min_samples_leaf': [1, 4, 7, 10, 13],
 'max_features': [6, 8, 10, 12, 16]}

對于每個參數(shù)含滴,小魚都列出了 5 個取值诱渤,參數(shù)有 5 個,一共會產(chǎn)生 5**5 = 3125 種組合蛙吏,再加上個 3 折的交叉驗證源哩,那么一共就需要訓練 9375 個模型,這樣我們調參的效率也就太低了鸦做。

那有什么辦法可以解決效率問題呢励烦?

答案就是 RandomizedSearchCV,這個函數(shù)可以幫助我們在候選集組合中泼诱,隨機地選擇幾組合適的參數(shù)來建模坛掠,并且求其交叉驗證后的評估結果。以此來大致地找到一個最合適的參數(shù)治筒。

這樣不我們就不需要訓練 9375 個模型屉栓,找到最優(yōu)的參數(shù)組合了。比如隨機選擇其中的 200 組參數(shù)耸袜,并進行 3 折交叉驗證友多,那么一共只需要訓練 600 個模型。

下面是代碼部分:

from sklearn.model_selection import RandomizedSearchCV

# 隨機選擇最合適的參數(shù)組合
rf = RandomForestRegressor(random_state=0)
rf_random = RandomizedSearchCV(
    estimator=rf, 
    param_distributions=random_grid, 
    n_iter=100, 
    scoring="neg_mean_absolute_error", 
    cv=3, 
    verbose=2, 
    random_state=0, 
    n_jobs=-1
)
rf_random.fit(X_train, y_train)

RandomizedSearchCV 參數(shù)說明:

  • estimatorRandomizedSearchCV 這個方法是一個通用的堤框,并不是專為隨機森林設計的域滥,所以我們需要指定選擇的算法模型是什么纵柿。
  • distributions:參數(shù)的候選空間,就是我們用字典格式給出的參數(shù)候選值启绰。
  • n_iter:隨機尋找參數(shù)組合的個數(shù)昂儒,比如在這里我們賦值了 100,代表接下來要隨機找 100 組參數(shù)的組合委可,然后在其中找到最好的一組渊跋。
  • scoring:模型的評估方法,即按照該方法去找到最好的參數(shù)組合着倾。
  • cv:幾折交叉驗證拾酝。
  • random_state:隨機種子,為了使得咱們的結果能夠一致屈呕,排除掉隨機成分的干擾微宝,一般我們都會指定成一個值。
  • n_jobs:多進程訓練虎眨,如果是 -1 就會用所有的 CPU蟋软。

輸出:

Fitting 3 folds for each of 100 candidates, totalling 300 fits
RandomizedSearchCV(cv=3, estimator=RandomForestRegressor(random_state=0),
                   n_iter=100, n_jobs=-1,
                   param_distributions={'max_depth': [10, 15, 20, 25, 30],
                                        'max_features': [6, 8, 10, 12, 16],
                                        'min_samples_leaf': [1, 4, 7, 10, 13],
                                        'min_samples_split': [2, 5, 9, 13, 17],
                                        'n_estimators': [50, 287, 525, 762,
                                                         1000]},
                   random_state=0, scoring='neg_mean_absolute_error',
                   verbose=2)

獲取最優(yōu)的參數(shù)組合:

>> rf_random.best_params_
{'n_estimators': 50,
 'min_samples_split': 5,
 'min_samples_leaf': 10,
 'max_features': 16,
 'max_depth': 25}

接下來,我們使用測試集來實際看看調參的結果如何嗽桩。定義相關函數(shù):

def predict_and_evaluate(model, x_test, y_test, print_mape=True):
    predictions = model.predict(x_test)
    # 計算誤差 MAPE (Mean Absolute Percentage Error)
    errors = abs(predictions - y_test)
    mape = errors / y_test
    if print_mape:
        print(f'MAPE:{mape.mean():.2%}')
    
    return mape.mean()

使用默認參數(shù)建模:

>> base_model = RandomForestRegressor(random_state=0)
>> base_model.fit(X_train, y_train)
>> predict_and_evaluate(base_model, X_test, y_test)
MAPE:6.65%

使用 RandomizedSearchCV 為我們找到的最優(yōu)參數(shù)組合:

>> best_random = rf_random.best_estimator_
>> predict_and_evaluate(best_random, X_test, y_test)
MAPE:6.60%

可以看到模型的效果提升了一些岳守,但是這已經(jīng)是上限了嗎?

GridSearchCV 網(wǎng)格搜索

RandomizedSearchCV 在隨機搜索時碌冶,相當于為我們鎖定了大致的范圍湿痢。接下來就要靠 GridSearchCV 在縮小后的范圍內開展地毯式搜索了,這就是網(wǎng)絡搜索扑庞,說白了就是將所有的參數(shù)組合都進行一遍譬重。

在隨機搜索時,我們得到的最優(yōu)參數(shù)組合為:

{'n_estimators': 50,
 'min_samples_split': 5,
 'min_samples_leaf': 10,
 'max_features': 16,
 'max_depth': 25}

在參數(shù)的附近罐氨,定義網(wǎng)格搜索的參數(shù)空間:

# 網(wǎng)絡搜索
param_grid = {
    'n_estimators': [50, 100, 200],
    'min_samples_split': [4, 5, 6],
    'min_samples_leaf': [9, 10, 11],
    'max_features': [15, 16, 17],
    'max_depth': [24, 25, 26]
}

進行網(wǎng)格搜索和交叉驗證:

from sklearn.model_selection import GridSearchCV

rf = RandomForestRegressor(random_state=0)
grid_search = GridSearchCV(
    estimator=rf, 
    param_grid=param_grid,
    scoring='neg_mean_absolute_error',
    cv=3, 
    n_jobs=-1,
    verbose=2
)

grid_search.fit(X_train, y_train)

輸出:

Fitting 3 folds for each of 243 candidates, totalling 729 fits
GridSearchCV(cv=3, estimator=RandomForestRegressor(random_state=0), n_jobs=-1,
             param_grid={'max_depth': [24, 25, 26],
                         'max_features': [15, 16, 17],
                         'min_samples_leaf': [9, 10, 11],
                         'min_samples_split': [4, 5, 6],
                         'n_estimators': [50, 100, 200]},
             scoring='neg_mean_absolute_error', verbose=2)

網(wǎng)格搜索最佳參數(shù)組合:

>> grid_search.best_params_
{'max_depth': 24,
 'max_features': 15,
 'min_samples_leaf': 10,
 'min_samples_split': 4,
 'n_estimators': 50}

評估:

>> predict_and_evaluate(grid_search.best_estimator_, X_test, y_test)
MAPE:6.59%

誤差下降了 0.01 個百分點臀规,改善效果不是很明顯≌ひ可以多來幾組地毯式搜索找到最優(yōu)的參數(shù)組合塔嬉。

總結

隨機搜索可以更節(jié)約時間,尤其是在任務開始階段租悄,我們并不知道哪一個參數(shù)在哪一個位置效果能更好谨究,這樣我們可以把參數(shù)間隔設置的更大一些,先用隨機搜索確定一些大致位置泣棋。

網(wǎng)絡搜索相當于地毯式搜索胶哲,當我們得到了大致位置之后,想在這里尋找到最優(yōu)參數(shù)的時候就派上用場了潭辈⊙煊欤可以把隨機和網(wǎng)絡搜索當做一套組合拳俩檬,搭配使用。

調參的方法其實還有很多碾盟,比如貝葉斯優(yōu)化。上述的調參方式技竟,每一個都是獨立的進行不會對之后的結果產(chǎn)生任何影響冰肴,貝葉斯優(yōu)化的基本思想在于每一個優(yōu)化都是在不斷積累經(jīng)驗,這樣我會慢慢得到最終的解應當在的位置榔组,相當于前一步結果會對后面產(chǎn)生影響了熙尉。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市搓扯,隨后出現(xiàn)的幾起案子检痰,更是在濱河造成了極大的恐慌,老刑警劉巖锨推,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铅歼,死亡現(xiàn)場離奇詭異,居然都是意外死亡换可,警方通過查閱死者的電腦和手機椎椰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沾鳄,“玉大人慨飘,你說我怎么就攤上這事∫胲瘢” “怎么了瓤的?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吞歼。 經(jīng)常有香客問我圈膏,道長,這世上最難降的妖魔是什么浆熔? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任本辐,我火速辦了婚禮,結果婚禮上医增,老公的妹妹穿的比我還像新娘慎皱。我一直安慰自己,他們只是感情好叶骨,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布茫多。 她就那樣靜靜地躺著,像睡著了一般忽刽。 火紅的嫁衣襯著肌膚如雪天揖。 梳的紋絲不亂的頭發(fā)上夺欲,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音今膊,去河邊找鬼些阅。 笑死,一個胖子當著我的面吹牛斑唬,可吹牛的內容都是我干的市埋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼恕刘,長吁一口氣:“原來是場噩夢啊……” “哼缤谎!你這毒婦竟也來了?” 一聲冷哼從身側響起褐着,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤坷澡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后含蓉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體频敛,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年馅扣,在試婚紗的時候發(fā)現(xiàn)自己被綠了姻政。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡岂嗓,死狀恐怖汁展,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情厌殉,我是刑警寧澤食绿,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站公罕,受9級特大地震影響器紧,放射性物質發(fā)生泄漏。R本人自食惡果不足惜楼眷,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一铲汪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧罐柳,春花似錦掌腰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春勺择,著一層夾襖步出監(jiān)牢的瞬間创南,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工省核, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留稿辙,地道東北人。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓气忠,卻偏偏與公主長得像邓深,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子笔刹,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內容