1. 程式人生 > >100天搞定機器學習|Day56 隨機森林工作原理及調參實戰(信用卡欺詐預測)

100天搞定機器學習|Day56 隨機森林工作原理及調參實戰(信用卡欺詐預測)

本文是對100天搞定機器學習|Day33-34 隨機森林的補充

前文對隨機森林的概念、工作原理、使用方法做了簡單介紹,並提供了分類和迴歸的例項。
本期我們重點講一下:
1、整合學習、Bagging和隨機森林概念及相互關係
2、隨機森林引數解釋及設定建議
3、隨機森林模型調參實戰
4、隨機森林模型優缺點總結

整合學習、Bagging和隨機森林

整合學習

整合學習並不是一個單獨的機器學習演算法,它通過將多個基學習器(弱學習器)進行結合,最終獲得一個強學習器。這裡的弱學習器應該具有一定的準確性,並且要有多樣性(學習器之間具有差異),比較常用的基學習器有決策樹和神經網路。

整合學習的核心就是如何產生並結合好而不同的基學習器,這裡有兩種方式是,一種是Bagging,基學習器之間沒有強依賴關係,可同時生成的並行化方法。一種是Boosting,基學習器之間有強依賴關係,必須序列生成。
整合學習另一個關鍵問題是結合策略,主要有平均法、投票法和學習法,這裡不再展開。

Bagging

Bagging是Bootstrap AGGregaING的縮寫,Bootstrap即隨機取樣,比如給定含有$m$個樣本的資料集$D$,每次隨機的從中選擇一個樣本,放入新的資料集,然後將其放回初始資料集$D$,放回後有可能繼續被採集到,重複這個動作$m$次,我們就得到新的資料集$D'$。

用這種方式,我們可以取樣出TGE含m個訓練樣本的取樣集,然後基於每個取樣集訓練基學習器,再將基學習器進行結合,這便是Bagging的基本流程。

隨機森林
隨機森林是非常具有代表性的Bagging整合演算法,它在Bagging基礎上進行了強化。
它的所有基學習器都是CART決策樹,傳統決策樹在選擇劃分屬性時是在當前結點的屬性集合(假定有d個屬性)中選擇最優屬性。但是隨機森林的決策樹,現在每個結點的屬性集合隨機選擇部分k個屬性的子集,然後在子集中選擇一個最優的特徵來做決策樹的左右子樹劃分,一般建議$k=log_2d$.分類決策樹組成的森林就叫做隨機森林分類器,迴歸決策樹所整合的森林就叫做隨機森林迴歸器。

RF的演算法:

輸入為樣本集$D={(x_,y_1),(x_2,y_2), ...(x_m,y_m)}$,弱分類器迭代次數T。

輸出為最終的強分類器$f(x)$

1)對於t=1,2...,T:
a)對訓練集進行第t次隨機取樣,共採集m次,得到包含m個樣本的取樣集Dt
b)用取樣集$D_t$訓練第t個決策樹模型$G_t(x)$,在訓練決策樹模型的節點的時候, 在節點上所有的樣本特徵中選擇一部分樣本特徵, 在這些隨機選擇的部分樣本特徵中選擇一個最優的特徵來做決策樹的左右子樹劃分

2)如果是分類演算法預測,則T個弱學習器投出最多票數的類別或者類別之一為最終類別。如果是迴歸演算法,T個弱學習器得到的迴歸結果進行算術平均得到的值為最終的模型輸出。

隨機森林引數解釋及設定建議

在scikit-learn中,RandomForest的分類類是RandomForestClassifier,迴歸類是RandomForestRegressor,需要調參的引數包括兩部分,第一部分是Bagging框架的引數,第二部分是CART決策樹的引數。這裡我們看一下scikit-learn中隨機森林的主要引數

隨機森林模型調參實戰

這是一道kaggle上的題目,通過信用卡交易記錄資料對欺詐行為進行預測,信用卡欺詐檢測檔案記錄了2013年9月歐洲信用卡持有者所發生的交易。在284807條交易記錄中共包含492條欺詐記錄。
資料集下載地址:請在公眾號後臺回覆[56]
需要說明的是,本文重點是RF模型調參,所以不涉及資料預處理、特徵工程和模型融合的內容,這些我會在本欄目未來的章節中再做介紹。
所以最終結果可能會不理想,這裡我們只關注通過調參給模型帶來的效能提升和加深對重要引數的理解即可。
1、匯入用到的包

import numpy as np
import pandas as pd
from sklearn.model_selection import GridSearchCV,train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import roc_auc_score

2、匯入資料

df = pd.read_csv("D:\WKS\PyProject\Credit_Card\creditcard.csv")
data=df.iloc[:,1:31]

284807條交易記錄中只有492條欺詐記錄,樣本嚴重不平衡,這裡我們需要使用下采樣策略(減少多數類使其數量與少數類相同)

X = data.loc[:, data.columns != 'Class']
y = data.loc[:, data.columns == 'Class']

number_records_fraud = len(data[data.Class == 1]) # class=1的樣本函式
fraud_indices = np.array(data[data.Class == 1].index) # 樣本等於1的索引值

normal_indices = data[data.Class == 0].index # 樣本等於0的索引值

random_normal_indices = np.random.choice(normal_indices,number_records_fraud,replace = False)
random_normal_indices = np.array(random_normal_indices)

