整合學習入門及程式碼實現
bagging原理
bagging的思路是訓練k個獨立的基學習器,對於每個基學習器的結果進行結合(加權或者多數投票)來獲得一個強學習器。
boostrap
boost最早用於經濟學,為了研究大樣本中的特徵值,通過有放回的多次取樣研究樣本的特徵。
- 在原有的樣本中通過重抽樣抽取一定數量(比如100)的新樣本,重抽樣(Re-sample)的意思就是有放回的抽取,即一個數據有可以被重複抽取超過一次。
- 基於產生的新樣本,計算我們需要估計的統計量。
- 重複上述步驟n次(一般是n>1000次)。
- 最後,我們可以計算被估計量的均值和方差
其中,均值為n次取樣的平均值的均值,方差為n次取樣方差/樣本數-1
類似於概統中的樣本分佈估計總體
在此bagging使用了boostrap的思想,從m個樣本的訓練集中有放回地抽取m次,獲得第一個樣本集,用於訓練第一個基學習器,以此類推可獲得k個樣本集供基學習器訓練。由於訓練資料不同,我們獲得的基學習器會有很大的差異。同時保證了資料儘可能被使用到。
由於使用了boostrap進行訓練集的抽取,由於其抽泣方法的特性,會有約0.368的樣本未被抽到,此部分樣本稱為包外樣本(記作oobs),可用作測試集,此部分的測試結果稱為“包外估計”,為真實誤差的無偏估計。
obbs估計等價於k折交叉驗證,使用obbs作為測試集能大幅減少計算。
基分類器選取
bagging要求基分類器對樣本分佈敏感,常用的基分類器為決策樹、神經網路。KNN、線性分類器由於過於“穩定”不適合作為基分類器。
- 樹的節點分裂隨機選擇特徵子集帶來隨機性,設定層數來控制泛化;
- 神經網路通過調整神經元數量、連線方式、網路層數、初始權值引入隨機性;
基分類器聚合
bagging的另一個重要步驟是模型聚合,我們通常使用比較簡單的方法來聚合多個模型,對於分類問題我們採用投票的方式,將出現最多的一個作為分類結果,對於迴歸問題取m個的平均值。
RandomForest
樣本集N,共N個樣本;特徵集M,共M個特徵
(1)樣本集N中以boostrap方法抽取k個訓練集,每個訓練集樣本個數為n(第一個隨機,隨機有放回抽取),且分類誤差取決於:
- 每棵樹的分類能力:單棵樹分類能力越強,分類誤差越小
- 樹之間的相關性:樹之間的相關性越小,分類誤差越小
(2)對每個訓練集,抽取M個特徵中的m個特徵(隨機無放回抽取):
- M較大時: m=\(log_2\)M或\(m=log_2M+1\);
- M較小時,在M中取L個特徵(L<k),用[-1, +1]上的均勻分佈來構建權重對L個特徵進行線性組合,構成k個特徵;
- m越小,相關性越小、分類能力越差;
- 是隨機森林唯一的超參(在不考慮樹本身的超參前提下),可以使用obb error(out of bag error)進行選擇
(3)對某n個樣本的訓練集,m個特徵的特徵集進行決策樹訓練
- 只訓練二叉樹:減少計算量;方便模型構建
- 無需剪枝:滿足差異性;減少計算量
m = n時,RF等價於CART樹
m越小,模型方差減小,偏差增大,趨近欠擬合;m越大,模型方差增大,偏差減小,趨近過擬合
bagging方法的程式碼實現——用於鳶尾花資料集
匯入相關的庫
from sklearn import neighbors
from sklearn import datasets
from sklearn.ensemble import BaggingClassifier
from sklearn import tree
from sklearn.model_selection import train_test_split
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
資料載入
載入鳶尾花資料集進行demo實現
iris = datasets.load_iris()
x_data = pd.DataFrame(iris.data, columns=iris.feature_names)
y_data = iris.target # 標籤
x_train,x_test,y_train,y_test, = train_test_split(x_data,y_data)
為了方便視覺化,我們選取兩列
x_data = x_data[['sepal width (cm)','petal length (cm)']]
分割資料集
X_train,X_test,y_train,y_test = train_test_split(x_data,y_data,
test_size = 1/3,random_state = 0)
我們利用KNN進行bagging實驗
knn = neighbors.KNeighborsClassifier()
knn.fit(X_train,y_train)
plot(knn)
plt.scatter(x_data.iloc[:,0],x_data.iloc[:,1],c = y_data)
plt.show()
此時的得分為0.94
使用整合學習 引數(一個模型,有返回的抽樣一百次) ,就是說進行一百次的knn分類器去分類,然後進行投票最高的那個模型
bagging_knn = BaggingClassifier(knn,n_estimators=60)
# 輸入資料建立模型
bagging_knn.fit(X_train,y_train)
plot(bagging_knn)
# 樣本散點圖
plt.scatter(x_data.iloc[:,0],x_data.iloc[:,1],c = y_data)
plt.show()
bagging_knn.score(X_test,y_test)
將KNN模型bagging的分類結果
得到結果為0.96
繪圖函式放在這裡,這種畫法可以較好地視覺化分類問題。
def plot(model):
# 獲取資料所在的範圍
x_min,x_max = x_data.iloc[:,0].min() - 1,x_data.iloc[:,0].max()+1
y_min,y_max = x_data.iloc[:,1].min() - 1,x_data.iloc[:,1].max()+1
#生成網格矩陣
xx,yy = np.meshgrid(np.arange(x_min,x_max,0.02),
np.arange(y_min,y_max,0.02))
z = model.predict(np.c_[xx.ravel(),yy.ravel()]) # ravel與flatten類似,多維資料轉一維.flatten不會改變原始資料,ravel會改變原始資料
z = z.reshape(xx.shape)
# 登高線圖
cs = plt.contourf(xx,yy,z)