1. 程式人生 > >Ensemble Learning(整合學習)

Ensemble Learning(整合學習)

整合學習原理:
所謂兼聽則明,偏信則闇。

這裡寫圖片描述

整合學習本身並不是一個單純的新演算法,它的目的是通過結合多個其他的機器學習模型來完成某個一個任務以提升最終結果的準確率,即三個臭皮匠賽過諸葛亮。從該思想出發自然可以想到,如何得到多個機器學習模型?又如何整合?基於此,整合學習也就有了多種形態。如果對不同類別的機器學習模型進行整合,如用SVM和樸素貝葉斯結合等等,不過一般來說提到整合學習都是指同類的模型,如多個決策樹,多個神經網路來整合。如果根據這些模型之間是否強相關又可分為Boosting系列,Bagging隨機森林(Random Forest)系列這兩種。
整合結合策略主要有:直接投票法,結果平均法,stacking等。

這裡寫圖片描述

Boosting
專注錯誤樣本,即先對所有樣本初始化一個權重(一般為均勻分佈),然後對這個樣本進行訓練,可以得到一個的誤差率,根據誤差率大小賦以權重,誤差越大權重就越小,對誤分的樣本增加它的權重,使訓練的下一個模型側重於誤分的樣本,然後再次根據誤差率更新權重,依次迭代,最後將會得到強模型,即就是多個弱模型的加權和。Boosting泛化錯誤率低,易編碼,可以用於大多數分類器上,無需調引數,但對離群點敏感。從演算法思想可以看出效能好的模型權重會大,對最後結果的影響就是能減少Bias。

AdaBoost演算法:

這裡寫圖片描述

AdaBoost簡單來說就是每次迭代找到最佳的單個模型,計算alpha,權重向量D,更新類別估計值,如果錯誤率為0或者達到迭代次數,則退出程式。

演算法實現:(Python)

def adaBoostTrainDS(dataArr,classLabels,numIt=40):
    weakClassArr = []
    m = shape(dataArr)[0]
    D = mat(ones((m,1))/m)  #初始化權重
    aggClassEst = mat(zeros((m,1)))#記錄每一個數據點的類別估計值
    for i in range(numIt):
        bestStump,error,classEst = buildStump(dataArr,classLabels,D)
        alpha = float(0.5
*log((1.0-error)/max(error,1e-16)))#防止分母變成0。Alpha表示的是模型的權重。錯誤率越低,權重越高 bestStump['alpha'] = alpha weakClassArr.append(bestStump) expon = multiply(-1*alpha*mat(classLabels).T,classEst) #區分正確或錯誤的樣本 D = multiply(D,exp(expon)) D = D/D.sum()#歸一化 aggClassEst += alpha*classEst#累加變成強模型 aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1)))#sign()通過投票預測的類別,計算正零負 errorRate = aggErrors.sum()/m Print( "total error: ",errorRate) if errorRate == 0.0: break return weakClassArr,aggClassEst.T

梯度提升樹(Gradient Boosting Decison Tree, GBDT):
又稱MART(Multiple Additive Regression Tree),與AdaBoost利用誤差率迭代的更新權重的思想不同,GBDT是利用前向分佈演算法,迭代尋找更弱的模型。也就是說,學習之前樹的殘差。比如預測一個月生活費,第一棵樹預測600,而實際是1000,那麼殘差為400,於是將生活費更新設為400,第二棵樹預測300,那麼殘差為100,繼續更新生活費為100,然後繼續迭代。GBDT相對來說能適用於處理各種型別的資料,不容易受異常噪音的影響。但是由於弱模型之間的依賴關係,難以並行訓練資料,不過可以通過自採樣的SGBT來達到部分並行。還有xgboost(eXtreme Gradient Boosting),它能夠自動利用CPU的多執行緒並行,而且在計算速度和準確率上有更好的表現。

GBDT和隨機森林的比較?
原始的Boost演算法是,為每一個樣本初識化同樣大小的一個權重值。在之後的每一步訓練中得到的模型,會根據資料點估計的對錯,增加分錯的權重,減少分對的權重,然後等進行了N次迭代,將會得到N個簡單的分類器,然後組合起來,得到一個最終的模型。而Gradient Boost與傳統的Boost的區別是,每一次的計算是為了減少上一次的殘差(residual),而為了消除殘差,在殘差減少的梯度(Gradient)方向上建立一個新的模型。所以說,在Gradient Boost中,每個新的模型的簡歷是為了使得之前模型的殘差往梯度方向減少,與傳統Boost對正確、錯誤的樣本進行加權有著很大的區別。

Bagging
又稱自舉匯聚法(bootstrap aggregating),專注多模型,即在訓練集合裡,多次隨機抽取的n個樣本進行訓練,高度並行化, 然後用結合策略進行結合。它對最後結果的影響是能減小variance,所以能抑制過擬合。
Random Forest:基本思想和Bagging一致,只是在對樹做特徵劃分選擇的時候不是每次選擇最好的,而是在其中隨機選擇,通過這種方式可以帶來更好的多樣性(diversity)。

