集成学习(ensemble learning)(二)
文章目錄
- 一、Bagging原理
- 1、隨機采樣(BootStrap)
- 2、弱分類器和結合決策
- 二、Bagging算法流程
- 三、隨機森林(Random Forest,RF)
- 1、特點
- 2、兩個“隨機”
- 3、分析
- 4、袋外錯誤率(oob error)
- 四、RF實例
- 1、API
- 2、示例
- (1)特征選擇
- (2)oob錯誤率
- 五、RF的推廣
- 1、extra trees
- 2、Totally Random Trees Embedding
- 3、Isolation Forest
- 參考資料
接上一篇: 集成學習(ensemble learning)。
本篇對集成學習中的 Bagging 和 隨機森林算法 進行總結。
一、Bagging原理
Bagging 的弱學習器之間沒有依賴關系,可以并行計算。
1、隨機采樣(BootStrap)
自助法,即有放回的采樣,也就是說,之前采集到的樣本在放回后有可能繼續被采集到。一般來講,隨機采樣的樣本數量和訓練集樣本數量一致為m,但是兩者內容不同。若對m個樣本的訓練集進行T次的隨機采樣,會得到T個采樣數據集且由于隨機性,T個采樣集都不相同。
Q:在自助法的采樣過程中,對m個樣本進行m次自助采樣,當m趨于無窮大時,最終有多少數據未被選擇過?
對于一個樣本,它在某一次含 mmm 個樣本的訓練集的隨機采樣中,每次被采集到的概率是 1m\frac{1}{m}m1?。不被采集到的概率為 1?1m1-\frac{1}{m}1?m1?。如果mmm次采樣都沒有被采集中的概率是 (1?1m)m(1-\frac{1}{m})^m(1?m1?)m。當m→∞m→∞m→∞時, (1?1m)m→1e?0.368(1-\frac{1}{m})^m→\frac{1}{e}?0.368(1?m1?)m→e1??0.368。也就是說,在bagging的每輪隨機采樣中,訓練集中大約有 36.8%36.8\%36.8% 的數據沒有被采樣集采集中。
袋外數據(Out of Bag,OOB),即對于這部分大約36.8%的沒有被采樣到的數據。這些數據可用作測試,用來檢測模型的泛化能力。
由于Bagging算法每次都進行采樣來訓練模型,因此泛化能力很強,對于降低模型的方差很有作用。當然對于訓練集的擬合程度就會差一些,也就是模型的偏倚會大一些。
注意:這和GBDT的子采樣是不同的。GBDT的子采樣是無放回采樣。
2、弱分類器和結合決策
弱學習器:沒有限制,最常用的一般也是決策樹和神經網絡。
對于分類問題,bagging通常采用簡單投票法,將最多票數的類別或者類別之一作為最終模型的輸出。
對于分類問題,bagging通常采用簡單平均法,將T個弱學習器得到的回歸結果進行算術平均得到最終的模型輸出。
二、Bagging算法流程
偽代碼
輸入:樣本集 D={(x1,y1),(x2,y2),...,(xm,ym)}D=\{(x_1,y_1),(x_2,y_2),...,(x_m,y_m)\}D={(x1?,y1?),(x2?,y2?),...,(xm?,ym?)},弱分類器算法,弱分類器迭代次數 T。
輸出:最終強分類器 f(x)f(x)f(x)
a) 對訓練集進行第 ttt 次隨機采樣,共采樣 mmm 次,得到包含 mmm 個樣本的采樣集 DtD_tDt?。
b)用采樣集 DtD_tDt? 訓練第 ttt 個弱分類器 Gt(x)G_t(x)Gt?(x)
三、隨機森林(Random Forest,RF)
隨機森林(Random Forest,RF) 是 Bagging 算法的進化版,其思想仍是bagging。
1、特點
優點
- 訓練可以高度并行化,提升大樣本的訓練速度;
- 具有極好的準確率;
- 能夠有效地運行在大數據集上;
- 能夠處理具有高維特征的輸入樣本,而且不需要降維;
- 能夠評估各個特征在分類問題上的重要性;
- 在生成過程中,能夠獲取到內部生成誤差的一種無偏估計;
- 對于缺省值問題也能夠獲得很好得結果。
缺點
- 在某些噪音比較大的樣本集上,RF模型容易陷入過擬合。
- 取值劃分比較多的特征容易對RF的決策產生更大的影響,從而影響擬合的模型的效果。
2、兩個“隨機”
每棵樹的按照如下規則生成如下:
(1) 若訓練集大小為 NNN,對于每棵樹而言,隨機且有放回地從訓練集中的抽取 NNN 個訓練樣本( bootstrapsamplebootstrap\ samplebootstrap?sample 方法),作為該樹的訓練集;(每棵樹的訓練集都是不同的,而且里面包含重復的訓練樣本)
Q1:為什么要隨機抽樣訓練集?
A1:若不進行隨機抽樣,每棵樹的訓練集都一樣,則最終訓練出的樹分類結果也是完全一樣的,這樣的話完全沒有bagging的必要;
Q2:為什么要有放回地抽樣?
如是無放回采樣,則每棵樹的訓練樣本是不同的,沒有交集,則每棵樹都是"有偏的",都是絕對"片面的"(當然這樣說可能不對),也就是說每棵樹訓練出來都是有很大的差異的;而隨機森林最后分類取決于多棵樹(弱分類器)的投票表決,這種表決應該是"求同",因此使用完全不同的訓練集來訓練每棵樹這樣對最終分類結果是沒有幫助的,這樣無異于是"盲人摸象"。
(2) 如果每個樣本的特征維度為 MMM,指定一個常數 m<<Mm<<Mm<<M,隨機地從 MMM 個特征中選取 mmm 個特征子集 ,每次樹進行分裂時,從這 mmm 個特征中選擇最優的;
(3) 每棵樹都盡最大程度的生長,并且沒有剪枝過程。
兩個隨機性的引入對隨機森林的分類性能至關重要。它們使得隨機森林不容易陷入過擬合,并且具有很好得抗噪能力(比如:對缺省值不敏感)。
3、分析
隨機森林分類效果(錯誤率)與兩個因素有關:
- 森林中任意兩棵樹的相關性:相關性越大,錯誤率越大;
- 森林中每棵樹的分類能力:每棵樹的分類能力越強,整個森林的錯誤率越低。
==》
減小特征選擇個數m,樹的相關性和分類能力也會相應的降低;增大m,兩者也會隨之增大。所以關鍵問題是如何選擇最優的m(或者是范圍),這也是隨機森林唯一的一個參數。
4、袋外錯誤率(oob error)
在構建每棵樹時,我們對訓練集使用了不同的bootstrap sample(隨機且有放回地抽取)。所以對于每棵樹而言(假設對于第k棵樹),大約有 36.8%36.8\%36.8% 的訓練實例沒有參與第 kkk 棵樹的生成,它們稱為第k棵樹的oob樣本。
依據計算袋外錯誤率oob error(out-of-bag error),可以選擇最優的 mmm。
oob 估計(以樣本為單位):
- 對每個樣本,計算它作為oob樣本的樹對它的分類情況;
- 多數投票作為該樣本的分類結果;
- 用誤分個數占樣本總數的比率作為隨機森林的oob誤分率。
oob錯誤率是隨機森林泛化誤差的一個無偏估計,它的結果近似于需要大量計算的k折交叉驗證。
四、RF實例
1、API
在scikit-learn中,RandomForest的分類類是RandomForestClassifier,回歸類是RandomForestRegressor,需要調參的參數包括兩部分,第一部分是Bagging框架的參數,第二部分是CART決策樹的參數。
- 官方文檔 sklearn.ensemble.RandomForestClassifier
- 官方文檔 sklearn.ensemble.RandomForestRegressor
關鍵部分參數
- n_estimators: 弱學習器的最大迭代次數,或者說最大的弱學習器的個數,默認是10。一般來說n_estimators太小,容易欠擬合,n_estimators太大,又容易過擬合,一般選擇一個適中的數值。實際應用中,可以以10為單位,考察取值范圍在1至201的調參情況。
- bootstrap:默認True,是否有放回的采樣。
- oob_score:默認False,即是否采用袋外樣本來評估模型的好壞。個人推薦設置為True,因為袋外分數反應了一個模型擬合后的泛化能力。對單個模型的參數訓練,雖然可用cross validation來進行,但特別消耗時間,且對于隨機森林也沒有大的必要,所以用oob數據對決策樹模型進行驗證,算是一個簡單的交叉驗證,性能消耗小,但是效果不錯。
- criterion:CART樹做劃分時對特征的評價標準,分類模型和回歸模型的損失函數是不一樣的。分類RF對應的CART分類樹默認是基尼系數gini,另一個可選擇的標準是信息增益entropy,是用來選擇節點的最優特征和切分點的兩個準則。回歸RF對應的CART回歸樹默認是均方差mse,另一個可以選擇的標準是絕對值差mae。一般來說選擇默認的標準就已經很好的。
- max_features: RF劃分時考慮的最大特征數。默認是None,意味著劃分時考慮所有的特征數;如果是log2意味著劃分時最多考慮log2Nlog_2Nlog2?N個特征;如果是sqrt或者`auto意味著劃分時最多考慮 N~√N個特征。如果是整數,代表考慮的特征絕對數。如果是浮點數,代表考慮特征百分比,即考慮(百分比×N百分比\times N百分比×N)取整后的特征數,其中NNN為樣本總特征數。一般來說,如果樣本特征數不多,比如小于50,我們用默認的"None"就可以了,如果特征數非常多,我們可以靈活使用剛才描述的其他取值來控制劃分時考慮的最大特征數,以控制決策樹的生成時間。
- max_depth: 決策樹最大深度。默認為None,決策樹在建立子樹的時候不會限制子樹的深度這樣建樹時,會使每一個葉節點只有一個類別,或是達到min_samples_split。一般來說,數據少或者特征少的時候可以不管這個值。如果模型樣本量多,特征也多的情況下,推薦限制這個最大深度,具體的取值取決于數據的分布。常用的可以取值10-100之間。
- min_samples_split: 內部節點再劃分所需最小樣本數,默認2。這個值限制了子樹繼續劃分的條件,如果某節點的樣本數少于min_samples_split,則不會繼續再嘗試選擇最優特征來進行劃分。 默認是2, 如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。
- min_samples_leaf:葉子節點最少樣本數。 這個值限制了葉子節點最少的樣本數,如果某葉子節點數目小于樣本數,則會和兄弟節點一起被剪枝。 默認是1,可以輸入最少的樣本數的整數,或者最少樣本數占樣本總數的百分比。如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。
RF重要的框架參數比較少,主要需要關注的是 n_estimators,即RF最大的決策樹個數;
上面決策樹參數中最重要的包括最大特征數max_features, 最大深度max_depth, 內部節點再劃分所需最小樣本數min_samples_split和葉子節點最少樣本數min_samples_leaf。
進行預測的幾種常用方法
- predict_proba(x):給出帶有概率值的結果。每個點在所有label(類別)的概率和為1.
- predict(x):直接給出預測結果。內部還是調用的predict_proba(),根據概率的結果看哪個類型的預測值最高就是哪個類型。
- predict_log_proba(x):和predict_proba基本上一樣,只是把結果給做了log()處理。
2、示例
(1)特征選擇
wine數據:下載鏈接
# -*- coding:utf-8 -*- 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 pltDATA_PATH = './data/wine.data' data = pd.read_csv(DATA_PATH, header=None) data.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'] # print(data)# 查看標簽信息 class_label = np.unique(data['Class label']) # print(class_label) # 查看數據信息 # info_data = data.info() # print(info_data)# 除去標簽之外,共有13個特征,數據集的大小為178, # 下面將數據集分為訓練集和測試集 X, y = data.iloc[:, 1:].values, data.iloc[:, 0].values X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=2019) # 獲取特征名稱 feat_labels = data.columns[1:] print(feat_labels)# n_estimators:森林中樹的數量 # n_jobs 整數可選(默認=1)適合和預測并行運行的作業數, # 如果為-1,則將作業數設置為核心數 forest = RandomForestClassifier(n_estimators=10000, random_state=2019, n_jobs=-1) forest.fit(X_train, y_train)# 下面對訓練好的隨機森林,完成重要性評估 # feature_importances_ 可以調取關于特征重要程度 importances = forest.feature_importances_ print("重要性:", importances)X_columns = data.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("import level", fontsize=15, rotation=90) plt.rcParams['font.sans-serif'] = ["SimHei"] plt.rcParams['axes.unicode_minus'] = False for i in range(X_columns.shape[0]):plt.bar(i,importances[indices[i]],color='orange',align='center')plt.xticks(np.arange(X_columns.shape[0]),X_columns,rotation=90,fontsize=15) plt.show()輸出結果
重要性: [0.12039608 0.03059304 0.01423496 0.02537548 0.0393332 0.045703020.13610644 0.01406945 0.02534866 0.16986098 0.07455494 0.123148570.18127517]1) Proline 0.1812752) Color intensity 0.1698613) Flavanoids 0.1361064) OD280/OD315 of diluted wines 0.1231495) Alcohol 0.1203966) Hue 0.0745557) Total phenols 0.0457038) Magnesium 0.0393339) Malic acid 0.030593 10) Alcalinity of ash 0.025375 11) Proanthocyanins 0.025349 12) Ash 0.014235 13) Nonflavanoid phenols 0.014069(2)oob錯誤率
import matplotlib.pyplot as pltfrom collections import OrderedDict from sklearn.datasets import make_classification from sklearn.ensemble import RandomForestClassifierprint(__doc__)RANDOM_STATE = 2019# Generate a binary classification dataset. X, y = make_classification(n_samples=500, n_features=25,n_clusters_per_class=1, n_informative=15,random_state=RANDOM_STATE)# NOTE: Setting the `warm_start` construction parameter to `True` disables # support for parallelized ensembles but is necessary for tracking the OOB # error trajectory during training. ensemble_clfs = [("RandomForestClassifier, max_features='sqrt'",RandomForestClassifier(n_estimators=100,warm_start=True, oob_score=True,max_features="sqrt",random_state=RANDOM_STATE)),("RandomForestClassifier, max_features='log2'",RandomForestClassifier(n_estimators=100,warm_start=True, max_features='log2',oob_score=True,random_state=RANDOM_STATE)),("RandomForestClassifier, max_features=None",RandomForestClassifier(n_estimators=100,warm_start=True, max_features=None,oob_score=True,random_state=RANDOM_STATE)) ]# Map a classifier name to a list of (<n_estimators>, <error rate>) pairs. error_rate = OrderedDict((label, []) for label, _ in ensemble_clfs)# Range of `n_estimators` values to explore. min_estimators = 15 max_estimators = 175for label, clf in ensemble_clfs:for i in range(min_estimators, max_estimators + 1):clf.set_params(n_estimators=i)clf.fit(X, y)# Record the OOB error for each `n_estimators=i` setting.oob_error = 1 - clf.oob_score_error_rate[label].append((i, oob_error))# Generate the "OOB error rate" vs. "n_estimators" plot. for label, clf_err in error_rate.items():xs, ys = zip(*clf_err)plt.plot(xs, ys, label=label)plt.xlim(min_estimators, max_estimators) plt.xlabel("n_estimators") plt.ylabel("OOB error rate") plt.legend(loc="upper right") plt.show()輸出結果
五、RF的推廣
基于RF的變種算法,廣泛應用在分類回歸、特征轉換、異常點檢測等場景。
1、extra trees
與Random Forest區別:
- 對于每個決策樹的訓練集,RF采用的是隨機采樣bootstrap來選擇采樣集作為每個決策樹的訓練集,而extra trees一般不采用隨機采樣,即每個決策樹采用原始訓練集。
- 在選定了劃分特征后,RF的決策樹會基于基尼系數,均方差之類的原則,選擇一個最優的特征值劃分點,這和傳統的決策樹相同。但是extra trees比較的激進,它會隨機的選擇一個特征值來劃分決策樹。
從第二點可以看出,由于隨機選擇了特征值的劃分點位,而不是最優點位,這樣會導致生成的決策樹的規模一般會大于RF所生成的決策樹。也就是說,模型的方差相對于RF進一步減少,但是偏倚相對于RF進一步增大。在某些時候,extra trees的泛化能力比RF更好。
2、Totally Random Trees Embedding
Totally Random Trees Embedding(TRTE)是一種非監督學習的數據轉化方法。它將低維的數據集映射到高維,從而讓映射到高維的數據更好的運用于分類回歸模型。
TRTE在數據轉化的過程也使用了類似于RF的方法,建立T個決策樹來擬合數據。當決策樹建立完畢以后,數據集里的每個數據在T個決策樹中葉子節點的位置也定下來了。比如我們有3顆決策樹,每個決策樹有5個葉子節點,某個數據特征x劃分到第一個決策樹的第2個葉子節點,第二個決策樹的第3個葉子節點,第三個決策樹的第5個葉子節點。則x映射后的特征編碼為(0,1,0,0,0, 0,0,1,0,0, 0,0,0,0,1), 有15維的高維特征。這里特征維度之間加上空格是為了強調三顆決策樹各自的子編碼。
3、Isolation Forest
Isolation Forest(IForest)是一種異常點檢測的方法。
- 對于在T個決策樹的樣本集,IForest也會對訓練集進行隨機采樣,但是采樣個數要遠遠小于訓練集個數(目的是異常點檢測,只需要部分的樣本,一般就可以檢測出異常點)。
- 對于每一個決策樹的建立,IForest采用隨機選擇一個劃分特征,對劃分特征隨機選擇一個劃分閾值。
- IForest一般會選擇一個比較小的最大決策樹深度max_depth,原因同樣本采集,用少量的異常點檢測一般不需要這么大規模的決策樹。
異常點判斷:將測試樣本點 xxx 擬合到 TTT 顆決策樹。計算在每顆決策樹上該樣本的葉子節點的深度 ht(x)h_t(x)ht?(x)。從而可以計算出平均高度 h(x)h(x)h(x)。此時我們用下面的公式計算樣本點xxx的異常概率:
s(x,m)=2?h(x)c(m)s(x,m)=2^{-\frac{h(x)}{c(m)}}s(x,m)=2?c(m)h(x)?
其中,mmm為樣本個數。c(m)c(m)c(m)的表達式為:
c(m)=2ln?(m?1)+ξ?2m?1m,ξ為歐拉常數c(m)=2\ln(m-1)+\xi-2\frac{m-1}{m},\xi \text{為歐拉常數}c(m)=2ln(m?1)+ξ?2mm?1?,ξ為歐拉常數
s(x,m)s(x,m)s(x,m)的取值范圍是[0,1][0,1][0,1],取值越接近于1,則是異常點的概率也越大。
參考資料
- Sklearn-RandomForest隨機森林
- Bagging與隨機森林算法原理小結
總結
以上是生活随笔為你收集整理的集成学习(ensemble learning)(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【爬虫】Scrapy爬取腾讯社招信息
- 下一篇: 【数据竞赛】“达观杯”文本智能处理挑战赛