under_sample_indices = np.concatenate([fraud_indices,random_normal_indices]) # Appending the 2 indices

under_sample_data = data.iloc[under_sample_indices,:] # Under sample dataset

X_undersample = under_sample_data.loc[:,under_sample_data.columns != 'Class']
y_undersample = under_sample_data.loc[:,under_sample_data.columns == 'Class']

X_train, X_test, y_train, y_test = train_test_split(X_undersample,y_undersample,test_size = 0.3, random_state = 0)

先用預設引數訓練RF

rf0 = RandomForestClassifier(oob_score=True, random_state=666)
rf0.fit(X_train,y_train)
print(rf0.oob_score_)
y_predprob = rf0.predict_proba(X_test)[:,1]
print("AUC Score (Train): %f" % roc_auc_score(y_test, y_predprob))

0.9244186046511628
AUC Score (Train): 0.967082
除oob_score將預設的False改為True, 我們重點優化n_estimators、max_depth、min_samples_leaf 這三個引數。為簡單起見,模型評價指標,我們選擇AUC值。
模型調優我們採用網格搜尋調優引數(grid search),通過構建引數候選集合,然後網格搜尋會窮舉各種引數組合,根據設定評定的評分機制找到最好的那一組設定。
先優化n_estimators

param_test1 = {'n_estimators':range(10,101,10)}
gsearch1 = GridSearchCV(estimator = RandomForestClassifier(oob_score=True, random_state=666,n_jobs=2), 
                       param_grid = param_test1, scoring='roc_auc',cv=5)
gsearch1.fit(X_train,y_train)
gsearch1.cv_results_, gsearch1.best_params_, gsearch1.best_score_

{'n_estimators': 50},
0.9799524239675649)
在優化後的n_estimators基礎上,優化max_features

param_test2 = {'max_depth':range(2,12,2)}
gsearch2 = GridSearchCV(estimator = RandomForestClassifier(n_estimators= 50,oob_score=True, random_state=666,n_jobs=2),
   param_grid = param_test2, scoring='roc_auc',cv=5)
gsearch2.fit(X_train,y_train)
gsearch2.cv_results_, gsearch2.best_params_, gsearch2.best_score_

{'max_depth': 6},
0.9809897227343921)
在上述兩個引數優化結果的基礎上優化max_depth

param_test2 = {'min_samples_split':range(2,8,1)}
gsearch2 = GridSearchCV(estimator = RandomForestClassifier(n_estimators= 50,max_depth=6,
                                  oob_score=True, random_state=666,n_jobs=2),
   param_grid = param_test2, scoring='roc_auc',cv=5)
gsearch2.fit(X_train,y_train)
gsearch2.cv_results_, gsearch2.best_params_, gsearch2.best_score_

{'min_samples_split': 5},
0.9819618127837587)

最後我們綜合再次嘗試

rf1 = RandomForestClassifier(n_estimators= 50,max_depth=6,min_samples_split=5,oob_score=True, random_state=666,n_jobs=2)
rf1.fit(X_train,y_train)
print(rf1.oob_score_)
y_predprob1 = rf1.predict_proba(X_test)[:,1]
print("AUC Score (Train): %f" % roc_auc_score(y_test, y_predprob1))

0.9331395348837209
AUC Score (Train): 0.977811
最終結果比調參前有所提升

隨機森林優缺點總結

RF優點
1.不容易出現過擬合,因為選擇訓練樣本的時候就不是全部樣本。
2.可以既可以處理屬性為離散值的量,比如ID3演算法來構造樹,也可以處理屬性為連續值的量,比如C4.5演算法來構造樹。
3.對於高維資料集的處理能力令人興奮,它可以處理成千上萬的輸入變數,並確定最重要的變數,因此被認為是一個不錯的降維方法。此外,該模型能夠輸出變數的重要性程度,這是一個非常便利的功能。
4.分類不平衡的情況時,隨機森林能夠提供平衡資料集誤差的有效方法
RF缺點
1.隨機森林在解決迴歸問題時並沒有像它在分類中表現的那麼好,這是因為它並不能給出一個連續型的輸出。當進行迴歸時,隨機森林不能夠作出超越訓練集資料範圍的預測,這可能導致在對某些還有特定噪聲的資料進行建模時出現過度擬合。
2.對於許多統計建模者來說,隨機森林給人的感覺像是一個黑盒子——你幾乎無法控制模型內部的執行,只能在不同的引數和隨機種子之間進行嘗試。

參考:

https://www.jianshu.com/p/708dff71df3a
https://zhuanlan.zhihu.com/p/30461746
https://www.cnblogs.com/pinard/p/6156009.html

《百面機器學習》中有一道關於隨機森林的面試題,大家可以思考一下:
可否將隨機森林中的基分類器由決策樹替換為線性分類器或K-近鄰呢?

解答:隨機森林屬於Bagging類的整合學習,Bagging的主要好處是整合後的分類器的方差比基分類器方差小。Bagging採用的分類器最好是本身對樣本分佈比較敏感(即不穩定的分類器),這樣Bagging才有價值。線性分類器或K-近鄰都是比較穩定,本身方差就很小,所以以他們作為基分類器使用Bagging並不能獲得更好地表現,甚至可能因為Bagging的取樣導致訓練中更難收斂,從而增大整合分類器的偏差。

本文由部落格一文多發平臺 OpenWrite 釋出!