經常使用的集成學習方法

集成學習是構建一組基學習器,並將它們綜合做爲最終的模型,在不少集成學習模型中,對基學習器的要求很低,集成學習適用於機器學習的幾乎全部的領域:
一、迴歸
二、分類
三、推薦
四、排序算法

集成學習有效的緣由
多樣的基學習器能夠在不一樣的模型中取長補短
每一個基學習器都犯不一樣的錯誤,綜合起來犯錯的可能性不大
可是想同的多個基學習器不會帶來任何提高bootstrap

集成學習示例:
經常使用的集成學習方法
例如在上圖中每一個線性模型都不能成功將該數據集分類
可是三個線性模型的簡單綜合便可將數據集成功分類,每一個模型犯不一樣的錯,可是在綜合時可以取長補短,使得綜合後的模型性能更好。網絡

那麼如何構建不一樣的基學習器?如何將基學習器綜合起來?數據結構

如何構建不一樣的學習器
一、採用不一樣的學習算法
二、採用相同的學習算法,可是使用不一樣的參數
三、採用不一樣的數據集,其中採用不一樣的樣本子集,在每一個數據集中使用不一樣的特徵框架

如何綜合不一樣的基學習器
一、投票法
每一個基學習器具備相同的權重
二、有權重的投票
可用不一樣的方法來肯定權重
三、訓練一個新模型來肯定如何綜合
stacking
咱們通常偏好簡單的模型(線性迴歸)dom

主要的集成學習模式有如下幾種
一、bagging random forest(隨機森林)
二、boosting
adaboost
GBDT
三、stacking機器學習

bagging
在集成算法中,bagging 方法會在原始訓練集的隨機子集上構建一類黑盒估計器的多個實例,而後把這些估計器的預測結果結合起來造成最終的預測結果。 該方法經過在構建模型的過程當中引入隨機性,來減小基估計器的方差(例如,決策樹)。 在多數狀況下,bagging 方法提供了一種很是簡單的方式來對單一模型進行改進,而無需修改背後的算法。 由於 bagging 方法能夠減少過擬合,因此一般在強分類器和複雜模型上使用時表現的很好(例如,徹底決策樹,fully developed decision trees),相比之下 boosting 方法則在弱模型上表現更好(例如,淺層決策樹,shallow decision trees)。ide

bagging 方法有不少種,其主要區別在於隨機抽取訓練子集的方法不一樣:函數

若是抽取的數據集的隨機子集是樣例的隨機子集,咱們叫作 Pasting 。
若是樣例抽取是有放回的,咱們稱爲 Bagging 。
若是抽取的數據集的隨機子集是特徵的隨機子集,咱們叫作隨機子空間 (Random Subspaces)。
最後,若是基估計器構建在對於樣本和特徵抽取的子集之上時,咱們叫作隨機補丁 (Random Patches) 。
在 scikit-learn 中,bagging 方法使用統一的 BaggingClassifier 元估計器(或者 BaggingRegressor ),輸入的參數和隨機子集抽取策略由用戶指定。max_samples 和 max_features 控制着子集的大小(對於樣例和特徵), bootstrap 和 bootstrap_features 控制着樣例和特徵的抽取是有放回仍是無放回的。 當使用樣本子集時,經過設置 oob_score=True ,可使用袋外(out-of-bag)樣原本評估泛化精度。性能

採樣機率

在Bagging中,一個樣本可能被屢次採樣,也可能一直不被採樣,假設一個樣本一直不出如今採樣集的機率爲(1-1/N) ** N,那麼對其求極限可知,原始樣本數據集中約有63.2%的樣本出如今了,Bagging使用的數據集中,同時在採樣中,咱們還可使用袋外樣本(out of Bagging)來對咱們模型的泛化精度進行評估.

最終的預測結果

對於分類任務使用簡單投票法,即每一個分類器一票進行投票(也能夠進行機率平均)
對於迴歸任務,則採用簡單平均獲取最終結果,即取全部分類器的平均值

基於KNN的Bagging算法

關於參數和方法要注意的是:

首先控制特徵子採樣與樣本子採樣是否採用,採用的話是否要注意控制比例(通常而言,不要採起較小的數值,過小的特徵子採樣和樣本子採樣都會形成子學習器的性能太差.通常而言特徵選擇越少,方差越大,這點能夠與最後的實驗方差誤差分解對比分析).
其次控制Bagging中的隨機數參數random_state固定,否則不一樣實驗的結果將不一致,同時要注意的不少時候random_state對於測試偏差的影響很大,所以加入你想要在某一個數據集上使用Bagging,那麼建議多嘗試幾個不一樣的Random_state
oob_score = True 對性能有必定的提高(使用袋外樣本進行泛化能力的評估,可是不少時候效果並不明顯,或者看不出什麼效果)
其餘參數通常默認便可

from sklearn.ensemble import BaggingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score

# load data from sklearn import datasets,model_selection
def load_data():
    iris=datasets.load_iris() # scikit-learn 自帶的 iris 數據集
    X_train=iris.data
    y_train=iris.target
    return model_selection.train_test_split(X_train, y_train,test_size=0.25,random_state=0,stratify=y_train)

bagging = BaggingClassifier(KNeighborsClassifier(),max_samples=0.1,max_features=0.5,random_state=1)

X_train,X_test,y_train,y_test=load_data()

bagging.fit(X_train,y_train)
y_pre = bagging.predict(X_test)
print(accuracy_score(y_test,y_pre))

boosting
Boosting主要是Adaboost(Adaptive Boosting),它與Bagging的不一樣在於他將權重賦予每一個訓練元組,生成基分類器的過程爲迭代生成。每當訓練生成一個分類器M(i)時要進行權重更新,使得M(i+1)更關注被M(i)分類錯誤的訓練元組。最終提高總體集合的分類準確率,集成規則是加權投票,每一個分類器投票的權重是其準確率的函數。

繼續詳細介紹的話,假設數據集D,共有d類。(X1,Y1)…(Xd,Yd),Yi是Xi的類標號,假設須要生成k的分類器。其步驟爲:

一、對每一個訓練元組賦予相等的權重1/d。

二、for i=1:k

從D中進行有放回的抽樣,組成大小爲d的訓練集Di,同一個元組能夠被屢次選擇,而每一個元組被選中的概率由權重決定。利用Di訓練獲得分類器Mi,而後使用Di做爲測試集計算Mi的偏差。而後根據偏差調整權重。

當元組沒有被正確分類時,則權重增長;反之權重減小。而後利用新的權重爲下一輪訓練分類器產生訓練樣本。使其更「關注」上一輪中錯分的元組。

三、進行加權投票集成

Bagging與Boosting的差別

經過上述簡單的介紹,能夠看出這兩種集成算法主要區別在於「加沒加權」。Bagging的訓練集是隨機生成,分類器相互獨立;而Boosting的分類器是迭代生成,更關注上一輪的錯分元組。所以Bagging的各個預測函數能夠並行生成;而Boosting只能順序生成。所以對於像一些比較耗時的分類器訓練算法(如神經網絡等)若是使用Bagging能夠極大地解約時間開銷。

可是經過在大多數數據集的實驗,Boosting的準確率多數會高於Bagging,可是也有極個別數據集使用Boosting反倒會退化。

stacking
stakcing經常在各大數據挖掘競賽中被普遍使用,號稱「大殺器」。是數據挖掘競賽高端玩家必備技能,本篇文章就對stakcing的一些基本原理進行介紹。

