隨機森林演算法原理與Python實現

郝hai發表於2024-04-28

隨機森林(Random Forest)是一種強大的整合學習方法,將多個決策樹組合成一個更為強大和穩健的模型,適用於分類和迴歸任務。其核心思想是透過構建大量決策樹,每棵樹都基於不同的隨機樣本和特徵子集進行訓練,最後透過投票或平均的方式綜合所有樹的預測結果。這樣做的好處在於增加了模型的多樣性,減少了過擬合風險,提高了整體的預測準確性和泛化能力。隨機森林廣泛應用於各個領域,包括但不限於醫療健康、金融風控、電商推薦、工業製造、生態環境監測、文字分類和影像識別等。在醫療健康領域,它可用於輔助醫生進行疾病診斷和預測;在金融領域,可用於信用評分和欺詐檢測;在電商領域,可用於個性化推薦系統;在工業製造領域,可用於質量控制和裝置故障預測。隨機森林的靈活性和高效性使其成為當今資料科學領域中的一項重要工具,為各種複雜問題的解決提供了可靠的解決方案。

一、隨機森林概述

隨機森林(Random Forest)是一種整合學習方法,常用於分類和迴歸問題。它透過構建多個決策樹來進行預測,然後透過取這些樹的輸出的平均值(迴歸問題)或投票(分類問題)來提高模型的準確性和魯棒性。隨機森林具有很強的泛化能力,對於複雜的資料集和高維特徵空間也表現良好。

1.1 隨機森林的兩種整合方法

Bagging(Bootstrap Aggregating):Bagging透過自助取樣(Bootstrap Sampling)生成多個不同的訓練集,並基於這些訓練集構建多個獨立的模型。最後,透過投票或平均的方式整合各個模型的預測結果。隨機森林就是Bagging的一種應用,它使用了自助取樣生成不同的訓練集,並構建了多個決策樹模型。
Boosting:Boosting是一種迭代的整合方法,它透過順序地訓練一系列弱分類器(例如,決策樹)來提升模型效能。Boosting方法透過加大錯誤樣本的權重,使得後續的模型更加關注之前模型預測錯誤的樣本,從而不斷改善模型的效能。

1.2 隨機森林的優缺點

優點 缺點
隨機森林能夠處理大量資料和高維特徵 在某些情況下,隨機森林可能會過度擬合,特別是當資料集包含大量噪聲或特徵之間存在強相關性時
具有較高的準確性和泛化能力 對於大規模資料集和高維特徵,訓練時間可能較長
對異常值和噪聲具有一定的容忍性 隨機森林的預測過程相對較慢,尤其是當模型中包含大量樹時
能夠處理缺失值,不需要額外的資料預處理
可解釋性較強,模型構建簡單

二、隨機森林的思想和原理

隨機森林(Random Forest)是一種經典的Bagging模型,其弱學習器為決策樹模型。如下圖所示,隨機森林模型會在原始資料集中隨機抽樣,構成n個不同的樣本資料集,然後根據這些資料集搭建n個不同的決策樹模型,最後根據這些決策樹模型的平均值(針對迴歸模型)或者投票(針對分類模型)情況來獲取最終結果。

2.1 Bagging演算法

Bagging的想法是採用類似於“民主投票”的方式,即每一個基礎模型都有一票,最終結果透過所有基礎模型投票,少數服從多數的原則產生預測結果。
原理:從原始訓練資料中(假設共有10000條資料),隨機有放回地抽取10000次資料構成一個新的資料集(因為是隨機有放回抽樣,所以可能出現某一條資料多次被抽中,也有可能某一條資料一次也沒有被抽中),每次使用一個訓練樣本訓練一個基礎模型。這樣進行有放回的隨機抽取n次後,訓練結束時我們就能獲得n個由不同的資料集訓練的基礎模型,也稱之為n個弱學習器,根據這n個弱學習器的結果,我們可以獲得一個更加準確合理的結果。

2.2 Boosting演算法

Boosting演算法的本質是將弱學習器提升為強學習器,它和Bagging的區別在於,Bagging對待所有的基礎模型一視同仁。而Boosting則做到了對於基礎模型的“區別對待”,通俗來講,Boosting演算法注重“培養精英”和“重視錯誤”。“培養精英”,即每一輪對於預測結果較為準確的基礎模型,會給予它一個較大的權重,表現不好的基礎模型則會降低它的權重。這樣在最終預測時,“優秀模型”的權重是大的,相當於它可以投出多票,而“一般模型”只能在投票時投出一票或不能投票。“重視錯誤”,即在每一輪訓練後改變訓練資料的權值或機率分佈,透過提高那些在前一輪被基礎模型預測錯誤樣例的權值,減小前一輪預測正確樣例的權值,來使得分類器對誤分的資料有較高的重視程度,從而提升模型的整體效果。

三、隨機森林的Python程式碼

3.1 隨機森林示例1

這裡使用一個流行的資料集,即Iris(鳶尾花)資料集。這個資料集包含了三個不同種類的鳶尾花(Setosa、Versicolor和Virginica),每個種類有四個特徵(花瓣長度、花瓣寬度、花萼長度和花萼寬度)。


# 匯入必要的庫
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report

# 載入鳶尾花資料集
iris = load_iris()
X = iris.data
y = iris.target

# 劃分資料集為訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 建立隨機森林分類器
rf_classifier = RandomForestClassifier(n_estimators=100, random_state=42)

# 訓練模型
rf_classifier.fit(X_train, y_train)

