Python中随机森林的实现与解释
使用像Scikit-Learn這樣的庫,現在很容易在Python中實現數百種機器學習算法。這很容易,我們通常不需要任何關于模型如何工作的潛在知識來使用它。雖然不需要了解所有細節(jié),但了解機器學習模型是如何工作的仍然有用。這使我們可以在模型表現不佳時進行診斷,或者解釋模型如何做出決策,如果我們想讓別人相信我們的模型,這是至關重要的。
在本文中,我們將介紹如何在Python中構建和使用Random Forest。除了查看代碼之外,我們還將嘗試了解此模型的工作原理。因為由許多決策樹組成的隨機森林,我們首先要了解單個決策樹如何對一個簡單的問題進行分類。然后,我們將努力使用隨機森林來解決現實世界的數據科學問題。本文的完整代碼在GitHub上以Jupyter Notebook的形式提供【1】。
理解決策
一個決策樹是一個隨機森林的基石,是一個直觀的模型。我們可以將決策樹視為一系列是/否問題,詢問我們的數據最終導致預測類(或回歸情況下的連續(xù)值)。這是一個可解釋的模型,因為它可以像我們一樣進行分類:(在理想世界中)在我們做出決定之前,我們會詢問有關可用數據的一系列問題。
決策樹的技術細節(jié)是如何形成有關數據的問題。在CART算法中,通過確定問題(稱為節(jié)點的分裂)來構建決策樹,這些問題在被回答時導致基尼雜質的最大減少。這意味著決策樹試圖通過在將數據干凈地劃分為類的特征中查找值來形成包含來自單個類的高比例樣本(數據點)的節(jié)點。
我們稍后將討論關于Gini雜質的低級細節(jié),但首先,讓我們構建一個決策樹,以便我們能夠在高層次上理解它。
關于簡單問題的決策樹
我們將從一個非常簡單的二進制分類問題開始,如下所示:
我們的數據僅具有兩個特征(預測變量),具有6個數據點,分成2個不同的標簽。雖然這個問題很簡單,但它不是線性可分的,這意味著我們不能通過數據繪制一條直線來對點進行分類。
然而,我們可以繪制一系列直線,將數據點劃分為多個框,我們稱之為節(jié)點。實際上,這就是決策樹在訓練期間所做的事情。有效地,決策樹是通過構造許多線性邊界而構建的非線性模型。
要創(chuàng)建決策樹并對數據進行訓練(fit),我們使用Scikit-Learn。
from sklearn.tree import DecisionTreeClassifier # Make a decision tree and train tree = DecisionTreeClassifier(random_state=RSEED) tree.fit(X, y)在訓練過程中,我們?yōu)槟P吞峁┨卣骱蜆撕?#xff0c;以便學習根據特征對點進行分類。(我們沒有針對這個簡單問題的測試集,但在測試時,我們只為模型提供功能并讓它對標簽進行預測。)
我們可以在訓練數據上測試我們模型的準確性:
print(fModel Accuracy: {tree.score(X, y)}) Model Accuracy: 1.0我們看到它獲得100%的準確性,這是我們所期望的,因為我們提供了訓練的答案(y)并沒有限制樹的深度。事實證明,完全學習訓練數據的能力可能是決策樹的缺點,因為它可能會導致過度擬合,我們稍后會討論。
視化決策樹
那么當我們訓練決策樹時,實際上會發(fā)生什么?我找到了一種有用的方法來理解決策樹是通過可視化來實現的,我們可以使用Scikit-Learn函數。
除葉子節(jié)點(彩色終端節(jié)點)外,所有節(jié)點都有5個部分:
問題基于特征的值詢問了數據。每個問題都有一個分裂節(jié)點的真或假答案。根據問題的答案,數據點向下移動。
gini:節(jié)點的Gini雜質。當我們向下移動樹時,平均加權基尼雜質值會減少。
samples:節(jié)點中的觀察數。
value:每個類的樣本數量。例如,頂部節(jié)點在類0中有2個樣本,在類1中有4個樣本。
class:節(jié)點中點的多數分類。在葉節(jié)點的情況下,這是對節(jié)點中所有樣本的預測。?
要對新點進行分類,只需向下移動樹,使用點的特征來回答問題,直到到達class作為預測的葉節(jié)點。
為了以不同的方式查看樹,我們可以在原始數據上繪制由決策樹構建的分割。
每個拆分都是一條線,它根據特征值將數據點劃分為節(jié)點。對于這個簡單的問題并且對最大深度沒有限制,劃分將節(jié)點中的每個點僅放置在同一類的點上。(再次,稍后我們將看到訓練數據的這種完美劃分可能不是我們想要的,因為它可能導致過度擬合。
### 基尼雜質
現在深入了解基尼雜質的概念(數學并不令人生畏!)。節(jié)點的基尼雜質是指節(jié)點中隨機選擇的樣本如果被標記的錯誤標記的概率。節(jié)點中樣本的分布。例如,在頂部(根)節(jié)點中,有44.4%的可能性錯誤地根據節(jié)點中的樣本標簽對隨機選擇的數據點進行分類。我們使用以下等式得出這個值:
節(jié)點的Gini雜質是1減去每個類的p_i平方的總和(對于二分類任務,這是2)。這可能有點令人困惑,所以讓我們計算出根節(jié)點的基尼雜質。
在每個節(jié)點處,決策樹在要素中搜索要拆分的值,從而最大限度地減少基尼雜質。(拆分節(jié)點的替代方法是使用信息增益)。
然后,它以貪婪的遞歸過程重復此拆分過程,直到達到最大深度,或者每個節(jié)點僅包含來自一個類的樣本。每層的加權總基尼雜質必須減少。在樹的第二層,總加權基尼雜質值為0.333:
最終,最后一層的加權總Gini雜質變?yōu)?意味著每個節(jié)點都是純粹的,并且從該節(jié)點隨機選擇的點不會被錯誤分類。雖然這似乎是好的,但這意味著模型可能過度擬合,因為節(jié)點僅使用訓練數據構建。
### 過度擬合:或者為什么森林比一棵樹更好
您可能會想問為什么不只使用一個決策樹?它似乎是完美的分類器,因為它沒有犯任何錯誤!要記住的關鍵點是樹在訓練數據上沒有犯錯。我們預計會出現這種情況,因為我們給樹提供了答案,并沒有限制最大深度(級別數)。機器學習模型的目標是很好地概括它以前從未見過的新數據。
當我們具有非常靈活的模型(模型具有高容量)時,過度擬合發(fā)生,其基本上通過緊密擬合來記憶訓練數據。問題是模型不僅學習訓練數據中的實際關系,還學習任何存在的噪聲。據說靈活模型具有高方差,因為學習參數(例如決策樹的結構)將隨著訓練數據而顯著變化。
另一方面,據說一個不靈活的模型具有較高的偏差,因為它對訓練數據做出了假設(它偏向于預先設想的數據思想。)例如,線性分類器假設數據是線性的,不具備適應非線性關系的靈活性。一個不靈活的模型可能無法適應訓練數據,在這兩種情況下 - 高方差和高偏差 - 模型無法很好地推廣到新數據。
創(chuàng)建一個非常靈活的模型來記憶訓練數據與不能學習訓練數據的不靈活模型之間的平衡稱為偏差 - 方差權衡,是機器學習的基本概念。
當我們不限制最大深度時決策樹容易過度擬合的原因是因為它具有無限的靈活性,這意味著它可以保持增長,直到它為每個單獨的觀察只有一個葉節(jié)點,完美地對所有這些進行分類。如果您返回決策樹的圖像并將最大深度限制為2(僅進行一次拆分),則分類不再100%正確。我們減少了決策樹的方差,但代價是增加了偏差。
作為限制樹深度的替代方案,它可以減少方差(好)并增加偏差(差),我們可以將許多決策樹組合成一個稱為隨機森林的單一集合模型。
隨機森林
在隨機森林是許多決策樹組成的模型。這個模型不是簡單地平均樹的預測(這樣的算法可以稱為“森林”),而是使用兩個關鍵概念,使其名稱為隨機森林:
①在構建樹時對訓練數據點進行隨機抽樣
②分割節(jié)點時考慮的隨機特征子集
隨機抽樣訓練觀察
在訓練時,隨機森林中的每棵樹都會從數據點的隨機樣本中學習。樣本用可放回抽取,稱為bootstraping,這意味著一些樣本將在一棵樹中多次使用。這個想法是通過對不同樣本上的每棵樹進行訓練,盡管每棵樹相對于特定訓練數據集可能具有高度差異,但總體而言,整個森林將具有較低的方差,但不會以增加偏差為代價。
在測試時,通過平均每個決策樹的預測來進行預測。這種在不同的數據bootstraped子集上訓練每個學習器然后對預測求平均值的過程稱為bagging,是bootstrap aggregating的縮寫。
用于拆分節(jié)點的隨機特征子集
隨機林中的另一個主要概念是,只考慮所有特征的子集來分割每個決策樹中的每個節(jié)點。通常,這被設置為sqrt(n_features)個用于分類,這意味著如果存在16個特征,則在每個樹中的每個節(jié)點處,將僅考慮4個隨機特征來分割節(jié)點。(隨機林也可以考慮每個節(jié)點的所有特征,如回歸中常見的那樣。這些選項可以在Scikit-Learn 的Random Forest實現中控制)。
如果你能理解一個決策樹,bagging的想法,以及隨機的特征子集,那么你對隨機森林的工作方式有了很好的理解:
隨機森林將數百或數千個決策樹組合在一起,在略微不同的觀察集上訓練每個決策樹,考慮到有限數量的特征,在每棵樹中分割節(jié)點。隨機森林的最終預測是通過平均每棵樹的預測來做出的。
要理解為什么隨機森林優(yōu)于單一決策樹,請想象以下情況:您必須決定特斯拉股票是否會上漲,并且您可以訪問十幾位對該公司沒有先驗知識的分析師。每個分析師都有較低的偏見,因為他們沒有任何假設,并且可以從新聞報道的數據集中學習。
這似乎是一個理想的情況,但問題是報告除了真實信號之外可能還包含噪聲。因為分析師完全根據數據做出預測 - 他們具有很高的靈活性 - 他們可能會被無關的信息所左右。分析師可能會從同一數據集中得出不同的預測。此外,如果給出不同的報告訓練集,每個分析師的差異很大,并且會得出截然不同的預測。
解決方案是不依賴于任何一個人,而是匯集每個分析師的投票。此外,就像在隨機森林中一樣,允許每個分析人員只訪問報告的一部分,并希望通過采樣取消噪聲信息的影響。在現實生活中,我們依賴于多種來源,因此,決策樹不僅直觀,而且在隨機森林中將它們組合在一起的想法也是如此。
隨機森林實踐
接下來,我們將使用Scikit-Learn在Python中構建一個隨機林。我們將使用分為訓練和測試集的真實數據集,而不是學習一個簡單的問題。我們使用測試集作為模型對新數據的執(zhí)行方式的估計,這也可以讓我們確定模型過度擬合的程度。
數據集
我們要解決的問題是二元分類任務,目的是預測個人的健康狀況。這些特征是個人的社會經濟和生活方式特征,標簽是0健康狀況不佳和1身體健康。此數據集是來自中心疾病控制和預防【2】。
通常,80%的數據科學項目需要對數據進行清理,探索和特征生成【3】。但是,對于本文,我們將集中于建模。
這是一個不平衡的分類問題,因此準確性Accuracy不是一個合適的指標。相反,我們將測量 Receiver Operating Characteristic Area Under the Curve (ROC AUC),從0(最差)到1(最佳)的度量,隨機猜測得分為0.5。我們還可以繪制ROC曲線以評估模型。
該notebook【4】包含了決策樹和隨機森林都實現,但在這里我們只專注于隨機森林。在讀取數據后,我們可以實例化和訓練隨機森林如下:
''' 遇到問題沒人解答?小編創(chuàng)建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' 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)以及預測概率(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曲線。頂部和左側的曲線是更好的模型:
隨機森林明顯優(yōu)于單一決策樹。
我們可以采用的模型的另一個診斷措施是繪制測試預測的confusion矩陣
這顯示了模型在左上角和右下角的正確預測以及模型在左下角和右上角錯的預測。我們可以使用這些圖來診斷我們的模型,并確定它是否表現良好,可以投入生產。
特征重要性
隨機林中的特征重要性表示基于該特征上拆分的所有節(jié)點上Gini雜質減少的總和。我們可以使用這些來嘗試找出隨機森林認為最重要的預測變量。可以從訓練好的隨機森林中提取特征重要性,并將其放入Pandas的DataFrame中,如下所示:
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, 指示患者是否行走困難,是在問題環(huán)境中有意義的最重要的特征。
我們可以通過構建最重要的附加特征,將特征重要性用于特征工程。我們還可以通過刪除低重要性特征,使用特征重要性來選擇特征。
在森林中可視化樹
最后,我們可以在森林中可視化單個決策樹。這次,我們必須限制樹的深度,否則它將太大而無法轉換為圖像。為了制作下圖,我將最大深度限制為6.這仍然導致我們無法完全解析的大樹!然而,鑒于我們深入研究了決策樹,我們掌握了模型的工作原理。
下一步
進一步的步驟是使用Scikit-Learn的RandomizedSearchCV中的隨機搜索來優(yōu)化隨機森林。優(yōu)化是指在給定數據集上找到模型的最佳超參數。最佳超參數將在數據集之間變化,因此我們必須在每個數據集上單獨執(zhí)行優(yōu)化(也稱為模型調整)。
我喜歡將模型調整視為尋找機器學習算法的最佳設置。我們可以在隨機林中優(yōu)化的因素包括決策樹的數量,每個決策樹的最大深度,用于拆分每個節(jié)點的最大特征數,以及葉節(jié)點中所需的最大數據點數。
總結
以上是生活随笔為你收集整理的Python中随机森林的实现与解释的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用selenium和pyquery爬取
- 下一篇: 值得收藏的45个Python优质资源