首先,在我看來stacking 嚴格來講不能稱爲一種算法,我理解的是一種很是精美而複雜的對模型的集成策略。你們都知道,在給定了數據集的狀況下,數據內部的空間結構和數據之間的關係是很是複雜的。而不一樣的模型,其實很重要的一點就是在不一樣的角度去觀測咱們的數據集。好比說,KNN 可能更加關注樣本點之間的距離關係(包括歐幾里得距離(Euclidean Distance)、明可夫斯基距離(Minkowski Distance 等等),當樣本距離相對較近, KNN 就把他們分爲一類;而決策樹,可能更加關注分裂節點時候的不純度變化,有點像咱們本身找的規則,在知足某個條件且知足某個條件的狀況下,決策樹把樣本分爲一類等等。也就是說,不一樣的算法模型,實際上是在不一樣的數據空間角度和數據結構角度來觀測數據,而後再依據它本身的觀測,結合本身的算法原理,來創建一個模型,在新的數據集上再進行預測。這樣你們就會有個疑問了,俗話說:三人行必有我師。既然是不一樣的算法對數據有不一樣的觀測,那麼咱們能不能相互取長補短,我看看你的觀測角度,你看看個人觀測角度,咱倆結合一下,是否是能夠獲得一個更加全面更加優秀的結果呢?答案是確定的。在我當初學基礎算法的時候就有這麼一個疑問,可是不知道怎麼結合,直到有一天看到了 stacking的框架,瞬間感受找到了一片新天地~~~~下面我從如下幾個方面介紹 stacking。

1、stacking 的框架結構與運行過程:

剛開始看 stacking 好像是交叉檢驗的既視感,其實並非這樣。假設是五折的stacking,咱們有一個train 數據集和一個test 數據集,那麼一個基本的stacking 框架會進行以下幾個操做:

一、選擇基模型。咱們能夠有 xgboost,lightGMB,RandomForest,SVM,ANN,KNN, LR 等等你能想到的各類基本算法模型。

二、把訓練集分爲不交叉的五份。咱們標記爲 train1 到 train5。

三、從 train1 開始做爲預測集,使用 train2 到 train5 建模,而後預測 train1,並保留結果;而後,以 train2 做爲預測集,使用 train1,train3 到 train5 建模,預測 train2,並保留結果;如此進行下去,直到把 train1 到 train5 各預測一遍;

四、在上述創建的五個模型過程當中,每一個模型分別對 test 數據集進行預測,並最終保留這五列結果,而後對這五列取平均,做爲第一個基模型對 test 數據的一個 stacking 轉換。

五、把預測的結果按照 train1 到 trian5 的位置對應填補上,獲得對 train 整個數據集在第一個基模型的一個 stacking 轉換。

六、選擇第二個基模型,重複以上 2-5 操做,再次獲得 train 整個數據集在第二個基模型的一個 stacking 轉換。

七、以此類推。有幾個基模型,就會對整個train 數據集生成幾列新的特徵表達。一樣,也會對test 有幾列新的特徵表達。

八、通常使用LR 做爲第二層的模型進行建模預測。

bagging的優勢:
易於並行計算
可使用不在訓練集中的樣原本估計基學習器的性能
boosting的優勢:
學習速度快可以有效利用弱學習器構建強大的學習器
boosting缺點與bagging相比更激進,更容易受噪聲影響過擬合,不易並行
stacking多用於最終綜合多個性能較好的模型,最易於過擬合

如何避免過擬合:
一、引入隨機性
是機器學習中一個廣爲使用的避免過擬合的方法

stacking示例代碼

from sklearn import datasets  

iris = datasets.load_iris()  
X, y = iris.data[:, 1:3], iris.target  

from sklearn import model_selection  
from sklearn.linear_model import LogisticRegression  
from sklearn.neighbors import KNeighborsClassifier  
from sklearn.naive_bayes import GaussianNB   
from sklearn.ensemble import RandomForestClassifier  
from mlxtend.classifier import StackingClassifier  
import numpy as np  

clf1 = KNeighborsClassifier(n_neighbors=1)  
clf2 = RandomForestClassifier(random_state=1)  
clf3 = GaussianNB()  
lr = LogisticRegression()  
sclf = StackingClassifier(classifiers=[clf1, clf2, clf3],   
                          meta_classifier=lr)  

print('3-fold cross validation:\n')  

for clf, label in zip([clf1, clf2, clf3, sclf],   
                      ['KNN',   
                       'Random Forest',   
                       'Naive Bayes',  
                       'StackingClassifier']):  

    scores = model_selection.cross_val_score(clf, X, y,   
                                              cv=3, scoring='accuracy')  
    print("Accuracy: %0.2f (+/- %0.2f) [%s]"   
          % (scores.mean(), scores.std(), label))
相關文章
相關標籤/搜索