順便總結一下方差與偏差之間的差別與聯絡:
這裡寫圖片描述

偏差指的是期望值與真實值之間的偏差程度,代表了演算法的擬合能力;方差是樣本在期望值附近的波動程度,度量了在有資料擾動情況下所帶來的影響。從上圖可以看出,模型複雜程度越高,擬合的程度就越高,訓練偏差就越小。但如果用新資料對該模型進行測試,結果可能不佳,即模型的方差很大。整體的誤差呈現出先降後升的情況,所以在選擇模型時應該好好的調配兩者之間的關係,比如正則化

這裡寫圖片描述

EL應用:
AdaBoostClassifier引數說明:
AdaBoostClassifier(algorithm=’SAMME.R’, base_estimator=None,learning_rate=1.0, n_estimators=50, random_state=None)

 algorithm:權重的度量,SAMME.R是預測概率大小作權重。SAMME是Adaboost演算法的擴充套件
 base_estimator:用於評估的學習模型演算法
 n_estimators:最大迭代次數
 random_state:是否隨機

完成分類和每棵決策樹的評分:

import numpy as np
import matplotlib.pyplot as plt

from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_gaussian_quantiles

X1, y1 = make_gaussian_quantiles(cov=2.,
                                 n_samples=200, n_features=2,
                                 n_classes=2, random_state=1)
X2, y2 = make_gaussian_quantiles(mean=(3, 3), cov=1.5,
                                 n_samples=300, n_features=2,
                                 n_classes=2, random_state=1)
X = np.concatenate((X1, X2))
y = np.concatenate((y1, - y2 + 1))

bdt = AdaBoostClassifier(DecisionTreeClassifier(max_depth=1),
                         algorithm="SAMME",
                         n_estimators=200)

bdt.fit(X, y)

plot_colors = "br"
plot_step = 0.02
class_names = "AB"

plt.figure(figsize=(10, 5))
plt.subplot(121)
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, plot_step),
                     np.arange(y_min, y_max, plot_step))

Z = bdt.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
cs = plt.contourf(xx, yy, Z, cmap=plt.cm.Paired)
plt.axis("tight")

for i, n, c in zip(range(2), class_names, plot_colors):
    idx = np.where(y == i)
    plt.scatter(X[idx, 0], X[idx, 1],
                c=c, cmap=plt.cm.Paired,
                s=20, edgecolor='k',
                label="Class %s" % n)
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.legend(loc='upper right')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Decision Boundary')

# 得分
twoclass_output = bdt.decision_function(X)
plot_range = (twoclass_output.min(), twoclass_output.max())
plt.subplot(122)
for i, n, c in zip(range(2), class_names, plot_colors):
    plt.hist(twoclass_output[y == i],
             bins=10,
             range=plot_range,
             facecolor=c,
             label='Class %s' % n,
             alpha=.5,
             edgecolor='k')
x1, x2, y1, y2 = plt.axis()
plt.axis((x1, x2, y1, y2 * 1.2))
plt.legend(loc='upper right')
plt.ylabel('Samples')
plt.xlabel('Score')
plt.title('Decision Scores')

plt.tight_layout()#自動控制邊緣間距
plt.subplots_adjust(wspace=0.35)
plt.show()

這裡寫圖片描述

AdaBoostRegressor引數說明:
AdaBoostRegressor(base_estimator=DecisionTreeRegressor(criterion=’mse’, max_depth=4, max_features=None,max_leaf_nodes=None, min_impurity_split=1e-07,min_samples_leaf=1, min_samples_split=2,min_weight_fraction_leaf=0.0, presort=False, random_state=None,splitter=’best’),learning_rate=1.0, loss=’linear’, n_estimators=300,random_state)

base_estimator:預設是決策樹
learning_rate=1.0:學習率
loss='linear':損失函式
n_estimators=300:最大迭代次數
random_state=是否隨機

完成迴歸的任務:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import AdaBoostRegressor

rng = np.random.RandomState(1)
X = np.linspace(0, 6, 100)[:, np.newaxis]
y = np.sin(X).ravel() + np.sin(6 * X).ravel() + rng.normal(0, 0.1, X.shape[0])

regr_1 = DecisionTreeRegressor(max_depth=4)

regr_2 = AdaBoostRegressor(DecisionTreeRegressor(max_depth=4),
                          n_estimators=300, random_state=rng)
print(regr_2)
regr_1.fit(X, y)
regr_2.fit(X, y)

y_1 = regr_1.predict(X)
y_2 = regr_2.predict(X)

plt.figure()
plt.scatter(X, y, c="k", label="training samples")
plt.plot(X, y_1, c="g", label="n_estimators=1", linewidth=2)
plt.plot(X, y_2, c="r", label="n_estimators=300", linewidth=2)
plt.xlabel("data")
plt.ylabel("target")
plt.title("Boosted Decision Tree Regression")
plt.legend()
plt.show()

這裡寫圖片描述

主要參考:
Peter Harrington《Machine learning in action》
Fabio Nelli《Python Data Analytics》