1. 程式人生 > >整合學習stacking

整合學習stacking

參考連結:https://blog.csdn.net/willduan1/article/details/73618677

stacking

Stacking先從初始資料集訓練出初級學習器,將初級學習器的輸出當作特徵構成新資料集,利用新資料集再訓練次級學習器(meta-learner)。初級學習器通常使用不同的學習演算法。
訓練階段,若直接用初級學習器的訓練集來產生次級訓練集,過擬合風險過大,因此一般使用交叉驗證的方式,用初級學習器未使用的樣本來產生次級學習器的訓練器。以k折交叉驗證為例,對某一個演算法使用交叉驗證,將k個作為驗證集的部分的輸出組合起來作為次級訓練集的特徵。過程如下:
在這裡插入圖片描述


次級學習器的輸入屬性表示和次級學習演算法對Stacking整合的泛化效能有很大影響。有研究表明,將初級學習器的輸出類概率作為次級學習器的輸入特徵,用多響應線性迴歸(Multi-response Linear Regression)作為次級學習演算法效果較好。

使用mlxtend實現stacking

參考連結:http://rasbt.github.io/mlxtend/
mlxtend幫助文件:https://sebastianraschka.com/pdf/software/mlxtend-latest.pdf
mlxtend是一個機器學習庫,裡面包含了一些機器學習的包和視覺化函式等等,其中包括了sklearn中沒有的stacking操作。文件從88頁開始講的stacking相關的部分。
通過stacking產生的特徵可以分為多種形式:
(以下例子來自官方文件),下面的例子全部為不帶交叉驗證時初始學習器學習到的特徵,如果使用交叉驗證,可以將StackingClassifier

都變為StackingCVClassifier即可。
(1)將初級分類器產生的類別標籤作為新特徵
使用KNN,樸素貝葉斯,隨機森林作為初級分類器,LR作為次級分類器。

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 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))

輸出:

Accuracy: 0.91 (+/- 0.01) [KNN]
Accuracy: 0.91 (+/- 0.06) [Random Forest]
Accuracy: 0.92 (+/- 0.03) [Naive Bayes]
Accuracy: 0.95 (+/- 0.03) [StackingClassifier]

視覺化程式碼:

import matplotlib.pyplot as plt
from mlxtend.plotting import plot_decision_regions
import matplotlib.gridspec as gridspec
import itertools
gs = gridspec.GridSpec(2, 2)
fig = plt.figure(figsize=(10,8))
for clf, lab, grd in zip([clf1, clf2, clf3, sclf],
    ['KNN',
    'Random Forest',
    'Naive Bayes',
    'StackingClassifier'],
    itertools.product([0, 1], repeat=2)):
    clf.fit(X, y)
    ax = plt.subplot(gs[grd[0], grd[1]])
    fig = plot_decision_regions(X=X, y=y, clf=clf)
    plt.title(lab)
plt.show()

在這裡插入圖片描述
(2)將初級分類器產生的輸出類概率作為新特徵
對於輸出概率,有兩種不同的處理方式。假設有2個初級分類器和3個類別輸出概率: p 1 = [ 0.2 , 0.5 , 0.3 ] , p 2 = [ 0.3 , 0.4 , 0.4 ] p1=[0.2, 0.5, 0.3],p2=[0.3,0.4,0.4]
如果average_probas=True,則對分類器的結果求平均,得到: p = [ 0.25 , 0.45 , 0.35 ] p=[0.25,0.45,0.35]
如果average_probas=False,則分類器的所有結果都保留作為新的特徵,這種方法是推薦的方法 p = [ 0.2 , 0.5 , 0.3 , 0.3 , 0.4 , 0.4 ] p=[0.2, 0.5, 0.3,0.3,0.4,0.4]

sclf = StackingClassifier(classifiers=[clf1, clf2, clf3],
                          use_probas=True,
                          average_probas=False,
                          meta_classifier=lr)

輸出:

Accuracy: 0.91 (+/- 0.01) [KNN]
Accuracy: 0.91 (+/- 0.06) [Random Forest]
Accuracy: 0.92 (+/- 0.03) [Naive Bayes]
Accuracy: 0.94 (+/- 0.03) [StackingClassifier]

(3)初級分類器採用不同的訓練集子集來訓練
需要結合sklearn中的pipeline和ColumnSelector來實現

from sklearn.datasets import load_iris
from mlxtend.classifier import StackingClassifier
from mlxtend.feature_selection import ColumnSelector
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression

iris = load_iris()
X = iris.data  # (150,4)
y = iris.target

pipe1 = make_pipeline(ColumnSelector(cols=(0, 2)),  # 選擇第0,2列特徵
                      LogisticRegression())
pipe2 = make_pipeline(ColumnSelector(cols=(1, 2, 3)),  # 選擇第1,2,3列特徵
                      LogisticRegression())

sclf = StackingClassifier(classifiers=[pipe1, pipe2],
                          meta_classifier=LogisticRegression())

sclf.fit(X, y)