拓端tecdat:Python集成學習:自己編寫構(gòu)建AdaBoost分類模型可視化決策邊界及sklearn
原文鏈接:http://tecdat.cn/?p=24421?
原文出處:拓端數(shù)據(jù)部落公眾號
AdaBoost是?
Boosting指的是機器學習元算法系列,它將許多 "弱 "分類器的輸出合并成一個強大的 "集合",其中每個弱分類器單獨的錯誤率可能只比隨機猜測好一點。
AdaBoost這個名字代表了自適應(yīng)提升,它指的是一種特殊的提升算法,在這種算法中,我們適合一連串的 "樹樁"(有一個節(jié)點和兩個葉子的決策樹),并根據(jù)它們預測的準確程度對它們的最終投票進行加權(quán)。在每個迭代之后,我們對數(shù)據(jù)集進行重新加權(quán),對那些被前一個弱學習者錯誤分類的數(shù)據(jù)點給予更大的重視,這樣,這些數(shù)據(jù)點在迭代t+1期間就會得到 "特別關(guān)注"。
?
它與隨機森林相比如何?
特點隨機森林AdaBoost深度無限(一棵完整的樹)樹樁(帶有 2 個葉子的單個節(jié)點)樹木生長獨立依次投票相同加權(quán)
AdaBoost 算法
A) 統(tǒng)一初始化樣本權(quán)重為?
.
B) 對于每次迭代 t:
找到
ht(x)
?最小化的弱學習?器?
.
我們根據(jù)其準確性為弱學習器設(shè)置權(quán)重:?
增加錯誤分類觀察的權(quán)重:?
.
重新歸一化權(quán)重,使得?
.
C)將最終預測作為弱學習器預測的加權(quán)多數(shù)票:?
.
繪圖
我們將使用下面的函數(shù)來可視化我們的數(shù)據(jù)點,并可選擇覆蓋擬合 AdaBoost 模型的決策邊界。
def plot(X: np.ndaay,
y: np.ndrry,
cf=None) -> None:
""" 繪制2D的±個樣本,可選擇決策邊界 """
if not ax:
fig, ax = plt.sults(fgsze=(5, 5), di=100)
pad = 1
x_min, x_max = X[:, 0].min() - pad, X[:, 0].max() + pad
y_min, y_max = X[:, 1].min() - pad, X[:, 1].max() + pad
if saligs is not None:
sies = np.array(spl_wigts) * X.hae[0] * 100
else:
sze = np.oes(sape=X.shpe[0]) * 100
if cf:
xx, yy = np.ehrid(n.aange(x_min, x_max, plot_step),
p.aang(y_min, y_max, plot_step))
pdt(np.c_[xx.ravel(), yy.ravel()])
# 如果所有的預測都是正類,則相應(yīng)地調(diào)整顏色圖。
if list(np.niue(Z)) == [1]:
colors = ['r']
else:
colors = ['b', 'r']
ax.st_im(in+0.5, _ax-0.5)
ax.st_lm(ymin+0.5, yax-0.5)
數(shù)據(jù)集
我們將使用類似的方法生成一個數(shù)據(jù)集??,但使用較少的數(shù)據(jù)點。這里的關(guān)鍵是我們想要兩個不可線性分離的類,因為這是 AdaBoost 的理想用例。
def maketat(n: it = 100, rased: it = None):
""" 生成一個用于評估AdaBoost分類器的數(shù)據(jù)集 """
nclas = int(n/2)
if ranmed:
np.ram.sed(rndoed)
X, y = me_gainqnes(n=n, n_fees=2, n_css=2)
plot(X, y)
使用 scikit-learn 進行基準測試
讓我們通過從scikit-learn導入AdaBoostClassifier,并將其擬合到我們的數(shù)據(jù)集上,來建立一個基準,看看我們的模型的輸出應(yīng)該是什么樣子的。
from skarn.esele import AdosClaser
bnh = Adostlier(netrs=10, atm='SAMME').fit(X, y)
plat(X, y, bech)
tnr = (prdict(X) != y).man()
分類器在 10 次迭代中完全擬合訓練數(shù)據(jù)集,我們數(shù)據(jù)集中的數(shù)據(jù)點被合理分離。
編寫自己的AdaBoost分類器
下面是我們的AdaBoost分類器的框架代碼。擬合模型后,我們將把所有的關(guān)鍵屬性保存到類中--包括每次迭代的樣本權(quán)重--這樣我們就可以在以后檢查它們,以了解我們的算法在每一步的作用。
下表顯示了我們將使用的變量名稱和前面在算法描述中使用的數(shù)學符號之間的映射。
變量數(shù)學sampleweight
wi(t)stump
ht(x)stumpweight
αterror
εtpredict(X)
Ht(x)
class AdBst:
""" AdaBoost分類器 ?"""
def __init__(self):
self.sump = None
self.stup_weght = None
self.erro = None
self.smle_weih = None
def _ceck_X_y(self, X, y):
""" 驗證關(guān)于輸入數(shù)據(jù)格式的假設(shè)"""
assrt st(y) == {-1, 1}
reurn X, y
擬合模型
回想一下我們的算法來擬合模型:
找到
ht(x)
?最小化的弱學習?器?
.
我們根據(jù)其準確性為弱學習器設(shè)置權(quán)重:?
增加錯誤分類觀察的權(quán)重:?
. 注意?
當假設(shè)與標簽一致時將評估為 +1,當它與標簽不一致時將評估為 -1。
重新歸一化權(quán)重,使得?
.
下面的代碼本質(zhì)上是上面的一對一的實現(xiàn),但是有幾點需要注意:
由于這里的重點是理解AdaBoost的集合元素,我們將調(diào)用DecinTeassfir(mxdpth=1, mlefnes=2)實現(xiàn)挑選每個ht(x)的邏輯。
我們在 for 循環(huán)之外設(shè)置初始統(tǒng)一樣本權(quán)重,并在每次迭代 t 內(nèi)設(shè)置 t+1 的權(quán)重,除非它是最后一次迭代。我們在這里特意在擬合模型上保存一組樣本權(quán)重,以便我們以后可以在每次迭代時可視化樣本權(quán)重。
def ft(slf, X: narry, y: ndray, ites: int):
""" 使用訓練數(shù)據(jù)擬合模型 """
X, y = slf._chck_X_y(X, y)
n = X.shpe[0]
# 啟動Numpy數(shù)組
self.smle_wegts = np.zos(shpe=(itrs, n))
self.tumps = np.zeos(she=iters, dtpe=obect)
# 均勻地初始化權(quán)重
sef.sampewegts[0] = np.one(shpe=n) / n
for t in range(iters):
# 擬合弱學習器
fit(X, y, smpe_eght=urrsmle_igts)
# 從弱學習者的預測中計算出誤差和樹樁權(quán)重
predict(X)
err = cu_seghts[(pred != y)].sum()# / n
weiht = np.log((1 - err) / err) / 2
# 更新樣本權(quán)重
newweis = (
crrawe * np.exp(-sum_wiht * y * tupd)
)
# 如果不是最終迭代,則更新t+1的樣本權(quán)重
if t+1 < ies:
sef.smpe_wit[t+1] = ne_saml_wigt
# 保存迭代的結(jié)果
sef.sups[t] = tump
做出預測
我們通過采取“加權(quán)多數(shù)投票”來做出最終預測,計算為每個樹樁的預測及其相應(yīng)樹樁權(quán)重的線性組合的符號 (±)。
def pedc(self, X):
""" 使用已經(jīng)擬合的模型進行預測 """
supds = np.aray([stp.pect(X) for sump in slf.stps])
return np.sgn(np.dt(self.tum_whts, sumpreds))
表現(xiàn)
現(xiàn)在讓我們把所有東西放在一起,用與我們的基準測試相同的參數(shù)來擬合模型。
# 將我們單獨定義的函數(shù)指定為分類器的方法
AaBt.fit = fit
Adostreit = pedct
plot(X, y, clf)
err = (clf.prdc(X) != y).mean()
不錯! 我們?nèi)〉昧伺csklearn基準完全相同的結(jié)果。我挑選了這個數(shù)據(jù)集來展示AdaBoost的優(yōu)勢,但你可以自己運行這個筆記本,看看它是否與輸出結(jié)果相匹配,無論起始條件如何。
可視化
由于我們把所有的中間變量作為數(shù)組保存在我們的擬合模型中,我們可以使用下面的函數(shù)來可視化我們的集合學習器在每個迭代t的演變過程。
左欄顯示了所選擇的 "樹樁 "弱學習器,它與ht(x)相對應(yīng)。
右邊一欄顯示了到目前為止的累積強學習器。?Ht(x)。
數(shù)據(jù)點標記的大小反映了它們的相對權(quán)重。在上一次迭代中被錯誤分類的數(shù)據(jù)點將被更多地加權(quán),因此在下一次迭代中顯得更大。
def truost(clf, t: int):
""" AdaBoost的擬合,直到(并包括)某個特定的迭代。 """
nwwghts = clf.suweighs[:t]
def plotost(X, y, clf, iters=10):
""" 在每個迭代中繪制出弱學習者和累積強學習者。 """
# 更大的網(wǎng)格
fig, axs = subplos(fisze=(8,ters*3),
nrows=iers,
ncls=2,
shaex=True,
dpi=100)
# 繪制弱學習者
plotot(X, y, cf.[i],
saplweghs=clf.saple_wigts[i],
aoat=False, a=ax1)
#繪制強學習者
truost(clf, t=i + 1)
pltot(X, y, tun_cf,
weights=smplweih[i], ax=ax2)
plt.t_aot()
為什么有些迭代沒有決策邊界?
您可能會注意到,我們的弱學習器在迭代 t=2,5,7,10 時將所有點歸類為正。發(fā)生這種情況是因為給定當前樣本權(quán)重,只需將所有數(shù)據(jù)點預測為正值即可實現(xiàn)最低誤差。請注意,在上面這些迭代的每個圖中,負樣本被按比例更高權(quán)重的正樣本包圍。
沒有辦法畫出一個線性決策邊界來正確分類任何數(shù)量的負面數(shù)據(jù)點,而不對正面樣本的更高累積權(quán)重進行錯誤分類。不過這并不能阻止我們的算法收斂。所有的負數(shù)點都被錯誤分類,因此樣本權(quán)重增加。這種權(quán)重的更新使得下一次迭代的弱學習者能夠發(fā)現(xiàn)一個有意義的決策邊界。
為什么我們對 alpha_t 使用那個特定的公式?
為什么我們使用這個特定的值?αt
?我們可以證明選擇?
?最小化在訓練集上的指數(shù)損失?
?。
忽略符號函數(shù),我們H
?在迭代時?的強學習器?t
?是弱學習器的加權(quán)組合?h(x)
。在任何給定的迭代中?t
,我們可以Ht(x)?
遞歸地將其定義?為迭代時的值?t?1
?加上當前迭代的加權(quán)弱學習器。
我們應(yīng)用于 H 的損失函數(shù)是所有 n 個數(shù)據(jù)點的平均損失??梢蕴娲?的遞歸定義?Ht(x)
,并使用恒等式分割指數(shù)項?
.
現(xiàn)在我們?nèi)p失函數(shù)關(guān)于 的導數(shù)?αt
?并將其設(shè)置為零以找到最小化損失函數(shù)的參數(shù)值??梢詫⒖偤头譃閮蓚€:case where?ht(xi)=yi
?和 case where??ht(xi)≠yi
。
最后,我們認識到權(quán)重之和等同于我們前面討論的誤差計算:∑Dt(i)=?t。進行置換,然后進行代數(shù)操作,我們就可以分離出αt。
?
進一步閱讀
sklearn.ensemble.AdaBoostClassifier?– 官方 scikit-learn 文檔
最受歡迎的見解
1.從決策樹模型看員工為什么離職
2.R語言基于樹的方法:決策樹,隨機森林
3.python中使用scikit-learn和pandas決策樹
4.機器學習:在SAS中運行隨機森林數(shù)據(jù)分析報告
5.R語言用隨機森林和文本挖掘提高航空公司客戶滿意度
6.機器學習助推快時尚精準銷售時間序列
7.用機器學習識別不斷變化的股市狀況——隱馬爾可夫模型的應(yīng)用
8.python機器學習:推薦系統(tǒng)實現(xiàn)(以矩陣分解來協(xié)同過濾)
9.python中用pytorch機器學習分類預測銀行客戶流失