文章目錄
- 一、什麼是随機森林?
- 1.1 定義
- 1.2 目的
- 1.3 随機森林 VS bagging
- 二、內建學習
- 2.1 定義
- 2.2 決策樹的問題
- 2.3 袋裝法概念與理論
- 2.4 裝袋法的優缺點
- 2.5 提升法概念與理論
- 2.6 bagging vs boosting
- 2.7 AdaBoosting
- 2.8 Gradient Boosting(GBM)
- 三、案例實作(bagging)
- 3.1 資料集描述
- 3.2 資料處理
- 3.3 決策樹
- 3.4 bagging方法
- 3.5 随機森林
- 四、案例實作(boosting)
- 4.1 資料集介紹
- 4.2 資料處理
- 4.3 AdaBoost介紹
- 4.4 AdaBoost 實作
- 4.5 XGBoost介紹
- 4.6 XGBoost 實作
- 五、結論
一、什麼是随機森林?
1.1 定義
随機森林回歸是一種使用內建學習方法進行回歸的監督學習算法。內建學習方法是一種将多種機器學習算法的預測結合起來進行比單個模型更準确的預測的技術。随機森林屬于內建學習中的袋裝法。
1.2 目的
随機森林是Bagging的改進版本,它在Bagging的基礎上做出了一個小調整,使得各個樹之間的相關性降低了(decorrelate trees)。
1.3 随機森林 VS bagging
每個分支點上,Bagging能夠考慮所有m=p個特征,而Random Forest隻能考慮m=sqrt§個特征。如果random forest的m取成p,那麼它與Bagging是相同的。(注:對于分類,一個好的預設值是:m = sqrt(p))。其中:m是在分割點可搜尋的特征的數量,這些特征是随機選取的;p是輸入變量的總數量。例如,如果一個分類問題的資料集有25個變量,那麼:m = sqrt(25)=5。
二、內建學習
2.1 定義
內建方法是一種将來自多個機器學習算法的預測組合在一起以做出比任何單個模型更準确的預測的技術。由許多模型組成的模型稱為內建模型。
2.2 決策樹的問題
- 決策樹對訓練它們的特定資料很敏感。如果訓練資料發生變化,最終的決策樹可能會完全不同,反過來,預測也會不同。
- 決策樹的缺點在于High Variance(高方差),也就是說,我們将樣本一分為二,用兩個子樣本分别拟合模型,得到的結果很可能不一樣。而Bagging,又稱Bootstrap Aggregation,就是為了降低分類器的Variance。這就是說,應用了Bagging後,不同樣本子集産出的分類器結果将會更相似。
- 決策樹的訓練計算成本也很高,存在過度拟合的巨大風險,并且往往會找到局部最優值。
- 為了解決這些弱點,我們轉向随機森林,它說明了将許多決策樹組合成一個模型的力量,能更完美。
2.3 袋裝法概念與理論
Bagging (袋裝法)是一種通用過程,可用于降低那些具有高方差的算法的方差,通常是決策樹。Bagging 使每個模型獨立運作,然後在最後聚合輸出優先于任何模型。Bagging的基本理念是:求平均值會降低Variance。
聚合是 Bagging 的最後一個階段。将基礎模型做出的多個預測組合起來産生一個最終模型。最終模型将具有低方差和高準确度分數。
想要降低模型的Variance(方差),并提高準确率的方法就是,從樣本總體中抽取很多個訓練集(Training Set),對每個訓練集分别拟合模型。将每個模型的結果求平均(Average)。
則實作步驟如下:
- 通過Bootstrap的方法,從一個Training Set中反複提取出多個樣本集,假設樣本集數量為B。
- 用這B個樣本分别拟合出B個預測性模型
- 将B個模型的結果取平均值,得到Bagging的預測結果。
其公式表達為:
回歸和分類:
- 對于回歸樹而言,Bagging的結果就是B個沒有經過Prune(剪枝)樹的結果平均值。
- 對于分類樹而言,我們通過Majority Vote,多數投票制,計算大多數模型認為結果應當屬于哪一類,Bagging認為多數的結果是最終的分類結果。
是以我們隻需要處理分類做袋裝即可。
2.4 裝袋法的優缺點
優點:
- Bagging 算法提高了模型的準确度得分。
- Bagging 算法可以處理過度拟合。
- Bagging 算法減少了偏差和方差錯誤。
- Bagging 可以很容易地實作并生成更健壯的模型。
但是,由于模型在最後用了平均值,是以Bagging結果的可解釋性降低了。
2.5 提升法概念與理論
Boosting同樣是Bagging的改進版本。它與Bagging的不同在于:樹的推導是有序的,每個樹的生成都借鑒了之前樹的經驗。Boosting方法不采用Boostrap的取樣方法,每個樹用的都是修正後的原始資料集(Original Dataset)。
在Boosting中,有如下參數需要考慮:
- B:樹的數量。要生成多少棵樹。
- d:每個樹中的分支(split)數。它掌握每棵樹的複雜度,若d=1,則樹隻有一個節點。
- λ:Shrinkage parameter,壓縮參數。一個非常小的正數。它掌握着Boosting學習的速率。代表着每個樹的作用大小。一般可以設定為0.01或0.001.一個非常小的λ代表每個樹的作用很小,是以需要非常大的B,非常多的樹去得到優秀的結果。
Boosting方法通過以上的步驟,以很慢的學習方式拟合模型。Boosting将殘差引入拟合模型的過程中,它在模型表現的不太好的地方慢慢的去優化它。也就是說,Boosting先拟合出一個原始的模型,之後的模型希望能夠一點點的優化原始模型中的Residual(殘差)。在拟合過程中,每個樹的權重,即發揮效用的大小就是shrinkage parameter(收縮參數)。
Boosting的學習方法是有時間循序(Sequential)的,在T時刻生成的樹的Residual,會在T+1時刻生成的樹中被改善優化。是以,Boosting是與原始模型息息相關的。同時,這種學習方法一般訓練成本較高,學習結果比較慢。
2.6 bagging vs boosting
2.7 AdaBoosting
在AdaBoost初始化時,對每個訓練的樣本給出相等的權重。之後對每個樣本進行模型的拟合。每一次訓練後,對之前失敗的訓練樣本集給予較大的權重。是以,之後的訓練會更加側重之前失敗的樣本集。最後,得到的模型按照預測效果給出權重,最終回歸或者分類的結果會按照權重平均,或者權重投票結果給出判别。
2.8 Gradient Boosting(GBM)
Gradient Boosting是Boosting的一種實作方法,在Boosting中,GBM定義了損失函數(Loss Function)的概念。GMB主要的理念在于,後建立的模型是在之前建立模型的梯度下降方向的。損失函數就是模型的誤差程度,損失函數越大,模型越容易出錯。如果我們的模型能夠讓損失函數持續的下降,則說明我們的模型在不停的改進,而最好的方式就是讓損失函數在其梯度(Gradient)的方向下降。
三、案例實作(bagging)
3.1 資料集描述
我們将使用糖尿病資料集來預測一個人是否患有糖尿病。收集的資料集具有Age和blood pressure等特征,Outcome列标記為 0(非糖尿病)或 1(糖尿病)。可幫助模型确定此人是否患有糖尿病。
資料集如下:
3.2 資料處理
第一步:讀取資料集
import pandas as pd
df = pd.read_csv("tang.csv")
如下:
第二步:檢查下缺失值(當然,資料用的完好的,實際情況下有可能會有缺失值)。
df.isnull().sum()
如下:
第三步:提取自變量和因變量
X = df.drop("Outcome",axis="columns")
y = df.Outcome
第四步:資料縮放。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
第五步:分割訓練集和測試集。
from sklearn.model_selection import train_test_split
#85%的資料是訓練集,25%是測試集。
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size = 0.25, random_state=10)
3.3 決策樹
第六步:建立模型并評估模型。
# 使用 k 折交叉驗證來建構我們的決策樹分類器
# K-fold 交叉驗證允許我們将資料集拆分為不同的子集或部分。然後使用每個子集訓練模型,并在每次疊代後獲得準确度分數。
#最後,計算平均準确度得分。K 是指我們拆分資料集的子集/部分的數量。
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeClassifier # 導入模型
scores = cross_val_score(DecisionTreeClassifier(), X, y, cv=5)
如下:
array([0.69480519, 0.66233766, 0.7012987 , 0.77124183, 0.71895425])
擷取平均分:
# 平均分
scores.mean()
如下:
0.7097275273745862
使用交叉驗證分數,我們得到準确度分數為0.7097275273745862。我們可以使用 bagging 算法建構相同的模型來比較準确度得分。
3.4 bagging方法
第一步:建構學習器
# 添加學習器
from sklearn.ensemble import BaggingClassifier
# base_estimator - 這表示用作基礎/弱學習器的算法。我們使用DecisionTreeClassifier算法作為我們的弱/基礎學習器。
# n_estimators - 這表示使用的弱學習器的數量。我們将使用 100
# max_samples - 從訓練集中采樣的最大資料數。我們使用 80%
#bootstrap -
# oob_score -
# random_state -
bag_model = BaggingClassifier(
base_estimator=DecisionTreeClassifier(),
n_estimators=100,
max_samples=0.8,
bootstrap=True,
oob_score=True,
random_state=0
)
第二步:訓練模型。
# 拟合模型
bag_model.fit(X_train, y_train)
第三步:評估模型。
# 模型準确率。結果确實比決策樹高。準确度得分從 提高0.7097275273745862到0.7604166666666666
bag_model.oob_score_
第四步: 檢測是否過拟合。
# 我們還可以使用測試資料集檢查準确度分數,以确定我們的模型是否過拟合。
# 準确度得分表明我們的模型沒有過度拟合。當我們在使用測試資料集時獲得較低的準确性時,就會發生過度拟合。
bag_model.score(X_test, y_test)
如下說明沒有過拟合:
0.7760416666666666
3.5 随機森林
随機森林不僅對資料行進行采樣,而且對列進行采樣。它還遵循裝袋步驟來生成聚合的最終模型。
第一步:建立模型。
from sklearn.ensemble import RandomForestClassifier
model=RandomForestClassifier(n_estimators=50)
第二步:訓練并擷取評分。
scores = cross_val_score(model, X, y, cv=5)
如下:
array([0.74675325, 0.73376623, 0.80519481, 0.81699346, 0.78431373])
第三步: 擷取平均分。
scores.mean()
如下:
0.7774042950513538
準确度得分很高,表明裝袋算法提高了模型準确度得分,它還可以防止模型過度拟合,是以不用去檢查過拟合了。評分從0.7760416666666666增加到0.7774042950513538,說明bagging和随機森林差不多。
四、案例實作(boosting)
第一個提升算法被稱為 AdaBoost(自适應提升),由 Freund 和 Schapire 設計發明。
內建方法是使用多個模型并将它們組合成一個以增強結果的技術。術語“模型”可以指任何模型 - 回歸、支援向量機和 kNN,需要改進性能的模型稱為基礎模型。盡管“提升”技術使用決策樹來提高模型的準确性,但它可以應用于任何基礎模型。然而,據觀察,提升基于決策樹的模型比提升其他模型提供更好的結果。一種可能的解釋是基礎模型(決策樹)和提升算法的結構相似性。
文章分為兩部分,便于讀者了解和留存資訊。這深入解釋了兩種提升算法——自适應提升(AdaBoost)和極限梯度提升(XGBoost)。與該算法類似的還有Light Gradient Boosting Method (LightGBM) 和 Category Boosting (CatBoost),讀者自行去了解。
4.1 資料集介紹
對于資料集中的一組特征,任務是識别蘑菇的類型是有毒的還是可食用的。資料集如下:
4.2 資料處理
第一步:讀取資料
import pandas as pd
df = pd.read_csv("mushrooms.csv")
如下:
第二步:由于特征數太多,檢視以下每一個特征類别數量。如果一個特征隻有一個唯一值,我們可以删除它,因為它在構模組化型時沒有意義。
for col in df.columns:
print(col,'特征個數', 'is', len(df[col].unique()))
如下:
class 特征個數 is 2
cap-shape 特征個數 is 6
cap-surface 特征個數 is 4
cap-color 特征個數 is 10
bruises 特征個數 is 2
odor 特征個數 is 9
gill-attachment 特征個數 is 2
gill-spacing 特征個數 is 2
gill-size 特征個數 is 2
gill-color 特征個數 is 12
stalk-shape 特征個數 is 2
stalk-root 特征個數 is 5
stalk-surface-above-ring 特征個數 is 4
stalk-surface-below-ring 特征個數 is 4
stalk-color-above-ring 特征個數 is 9
stalk-color-below-ring 特征個數 is 9
veil-type 特征個數 is 1
veil-color 特征個數 is 4
ring-number 特征個數 is 3
ring-type 特征個數 is 5
spore-print-color 特征個數 is 9
population 特征個數 is 6
habitat 特征個數 is 7
第三步:删除特征的類别數量隻有一個的,因為它對分類沒有意義了。
df = df.drop("veil-type", axis=1)
df.head(5)
如下:
第四步: 資料編碼。由于機器學習模型更喜歡數字資料,它識别不了字元,讓我們通過編碼将資料集轉換為數字。LabelEncoder()是 Scikit-Learn 包中将标簽轉換為數字的方法。
from sklearn.preprocessing import LabelEncoder
# 對每一列分别編碼再合并回去
label_encoder = LabelEncoder()
for column in df.columns:
df[column] = label_encoder.fit_transform(df[column])
如下:
第五步:提取目标矩陣Y和特征矩陣X(也就是自變量與因變量)。
X = df.drop('class',axis=1)
Y = df['class']
第六步:拆分資料集。資料集必須分成兩部分——訓練資料和測試資料。70% 用于訓練,30% 用于測試和标準化值。
from sklearn.model_selection import train_test_split # 拆分子產品
from sklearn.preprocessing import StandardScaler # 标準化子產品
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.3, random_state = 100)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
4.3 AdaBoost介紹
AdaBoost是 Adaptive Boosting 的縮寫, 專注于提高基礎學習器失敗區域的性能。基礎學習器是模型的第一次疊代。
從一個決策樹開始,錯誤分類的示例通過增加它們的權重(權重被提升)來懲罰。另一個決策樹是根據新的和修改的訓練資料建構的,其中包含權重樣本。新的弱學習器被依次添加到模型中,以學習和識别更複雜的模式。
每次疊代後的資料永遠不會相同,并且指出可能的錯誤分類以供算法識别和學習。錯誤分類的權重會增加,以便下一次疊代可以拾取它們。該過程重複指定為參數的疊代次數。該算法根據弱學習者的多數票以及它們各自的準确性進行預測。
随着疊代次數的增加,AdaBoost 可以抵抗過度拟合,并且在處理二進制分類問題時最有效。AdaBoost 包括一個額外的條件,即模型需要有小于 50% 的誤差才能維持它,否則,重複疊代直到生成更好的學習器。
AdaBoost 在模型建構中包含随機化,是以每次運作一段代碼時,都會生成一個略有不同的模型。每次運作代碼時,随機學習算法都會産生不同的結果,是以,通過多次運作代碼并對獲得的結果取平均值來評估此類算法的性能是一種很好的做法。
4.4 AdaBoost 實作
Python 中的sklearn庫有一種AdaBoostClassifier方法,用于将特征分類為有毒或可食用。
它的參數如下:
- base_estimator: boosted ensemble 是根據這個參數建構的。如果None,則值為DecisionTreeClassifier(max_depth=1)。
- n_estimators:估計器的上限,預設值為 50 終止提升。如果完美拟合,則提前停止學習。
- learning_rate:學習率通過這個值減少了分類器的貢獻。它的預設值為 1。
- algorithm:“SAAME”的預設值。此參數的另一個選項 SAMME.R 算法比 SAMME 算法收斂得更快,同時采用更少的提升疊代并産生更低的測試錯誤。
- random_state:随機數生成器使用的種子。
第七步: 接着處理後的資料,建立模型、訓練模型、評估模型。
from sklearn.ensemble import AdaBoostClassifier
model = AdaBoostClassifier(n_estimators = 50, learning_rate = 0.2) # 建立模型
adaboost=model.fit(X_train, Y_train) # 訓練
score = adaboost.score(X_test, Y_test)
如下:
0.9848236259228876
4.5 XGBoost介紹
為什麼 XGBoost 如此受歡迎?
- 速度和性能:最初是用 C++ 編寫的,它比其他內建分類器要快。
- 核心算法是可并行化的:因為核心 XGBoost 算法是可并行化的,它可以利用多核計算機的力量。它還可以在 GPU 上和跨計算機網絡上并行化,進而也可以在非常大的資料集上進行訓練。
- 始終優于其他算法方法:它在各種機器學習基準資料集上表現出更好的性能。
- 多種調優參數:XGBoost 内部具有交叉驗證、正則化、使用者定義的目标函數、缺失值、樹參數、scikit-learn 相容 API 等參數。
XGBoost(Extreme Gradient Boosting)屬于提升算法家族,其核心使用梯度提升(GBM)架構。它是一個優化的分布式梯度提升庫。
什麼是梯度提升?
- 在組合模型的梯度提升中,使用梯度下降将損失函數最小化。從技術上講,損失函數可以說是誤差,即預測值與實際值之間的差異。當然,誤差越小,機器學習模型就越好。
- 梯度提升是一種建立新模型的方法,該模型預測先前模型的殘差或誤差,然後将它們加在一起以進行最終預測。
- XGBoost 帶有一個額外的随機化參數,可以降低樹之間的相關性。分類器樹之間的較少相關性轉化為分類器集合的更好性能。
- XGBoost 通過正則化校正複雜模型來解決過拟合問題。正則化梯度提升也是一種選擇,同時考慮了 L1 正則化和 L2 正則化。
- 在增強處理性能時,該算法在 CPU 中使用多個核心。該算法利用 CPU 中的所有核心并行生成多個決策樹。
- 該系統被設計為塊狀結構,這使得資料的布局可以在後續疊代中重複使用,而不是重新計算。
4.6 XGBoost 實作
與 AdaBoost 不同的是,XGBoost 有一個獨立的庫,自己pip安裝。在導入庫和建立 的執行個體XGBClassifier之前,讓我們看一下調用該XGBClassifier方法所需的一些參數。
- max_depth:基礎學習者的樹的最大深度。
- learning_rate:XGBooster 的學習率。
- verbosity: 詳細程度。有效值介于 0(靜默)和 3(調試)之間。
- objective:要使用的學習目标。
- booster:要在和gbtree中選擇的助推器。gblineardart
- tree_method:要使用的樹方法。最保守的選項設定為預設值。
- n_jobs:并行線程數。
- gamma:在樹的葉節點上進行另一次分裂所需的最小損失減少。
- reg_alpha: XGBoost 權重的 L1 正則化項。
- reg_lambda: XGBoost 權重的 L2 正則化項。
- base_score:初始預測(也稱為全局偏差)。
- random_state:随機數種子。
-
importance_type:要關注的功能;gain, weight,或. _
cover_total_gaintotal_cover
第八步:繼續接着上面小結的模型進行實作:搭模組化型、訓練模型、評估模型。
# pip install XGBoost
from xgboost import XGBClassifier
model= XGBClassifier(n_estimators = 1000, learning_rate = 0.05) # 建立模型
xgboost=model.fit(X_train, Y_train, early_stopping_rounds = 5, eval_set = [(X_test, Y_test)],verbose = False) # 訓練模型
score_xgb = xgboost.score(X_test,Y_test)
如下:
1.0