實戰:用Python實現隨機森林

摘要: 隨機森林如何實現?爲何要用隨機森林?看這篇足夠了!html

由於有Scikit-Learn這樣的庫,如今用Python實現任何機器學習算法都很是容易。實際上,咱們如今不須要任何潛在的知識來了解模型如何工做。雖然不須要了解全部細節,但瞭解模型如何訓練和預測對工做仍有幫助。好比:若是性能不如預期,咱們能夠診斷模型或當咱們想要說服其餘人使用咱們的模型時,咱們能夠向他們解釋模型如何作出決策的。python

在本文中,咱們將介紹如何在Python中構建和使用Random Forest,而不是僅僅顯示代碼,我將嘗試瞭解模型的工做原理。我將從一個簡單的單一決策樹開始,而後以解決現實世界數據科學問題的方式完成隨機森林。本文的完整代碼GitHubJupyter Notebook的形式提供git

理解決策

決策樹是隨機森林的構建塊,它自己就是個直觀的模型。咱們能夠將決策樹視爲詢問有關咱們數據問題的流程圖。這是一個可解釋的模型,由於它決定了咱們在現實生活中的作法:在最終得出決定以前,咱們會詢問有關數據的一系列問題。github

決策樹的主要技術細節是如何構建有關數據的問題,決策樹是經過造成可以最大限度減小基尼係數的問題而創建的。稍後我會討論Gini Impurity,但這意味着決策樹試圖造成儘量純的節點,其中包含來自單個類的高比例樣本(數據點)的節點。算法

Gini Impurity和構建樹可能有點難以理解,因此首先讓咱們構建一個決策樹,以即可以更好的理解它。bootstrap

關於最簡單問題的決策

咱們從一個很是簡單的二進制分類問題開始,以下所示:app

咱們的數據只有兩個特徵(標籤),且只有6個數據點。dom

雖然這個問題很簡單,但它不是線性可分的,這意味着咱們不能經過數據繪製一條直線來對點進行分類。然而,咱們能夠繪製一系列劃分類的直線,這基本上是決策樹在造成一系列問題時將要作的事情。機器學習

要建立決策樹並在數據上訓練,咱們可使用Scikit-Learn:性能

 from sklearn.tree import DecisionTreeClassifier # Make a decision tree and train tree = DecisionTreeClassifier(random_state=RSEED) tree.fit(X, y)

在訓練過程當中,咱們爲模型提供特徵和標籤,以便學習根據特徵對點進行分類。咱們沒有針對這個簡單問題的測試集,可是在測試時,咱們只給模型提供功能並讓它對標籤作出預測。

咱們能夠在訓練數據上測試咱們模型的準確性:

print(f'Model Accuracy: {tree.score(X, y)}') Model Accuracy: 1.0

咱們看到它100%正確,這是咱們所指望的,由於咱們給了它訓練的答案。

化決策

當咱們訓練決策樹時,實際上會發生什麼?我發現瞭解決策樹的最有用的方法是經過可視化,咱們可使用Scikit-Learn的功能(詳細信息請查看筆記本本文)。

上圖顯示了決策樹的整個結構,除葉節點(終端節點)外,全部節點都有5個部分:

  1. 問題基於特徵值詢問數據:每一個問題都有對或錯的答案。根據問題的答案,數據點在樹中移動。
  2. Gini:節點的Gini雜質。當咱們向下移動樹時,平均加權基尼係數必須減小。
  3. samples:節點中的觀察數。
  4. value:每一個類的樣本數量。例如,頂部節點在類0中有2個樣本,在類1中有4個樣本。
  5. class:節點中點的多數分類。在葉節點的狀況下,這是對節點中全部樣本的預測。

葉節點沒有問題,由於這些是最終預測的地方。要對新節點進行分類,只需向下移動樹,使用點的特徵來回答問題,直到到達class預測的葉節點。你可使用上面的點進行嘗試,或者進行不一樣的預測。

基尼係數

在這一點上,咱們應該嘗試瞭解基尼係數。簡而言之,Gini Impurity是隨機選擇的樣本被節點中的樣本分佈標記錯誤的機率。例如,在頂部(根)節點中,有44.4%錯誤的可能性根據節點中樣本標籤的分佈對隨機選擇的數據點進行分類。咱們可使用下面這個等式獲得這個值:

節點的Gini係數n是1減去每一個J類的p_i平方的總和讓咱們計算出根節點的基尼係數

在每一個節點處,決策樹在要素中搜索要拆分的值,從而最大限度地減小基尼係數。(拆分節點替代方法是使用信息增益)。

而後,它以遞歸過程重複此拆分過程,直到達到最大深度,或者每一個節點僅包含來自一個類的樣本。每層樹的加權總基尼係數必須減小。在樹的第二層,總加權基尼係數值爲0.333:

最後一層的加權總Gini係數變爲0意味着每一個節點都是純粹的,而且從該節點隨機選擇的點不會被錯誤分類。雖然這彷佛是好結果,但這意味着模型可能過分擬合,由於節點僅使用是經過訓練數據構建的

過分擬合:爲何森林比一棵樹更

你可能會想問爲何不僅使用一個決策樹?它彷佛是完美的分類器,由於它沒有犯任何錯誤!記住這其中的關鍵點是樹在訓練數據上沒有犯錯。由於咱們給樹提供了答案。機器學習模型的要點是很好地歸納測試數據。不幸的是,當咱們不限制決策樹的深度時,它每每會過分擬合

當咱們的模型具備高方差而且基本上記憶訓練數據時,必定會發生過分擬合。這意味着它能夠很好地在訓練數據上,但因爲測試數據不一樣,它將沒法對測試數據作出準確的預測!咱們想要的是一個能很好地學習訓練數據的模型,而且能夠在其餘數據集上發揮做用。當咱們不限制最大深度時,決策樹容易過分擬合的緣由是由於它具備無限的複雜性,這意味着它能夠保持增加,直到它爲每一個單獨的觀察只有一個葉節點,完美地對全部這些進行分類。

要理解爲何決策樹具備高差別,咱們能夠用一我的來考慮它。想象一下,你以爲明天蘋果股票會上漲,你會問一些分析師。每一位分析師均可能會有很大差別而且會嚴重依賴他們能夠訪問的數據。一位分析師可能只閱讀親蘋果新聞,所以她認爲價格會上漲,而另外一位分析師最近從她的朋友那裏聽到蘋果產品的質量開始降低,她可能就認爲價格會降低。這些個體分析師的差別很大,由於他們的答案極其依賴於他們所看到的數據。

由於每一個分析師均可以訪問不一樣的數據,因此預計個體差別會很大,但整個集合的整體方差應該減小。使用許多個體本質上是隨機森林背後的想法:而不是一個決策樹,使用數百或數千個樹來造成一個強大的模型。(過分擬合的問題被稱爲誤差-方差權衡,它是機器學習中的一個基本主題)。

隨機森林

隨機森林是許多決策樹組成的模型。這個模型不只僅是一個森林,並且它仍是隨機的,由於有兩個概念:

  1. 隨機抽樣的數據點;
  2. 基於要素子集拆分的節點;

隨機抽

隨機森林背後的關鍵是每棵樹在數據點的隨機樣本上訓練。樣本用替換(稱爲bootstrapping)繪製,這意味着一些樣本將在一個樹中屢次訓練。這個想法是經過對不一樣樣本的每棵樹進行訓練,儘管每棵樹相對於一組特定的訓練數據可能有很大的差別,但整體而言,整個森林的方差都很小。每一個學習者在數據的不一樣子集上學習,而後進行平均的過程被稱爲bagging,簡稱bootstrap aggregating

用於拆分節點的隨機特徵子集

隨機森林背後的另外一個關鍵點是,只考慮全部特徵的子集來分割每一個決策樹中的每一個節點。一般,這被設置爲sqrt(n_features)意味着在每一個節點處,決策樹考慮在特徵的樣本上分割總計特徵總數的平方根。考慮到每一個節點的全部特徵,也能夠訓練隨機森林。

若是你掌握單個決策樹、bagging決策樹和隨機特徵子集,那麼你就能夠很好地理解隨機森林的工做原理。隨機森林結合了數百或數千個決策樹,在略微不一樣的觀察集上訓練每一個決策樹,而且僅考慮有限數量的特徵來分割每一個樹中的節點。隨機森林作出的最終預測是經過平均每棵樹的預測來作出的。