# 在測試集上進行預測
y_pred = rf_classifier.predict(X_test)

# 評估模型效能
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy:.2f}')

# 輸出更詳細的分類報告
print('Classification Report:\n', classification_report(y_test, y_pred))

在這個案例中,使用了鳶尾花資料集,將資料集劃分為訓練集和測試集,建立了一個包含100個決策樹的隨機森林分類器,並輸出了模型的準確度和分類報告。你可以根據你的實際需求和資料集進行調整和修改。

3.2 特徵比較評分示例2

一個資料集中往往有成百上千個特徵,如何在其中選擇比結果影響最大的那幾個特徵,以此來縮減建立模型時特徵數是我們比較關心的問題。這樣的方法其實很多,比如主成分分析,lasso等等。用隨機森林方法也可以進行特徵篩選。隨機森林進行特徵重要性評估的思想就是看每個特徵在隨機森林中的每棵樹上做了多大的貢獻,然後取個平均值,最後比一位元徵之間的貢獻大小。
貢獻大小通常使用基尼指數(Gini index)或者袋外資料(OOB)錯誤率作為評估指標來衡量,這裡我們再學習一下用基尼指數來評價的方法。我們將變數重要性評分 (variable importance measures) 用VIM來表示,將Gini指數用GI來表示,假設\(m\)個特徵X1,X2,X3,......,Xc,現在要計算出每個特徵Xj的Gini指數評分為\(VIM_j (Gini)\) , 亦即第 \(\mathrm{j}\) 個特徵在RF所有決策樹中節點分裂不純度的平均改變數。Gini指數的計算公式為:

\[G I_m=\sum_{k=1}^{|K|} \sum_{k^{\prime} \neq k} p_{m k} p_{m k^{\prime}}=1-\sum_{k=1}^{|K|} p_{m k}^2 \]

其中, \(K\) 表示有 \(K\) 個類別;\(P_{mk}\)表示節點 \(m\) 中類列 \(k\) 所佔的比例。特徵Xj在節點 \(m\) 的重要性,即節點 \(m\) 分支前後的Gini指數變化量為:

\[V I M_{j m}^{(G i n i)}=GI_m-GI_l-GI_r \]

其中,\(GI_l\)\(GI_r\)分別表示分枝後兩個新節點的Gini指數。
如果,特徵Xj在決策樹中出現的節點在集合M中,那麼Xj在第\(i\)顆樹的重要性為:

\[V I M_{i j}^{(\text {Gini })}=\sum_{m \in M} V I M_{j m}^{(\text {Gini })} \]

假設隨機森林(Random Forest)中共有 \(n\) 顆樹,那麼

\[VIM_j^{(\text {Gini })}=\sum_{i=1}^n V I M_{i j}^{(\text {Gini })} \]

最後,把所有求得的重要性評分做一個歸一化處理,即

\[V I M_j=\frac{V I M_j}{\sum_{i=1}^c V I M_i} \]

# url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data'
# 從這個網址下載資料編輯成資料檔案wine.txt,放到工作路徑中

import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

# 讀取資料集
url1 = pd.read_csv(r'wine.txt', header=None)
url1.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash',
                'Alcalinity of ash', 'Magnesium', 'Total phenols',
                'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins',
                'Color intensity', 'Hue', 'OD280/OD315 of diluted wines', 'Proline']

# 將資料集分為特徵和標籤
x, y = url1.iloc[:, 1:].values, url1.iloc[:, 0].values
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=0)

# 構建隨機森林模型
forest = RandomForestClassifier(n_estimators=10000, random_state=0, n_jobs=-1)
forest.fit(x_train, y_train)

# 獲取特徵重要性
importances = forest.feature_importances_
feat_labels = url1.columns[1:]
indices = np.argsort(importances)[::-1]

# 列印特徵重要性
for f in range(x_train.shape[1]):
    print("%2d) %-*s %f" % (f + 1, 30, feat_labels[indices[f]], importances[indices[f]]))

# 設定重要性閾值,篩選變數
threshold = 0.15
x_selected = x_train[:, importances > threshold]

# 視覺化特徵重要性
plt.figure(figsize=(10, 6))
plt.title("紅酒資料集中各個特徵的重要程度", fontsize=18)
plt.ylabel("Importance level", fontsize=15, rotation=90)
plt.rcParams['font.sans-serif'] = ["SimHei"]
plt.rcParams['axes.unicode_minus'] = False

for i in range(x_train.shape[1]):
    plt.bar(i, importances[indices[i]], color='orange', align='center')

plt.xticks(np.arange(x_train.shape[1]), feat_labels[indices], rotation=90, fontsize=15)
plt.show()

總結

隨機森林是一種高效的機器學習演算法,它基於整合學習的思想,透過構建多個決策樹並整合它們的預測結果來提高整體的預測精度。在隨機森林中,每個決策樹都是基於不同的隨機樣本和隨機特徵進行訓練的,這種隨機性有助於減少過擬合的風險,並提高模型的泛化能力。隨機森林是一種強大且實用的機器學習工具在各種應用場景中表現出色。然而,隨機森林模型在訓練時可能需要較大的計算資源,且對於某些特定問題可能不是最優的解決方案。因此,在選擇使用隨機森林時,需要根據具體問題和資料進行權衡和評估。

參考資料

  1. 隨機森林分類模型(python案例程式碼)
  2. Python隨機森林模型的基本原理和程式碼實現
  3. Python機器學習筆記——隨機森林演算法

相關文章