前言
集成學習通過組合多個模型的優勢,常能獲得比單一模型更優的性能,隨機森林便是其中的典型代表。它基于 Bagging 思想,通過對樣本和特征的雙重隨機采樣,構建多棵決策樹并綜合其結果,在降低過擬合風險的同時,顯著提升了模型的穩定性與泛化能力。
本文將從隨機森林的核心原理出發,結合實戰案例對比其與單棵決策樹、邏輯回歸的性能差異,通過可視化拆解森林內部結構,并總結其優缺點與適用場景,幫助讀者快速掌握這一強大算法的核心邏輯與應用方法。
1、隨機森林介紹
Bagging 思想 + 決策樹就誕生了隨機森林(Random Forest)。它通過構建多棵決策樹并綜合其結果,顯著提升了模型的泛化能力和穩定性。
隨機森林,都有哪些隨機?
- 樣本隨機:在構建每棵決策樹時,采用有放回的隨機抽樣(bootstrap 抽樣)從原始數據集中選取訓練樣本
- 特征隨機:在每個決策樹節點分裂時,隨機選擇部分特征子集,僅從該子集中尋找最優分裂條件
這種雙重隨機性使得森林中的每棵樹都具有一定的差異性,有效降低了單棵決策樹容易過擬合的風險,同時通過多棵樹的集體決策提高了預測的準確性和穩定性。
隨機森林的工作流程可概括為:
-
從原始數據集中通過 bootstrap 抽樣生成多個不同的訓練子集
-
為每個子集構建一棵決策樹,樹的每個節點僅使用隨機選擇的部分特征
-
對于分類問題,通過投票機制綜合所有樹的預測結果;對于回歸問題,則取所有樹預測值的平均值
2、隨機森林實戰
本章將通過具體的代碼實現,在經典的鳶尾花數據集上開展實戰實驗,直觀對比隨機森林與單棵決策樹、邏輯斯蒂回歸的性能差異。
2.1、導包加載數據
import numpy as np
from sklearn import tree
from sklearn import datasets
from sklearn.model_selection import train_test_split
import graphviz
# ensemble 集成
# 隨機森林
from sklearn.ensemble import RandomForestClassifier
# 作為對照
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
# 加載數據
X,y = datasets.load_iris(return_X_y=True)
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state = 112)
2.2、普通決策樹
score = 0
for i in range(100):X_train,X_test,y_train,y_test = train_test_split(X,y)model = DecisionTreeClassifier()model.fit(X_train,y_train)score += model.score(X_test,y_test)/100
print('隨機森林平均準確率是:',score)
單棵決策樹的性能受訓練數據分割和樹結構影響較大,多次運行的結果通常會有較大波動。
2.3、隨機森林(運行時間稍長)
score = 0
for i in range(100):X_train,X_test,y_train,y_test = train_test_split(X,y)model = RandomForestClassifier()model.fit(X_train,y_train)score += model.score(X_test,y_test)/100
print('隨機森林平均準確率是:',score)
結論:
- 和決策樹對比發現,隨機森林分數稍高,結果穩定
- 隨機森林通過集成多棵樹的預測,有效降低了模型的方差,減少了過擬合風險
- 這種穩定性在數據集較小時尤為明顯
2.4、邏輯斯蒂回歸
import warnings
warnings.filterwarnings('ignore')
score = 0
for i in range(100):X_train,X_test,y_train,y_test = train_test_split(X,y)lr = LogisticRegression()lr.fit(X_train,y_train)score += lr.score(X_test,y_test)/100
print('邏輯斯蒂回歸平均準確率是:',score)
結論:
- 不同算法對特定數據集的適應性不同,邏輯斯蒂回歸在鳶尾花數據集上表現優秀
- 隨機森林作為一種強大的通用算法,在各類數據集上通常都能取得良好表現
- 實際應用中應嘗試多種算法并選擇最適合當前問題的模型
3、隨機森林可視化
3.1、創建隨機森林進行預測
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state = 9)
forest = RandomForestClassifier(n_estimators=100,criterion='gini')
forest.fit(X_train,y_train)
score1 = round(forest.score(X_test,y_test),4)
print('隨機森林準確率:',score1)
print(forest.predict_proba(X_test))
隨機森林的predict_proba方法返回每個樣本屬于各個類別的概率,這是通過綜合所有決策樹的預測結果得到的。
準確率為1.0:
3.2、對比決策樹
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state = 112)
model = DecisionTreeClassifier()
model.fit(X_train,y_train)
print('決策樹準確率:',model.score(X_test,y_test))
proba_ = model.predict_proba(X_test)
print(proba_)
準確率為1.0:
總結:
- 一般情況下,隨機森林比決策樹更加優秀
- 隨機森林的predict_proba()返回的是概率分布(如 0.97),反映了模型對預測結果的置信度
- 單棵決策樹的predict_proba()返回的是確定值(0 或 1),因為每個樣本最終只會落入一個葉節點
3.3、繪制決策樹
隨機森林由多棵決策樹組成,我們可以查看其中的部分樹來理解森林的多樣性:
# 第一顆樹類別
dot_data = tree.export_graphviz(forest[0],filled=True)
graph = graphviz.Source(dot_data)
graph
# 第五十顆樹類別
dot_data = tree.export_graphviz(forest[49],filled=True)
graph = graphviz.Source(dot_data)
graph
# 第100顆樹類別
dot_data = tree.export_graphviz(forest[-1],filled=True)
graph = graphviz.Source(dot_data)
graph
通過對比可以發現,隨機森林中的不同決策樹在結構和分裂條件上存在差異,這種多樣性是隨機森林能夠提高預測性能的關鍵。
4、隨機森林總結
隨機森林主要步驟:
- 隨機選擇樣本:采用有放回抽樣(bootstrap)從原始數據集中生成多個訓練樣本集。
- 隨機選擇特征:每棵樹的每個節點分裂時,僅從隨機選擇的特征子集中尋找最優分裂條件。
- 構建決策樹:為每個樣本集構建一棵決策樹,不進行剪枝。
- 綜合結果:分類問題采用多數投票機制,回歸問題采用平均值。
優點:
- 泛化能力強:通過集成多棵樹的預測,有效降低了過擬合風險
- 處理高維數據:特征隨機選擇機制使模型能高效處理高維度數據
- 特征重要性評估:可以輸出特征重要性分數,輔助特征選擇和數據理解
- 并行計算:樹的構建過程相互獨立,可并行計算,提高訓練效率
- 對缺失值和異常值不敏感:相比其他算法具有更強的魯棒性
- 適用范圍廣:既可用于分類問題,也可用于回歸問題
缺點:
- 計算成本較高:構建多棵樹需要更多計算資源和時間
- 模型解釋性差:雖然單棵樹易于解釋,但多棵樹的集成結果難以直觀解釋
- 對噪聲數據敏感:對于噪聲過大的數據,仍有可能出現過擬合
- 內存占用較大:存儲多棵決策樹需要更多內存空間
參數調優關鍵:
- n_estimators:森林中樹的數量,通常越大性能越好,但計算成本也越高。
- max_features:每個節點分裂時考慮的最大特征數,控制特征隨機性。
- max_depth:樹的最大深度,控制樹的復雜度,防止過擬合。
- min_samples_split:分裂內部節點所需的最小樣本數。
- min_samples_leaf:葉節點所需的最小樣本數。
隨機森林作為一種強大而實用的算法,在數據挖掘、機器學習競賽和工業界都有廣泛應用,是解決分類和回歸問題的首選算法之一。
經過本章的實戰對比,隨機森林的優勢已然清晰:相比單棵決策樹,它用集成的力量提升了穩定性與準確率;面對邏輯斯蒂回歸,也展現出強勁的競爭力。