隨機森林實踐

與其餘Scikit-Learn模型很是類似,在Python中使用隨機森林只須要幾行代碼。咱們將構建一個隨機森林,但不是針對上面提到的簡單問題。爲了將隨機森林與單個決策樹的能力進行對比,咱們將使用分爲訓練和測試的真實數據集。

數據集

咱們要解決的問題是二進制分類任務。這些特徵是我的的社會經濟和生活方式特徵,標籤是健康情況不佳爲0和身體健康爲1。此數據集是由中心疾病控制和預防收集,能夠在這裏找到。這是一個不平衡的分類問題,所以準確性不是一個合適的指標。相反,咱們將測量接收器工做特性區域曲線(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)以及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而單一決策樹是0.67。若是咱們查看訓練分數,咱們注意到兩個模型都達到了1.0 ROC AUC,由於咱們給這些模型提供了訓練答案,並無限制最大深度。然而,儘管隨機森林過分擬合,但它可以比單一決策樹更好地推廣測試數據。

若是咱們檢查模型,咱們會看到單個決策樹達到最大深度55,總共12327個節點。隨機森林中的平均決策樹的深度爲46和13396個節點。即便平均節點數較多,隨機森林也能更好地推廣!

咱們還能夠繪製單個決策樹(頂部)和隨機森林(底部)的ROC曲線。頂部和左側的曲線是更好的模型:

咱們看到隨機森林明顯優於單一決策樹。咱們能夠採用模型的另外一個診斷措施是繪製測試預測的混淆矩陣:

特徵重要性(Feature Importances)

隨機森林中的特徵重要性表示在該特徵上拆分的全部節點上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

咱們還能夠經過刪除具備0或低重要性的特徵來使用特徵重要性來選擇特徵

在森林中可

最後,咱們能夠在森林中可視化單個決策樹。此次,咱們必須限制樹的深度,不然它將太大而沒法轉換爲圖像。爲了製做我將最大深度限制爲6,這仍然致使咱們沒法徹底解析的大樹!

優化決策樹

下一步多是經過隨機搜索和Scikit-LearnRandomizedSearchCV來優化隨機森林。

優化是指在給定數據集上找到模型的最佳超參數。最佳超參數將在數據集之間變化,所以咱們必須在每一個數據集上單獨執行優化(也稱爲模型調整)。我喜歡將模型調整視爲尋找機器學習算法的最佳設置。有關隨機森林模型優化的隨機搜索的實現,請參閱Jupyter Notebook

結論

在本文中,咱們不只在Python中構建和使用了隨機森林,並且還對模型的進行了分析。

咱們首先查看了一個單獨的決策樹,一個隨機森林的基本構建塊,而後咱們看到了如何在一個集合模型中組合數百個決策樹。當與bagging特徵一塊兒使用和隨機抽樣時,該集合模型被稱爲隨機森林。從這篇文章中理解的關鍵概念是:

  1. 決策:直觀模型,根據詢問有關特徵值的問題流程圖作出決策,經過過分擬合訓練數據表示方差高。
  2. Gini Impurity:衡量決策樹在拆分每一個節點時嘗試最小化的度量。表示根據節點中樣本的分佈對來自節點的隨機選擇的樣本進行分類的機率。
  3. Bootstrapping:用替換的方式隨機觀察組進行採樣。隨機森林用於訓練每一個決策樹的方法。
  4. 隨機的特徵子集:在考慮如何在決策樹中分割每一個節點時選擇一組隨機特徵。
  5. 隨機森林:由數百或數千個決策樹組成的集合模型,使用自舉,隨機特徵子集和平均投票來進行預測。這是一個bagging總體的例子。
  6. 誤差-方差:機器學習中的基本問題,描述了高複雜度模型之間的權衡,以採用最好的方式學習訓練數據,代價是沒法推廣到測試數據以及簡單的模型(高偏見)甚至沒法學習訓練數據。隨機森林減小了單個決策樹的方差,同時還準確地學習了訓練數據,從而更好地預測了測試數據。

但願本文爲你提供了開始在項目中使用隨機森林所需的信心和理解。隨機森林是一種強大的機器學習模型,但這不該該阻止咱們知道它是如何工做的!

原文連接

相關文章
相關標籤/搜索