整合學習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個類別輸出概率:
如果average_probas=True
,則對分類器的結果求平均,得到:
如果average_probas=False
,則分類器的所有結果都保留作為新的特徵,這種方法是推薦的方法
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)