作者:chen_h
微信號 & QQ:862251340
微信公眾號:coderpai
(一)機器學習中的集成學習入門
(二)bagging 方法
(三)使用Python進行交易的隨機森林算法
(四)Python中隨機森林的實現與解釋
通過從單個決策樹構建來使用和理解隨機森林
幸運的是,對于像Scikit-Learn這樣的庫,現在很容易在Python中實現數百種機器學習算法。這很容易,我們通常不需要任何關于模型是如何工作的知識來使用它。雖然不需要知道所有細節,但了解機器學習模型如何工作仍然是非常有幫助的。這使我們可以在模型表現不佳時進行修改參數,或解釋模型如何做出決策,如果我們想要說服別人相信我們的模型,這是至關重要的。
在本文中,我們將介紹如何在Python中構建和使用Random Forest。除了查看代碼之外,我們還將嘗試了解此模型的工作原理。因為由許多決策樹組成的隨機森林,我們首先要了解單個決策樹如何對一個簡單的問題進行分類。然后,我們將努力使用隨機森林來解決現實世界的數據科學問題。
理解決策樹
決策樹是隨機森林的構建塊,是一種非常直觀的模型。我們可以將決策樹視為一系列對我們數據進行是/否分類的問題。這是一個可解釋的模型,因為它可以像我們人類一樣進行分類:在我們做出決定之前(在理想世界中),我們會詢問有關可用數據的一系列查詢,或者一系列特征。
在CART算法中,通過確定特征(稱為節點的分裂)來構建決策樹,這些特征在經過節點的時候通過Gini指數來進行判斷。我們稍后會詳細討論關于Gini 指數的細節,但首先,讓我們構建一個決策樹,以便我們能夠在高層次上理解它。
關于簡單問題的決策樹
我們將從一個非常簡單的二分類問題開始,如下所示:
我們的數據只有特征,x1 和 x2,圖中有 6 個數據樣本,分為兩個標簽 0 和 1。雖然這個問題非常簡單,但它是線性不可分的,這意味著我們不能通過數據繪制一條直線來對數據進行分類。
然而,我們可以繪制一系列直線,將數據點分成多個框,我們稱之為節點。實際上,這就是決策樹在訓練期間所進行的操作。簡單的說,決策樹就是通過構造很多線性邊界來構造的非線性模型。
為了創建決策樹并在數據上進行訓練,我們使用 sklearn 來進行。
from
sklearn
.
tree
import
DecisionTreeClassifier
# Make a decision tree and train
tree
=
DecisionTreeClassifier
(
random_state
=
RSEED
)
tree
.
fit
(
X
,
y
)
在訓練期間,我們為模型提供特征和標簽,以便它可以根據特征進行學習,然后分類。然后,我們可以在訓練數據上面對我們的模型進行測試。PS:因為我們沒有測試數據。
print
(
f
'Model Accuracy: {tree.score(X, y)}'
)
Model Accuracy
:
1.0
我們看到它獲得了100%的準確性,這也正是我們所期望的,因為我們給了它訓練的數據,并且沒有限制樹的深度。 事實證明,完全學習訓練數據的能力可能是決策樹的缺點,因為它可能會導致過度擬合,這一點我們稍后會討論。
可視化決策樹
那么,當我們訓練決策樹時,實際上是在發生一些什么變化呢?我們找到一種可視化方法來理解決策樹,我們可以通過 scikit-learn 中的函數,如下:
除了葉子節點,所有節點都有五個部分:
- 基于特征的查詢,每個分裂節點都會給出真或者假的答案,根據答案,數據點向下移動到樹上;
- gini:節點的 gini 指數。當我們向下移動時,平均加權的gini指數會減?。?
- samples:節點中的觀察數;
- value:每個類中的樣本數。例如,頂部節點在類 0 中有2個樣本,在類1中有4個樣本;
- class:節點中點的多數分類。在葉子節點中,這就是對節點中所有樣本的預測了;
對于葉子節點的理解肯定沒有問題,因為這些是最終預測的地方。要對新的數據點進行分類,我們只需要將數據點進行下移就行了,使用點的特征來回答問題,直到到達類是預測的葉節點。
為了以不同的方式查看樹,我們可以在原始數據上繪制決策樹構建的分割。
每個拆分就是一條線,根據特征值將數據點劃分為節點。對于這個簡單的問題,我們并沒有對最大深度進行限制,分區將節點中的每個點僅放置在同一類的點上。稍后我們將看到訓練數據的這種完美劃分可能不是我們想要的,因為它可能導致過度擬合。
gini 不純度
在這一節上,我們會深入了解基尼不純度的概念。節點的Gini不純度是指節點中隨機選擇的樣本如果被標記錯誤的概率,其實也就是節點中樣本的分布。例如,在頂部節點中,Gini不純度為 44.4% 。我們使用以下等式得出這個值:
節點 n 的Gini不純度是 1 減去每個類概率平方的總和。這個聽起來可能會有點困惑,那么我們就以根節點來做一個例子:
在每個節點處,決策樹在特征中進行拆解,從而最大限度的減少GIni不純度。
然后,它以貪婪的遞歸過程重復此拆分過程,直到達到最大深度,或者每個節點僅包含來自一個類的樣本。 每層樹木的加權總Gini不純度必須減少。 在樹的第二層,總加權基尼雜質值為0.333:
最終,最后一層的加權總 Gini 不純度變為 0 ,意味著每個節點都是純粹的,并且從該節點隨機選擇的點不會被錯誤分類。雖然這似乎是非常好的,但這意味著該模型可能過度擬合了,因為節點僅適用訓練數據構建。
過度擬合:為什么森林比一棵樹好
您可能會想問為什么不使用一個決策樹?它似乎是完美的分類器,因為它沒有犯任何錯誤!沒有分錯一個數據。但要記住的關鍵點是這個樹是在訓練數據上沒有犯錯。機器學習模型的目標是很好地概括它以前從未見過的新數據。
當我們具有非常靈活的模型(模型具有高容量)時,就會發生過度擬合,因為它基本上就是通過緊密擬合訓練數據來生成模型的。問題是模型不僅學習訓練數據中的實際關系,還學習任何存在的噪聲。靈活模型具有高方差,因為學習參數(例如決策樹的結構)將隨著訓練數據而顯著變化。
另一方面,一個不靈活的模型被認為具有很高的偏差,因為它對訓練數據做出了假設(它偏向于預先設想的數據思想。)例如,線性分類器假設數據是線性的,不具備適應非線性關系的靈活性。一個不靈活的模型可能無法適應訓練數據,在這兩種情況下,高方差和高偏差,那么模型無法很好地推廣到新數據。
當我們不限制最大深度時,決策樹非常容易過度擬合的原因是因為它具有無限的靈活性,這意味著它可以保持無限增長,直到它一個葉節點只有一個類別,完美地對所有這些進行分類。 如果您返回到決策樹的圖像并將最大深度限制為2(僅進行一次拆分),則分類不再100%正確。 我們減少了決策樹的方差,但代價是增加了偏差。
我們為了限制樹的深度,我們可以將許多決策樹組合成稱為隨機森林的單個集合模型。那么就會減少方差(好)并增加偏差(差)。
隨機森林
隨機森林是由許多決策樹組成的模型。 這個模型不是簡單地平均樹的預測(我們可以稱之為“森林”),而是使用兩個關鍵概念,使其名稱為隨機:
- 在構建樹時對訓練數據點進行隨機抽樣
- 分割節點時考慮的隨機特征子集
隨機抽樣訓練數據
在訓練時,隨機森林中的每棵樹都會從數據點的隨機樣本中學習。 樣本用替換采樣,稱為自舉,這意味著一些樣本將在一棵樹中多次使用。 這個想法是通過對不同樣本的每棵樹進行訓練,盡管每棵樹相對于一組特定的訓練數據可能具有很大的差異,但總體而言,整個森林的方差較小,但不會以增加偏差為代價。
在測試時,通過平均每個決策樹的預測來進行預測。 這種在不同的數據子集上訓練每個學習器然后對預測求平均值的過程稱為bagging,是 bootstrap aggregating的縮寫。
用于拆分節點的隨機特征子集
隨機林中的另一個主要概念是,僅考慮所有特征的子集來分割每個決策樹中的每個節點。 通常,這被設置為sqrt(n_features)用于分類,這意味著如果有16個特征,則在每個樹中的每個節點處,將僅考慮4個隨機特征來分割節點。 (隨機林也可以考慮每個節點的所有特征,在回歸中比較常用。這些選項可以在Scikit-Learn Random Forest實現中控制)。
如果你能理解一個決策樹,bagging的想法,以及隨機的特征子集,那么你對隨機森林的工作方式有了很好的理解:
隨機森林將數百或數千個決策樹組合在一起,在略微不同的訓練集上訓練每個決策樹,考慮到有限數量的特征,在每棵樹中分割節點。 隨機森林的最終預測是通過平均每個樹的預測來做出的。
要理解為什么隨機森林優于單一決策樹時,請想象以下情況:您必須決定特斯拉股票是否會上漲,并且您可以訪問十幾位對該公司沒有先驗知識的分析師。每個分析師都有較低的偏差,因為他們沒有任何假設,并且可以從新聞報道的數據集中學習。
這似乎是一個理想的情況,但問題是報告除了真實信號之外可能還包含噪聲。因為分析師完全根據數據做出預測 - 他們具有很高的靈活性 - 他們可能會被無關的信息所左右。分析師可能會從同一數據集中得出不同的預測。此外,如果給出不同的報告訓練集,每個單獨的分析師都有很大的差異,并會提出截然不同的預測。
解決方案是不依賴于任何一個人,而是匯集每個分析師的投票分析結果。此外,與隨機森林一樣,允許每個分析人員僅訪問報告的一部分,并希望通過采樣取消噪聲信息的影響。在現實生活中,我們依賴于多種來源(絕不相信亞馬遜的獨立評論),因此,決策樹不僅直觀,而且在隨機森林中將它們組合在一起的想法也是如此。
隨機森林實踐
接下來,我們將使用 Scikit-Learn 在 Python 中構建一個隨機森林。 我們將使用分為訓練和測試集的真實數據集,而不是學習一個簡單的問題。 我們使用測試集作為模型對新數據的執行方式的估計,這也可以讓我們確定模型過度擬合的程度。
數據集
我們要解決的問題是二元分類任務,其目標是預測個人的健康狀況。 這些特征是個人的社會經濟和生活方式特征,健康狀況不佳的標簽為0,健康狀況為1。 該數據集由疾病控制和預防中心收集,可在此處獲取(https://www.kaggle.com/cdc/behavioral-risk-factor-surveillance-system)。
通常,數據科學項目的80%的時間用于清理,探索和制作數據中的特征。 但是,對于本文,我們將直接使用建模。 這是一個不平衡的分類問題,因此準確性不是一個合適的指標。 相反,我們利用 ROC AUC進行評估,從0(最差)到1(最佳)的度量,隨機猜測得分為0.5。 我們還可以繪制ROC曲線以評估模型。
接下來我們開始學習隨機森林代碼,如下:
from
sklearn
.
ensemble
import
RandomForestClassifier
# Create the model with 100 trees
model
=
RandomForestClassifier
(
n_estimators
=
100
,
bootstrap
=
True
,
max_features
=
'sqrt'
)
# Fit on training data
model
.
fit
(
train
,
train_labels
)
在訓練幾分鐘后,模型準備好對測試數據進行如下預測:
# Actual class predictions
rf_predictions
=
model
.
predict
(
test
)
# Probabilities for each class
rf_probs
=
model
.
predict_proba
(
test
)
[
:
,
1
]
我們進行類別預測以及預測概率(predict_proba)來計算ROC AUC。 一旦我們有了測試預測,我們就可以計算出ROC AUC。
from sklearn.metrics import roc_auc_score
# Calculate roc auc
roc_value = roc_auc_score(test_labels, rf_probs)
結果
隨機森林的最終測試ROC AUC為0.87,而具有無限最大深度的單一決策樹的最終測試ROC AUC為0.67。 如果我們查看訓練分數,兩個模型都達到了1.0 的 ROC AUC,這也是預期的,因為我們給這些模型提供了訓練標簽,并沒有限制每棵樹的最大深度。
雖然隨機森林過度擬合(在訓練數據上比在測試數據上做得更好),但它能夠比單一決策樹更好地推廣測試數據。 隨機森林具有較低的方差(良好),同時保持決策樹的相同低偏差(也很好)。
我們還可以繪制單個決策樹(頂部)和隨機森林(底部)的ROC曲線。 頂部和左側的曲線是更好的模型:
上面是決策樹的 ROC
上圖是隨機森林的 ROC
我們可以采用模型的另一個評估方法,混淆矩陣:
這顯示模型在左上角和右下角正確的預測以及模型在左下角和右上角錯誤的預測。 我們可以使用這些圖來診斷我們的模型,并確定它是否做得足夠好以投入生產。
特征重要性
隨機林中的特征重要性表示在該特征在拆分的所有節點上Gini不純度減少的總和。 我們可以使用這些來嘗試找出隨機森林認為最重要的預測特征。 可以從訓練好的隨機森林中提取重要的特征,并將其放入Pandas數據框中,如下所示:
import
pandas
as
pd
# Extract feature importances
fi
=
pd
.
DataFrame
(
{
'feature'
:
list
(
train
.
columns
)
,
'importance'
:
model
.
feature_importances_
}
)
.
\
sort_values
(
'importance'
,
ascending
=
False
)
# Display
fi
.
head
(
)
feature importance
DIFFWALK
0.036200
QLACTLM2
0.030694
EMPLOY1
0.024156
DIFFALON
0.022699
USEEQUIP
0.016922
特征重要性告訴我們哪些特征在類之間最具辨別力,可以讓我們深入了解問題。 例如,這里指示患者是否行走困難的 DIFFWALK 特征是最具有意義的特征。
通過構建最重要的特征分析,我們可以通過刪除低重要性的特征,使用高重要性的特征來進行學習。
可視化隨機森林
最后,我們可以在森林中可視化單個決策樹。 這次,我們必須限制樹的深度,否則它將太大而無法轉換為圖像。 為了得到下圖,我將最大深度限制為6.這仍然導致我們無法完全解析大樹! 然而,鑒于我們深入研究決策樹,我們掌握了模型的工作原理。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
