機器學習算法——使用Adaboost進行分類性能提升

AdaBoost原理

Ensemble Learning(集成學習)

集成學習是指集合多個弱分類器以形成一個集成的強分類器。集成學習的框架可以通過下圖來反映
在這裏插入圖片描述
也就是說,集成學習是一種集合了多個機器學習模型的“意見”,已完成最後決策的機制。
常見的集成學習策略有三種:

  • Bagging
  • Boosting
  • Stacking

Bagging和Boosting的不同可以通過下面這張圖來理解
在這裏插入圖片描述
Bagging對數據集進行隨機採樣,構成 NN 組,然後每組使用模型單獨訓練,最後進行表決,是一種類似於串聯的結構。而Boosting則是不改變訓練集的情況下,不斷調整樣本權重來調優弱分類器性能,實際上是一種串行的思路。
而我們接下來要探討的AdaBoost是屬於Boosting策略型集成算法的一種。

AdaBoost工作機制

在這裏插入圖片描述

分類器實現

準備工作

以下是我們需要用的工具

import numpy as np
import pandas as pd
from random import seed
from random import randrange
from math import sqrt
from math import exp
from math import pi
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score, RepeatedStratifiedKFold
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
import operator
import plotly.express as px
from plotly.offline import init_notebook_mode
init_notebook_mode(connected=True)
import plotly.graph_objects as go
from plotly.subplots import make_subplots

基本接口調用

從最簡單的開始,我們調用sklearn的AdaBoost分類器接口,完成最基本的實現。

# 隨機創建一個預測問題
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=6)
# 調用AdaBoost分類策略
model = AdaBoostClassifier()
# 交叉檢驗
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# 計算準確率
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
print('準確率: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))

該問題的輸出結果類似以下:

準確率: 0.806 (0.041)

更換元分類器

最常見的AdaBoost元分類器是決策樹,這也是sklearn中默認的元分類器,如果我們不傳入任何參數進入AdaBoostClassifier,那麼它就會默認使用一層的決策樹來作爲它的元分類器。但是實際上,AdaBoost接受所有能夠樣本賦權的分類器作爲其的元分類器,而我們最常見的賦權分類器有兩種,即決策樹和支持向量機(SVM)。在這個部分我們嘗試在一個分類問題中找到一個較優的元分類器。
首先,我們先嚐試以不同層數的決策樹作爲元分類器來看看AdaBoost的效果

def get_dataset(iris=True):
    """
    獲取研究的數據集
    @是否用鳶尾花數據集進行測試
    """
    if iris == True:
        data = load_iris()
        X = data.data
        y = data.target
    else:
        X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=6)
    return X, y
 
def get_models():
    """
    產生弱分類器(基元)
    """
    models = dict()
    for i in range(1,11):
        models[str(i)] = AdaBoostClassifier(base_estimator=DecisionTreeClassifier(max_depth=i))
    return models
 ![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20200516110831264.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTY3Nzg3Ng==,size_16,color_FFFFFF,t_70)
def evaluate_model(model):
    """
    使用交叉檢驗評估模型
    @model: 模型
    """
    cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
    scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
    return scores
 
X, y = get_dataset(iris=False)
models = get_models()
results, names = [], []
for name, model in models.items():
    scores = evaluate_model(model)
    results.append(scores)
    names.append(name)
    print('>%s %.3f (%.3f)' % (name, np.mean(scores), np.std(scores)))
# 畫圖
fig = go.Figure()
c = ['hsl('+str(h)+',50%'+',50%)' for h in np.linspace(0, 360, len(results))]
for result, i in zip(results, [j for j in range(len(results))]):
    fig.add_trace(go.Box(
    y=result,
    name=names[i],
    jitter=0.3,
    pointpos=-1.8,
    boxpoints='all',
    marker_color=c[i],
    line_color=c[i],
    boxmean='sd'))
fig.update_layout(template='none')
fig.show()

以不同層數的決策樹作爲元分類器得到的精確度結果:

>1 0.806 (0.041)
>2 0.863 (0.028)
>3 0.866 (0.030)
>4 0.890 (0.030)
>5 0.917 (0.026)
>6 0.924 (0.021)
>7 0.923 (0.021)
>8 0.930 (0.026)
>9 0.933 (0.021)
>10 0.925 (0.027)

可視化一下這個結果:
在這裏插入圖片描述
接着,我們將元分類器換爲支持向量機:

# 隨機創建一個預測問題
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=6)
# 建立支持向量機元分類器
svc = SVC(probability=True, kernel='linear')
# 調用AdaBoost分類策略
model = AdaBoostClassifier(base_estimator=svc)
# 交叉檢驗
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# 計算準確率
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
print('準確率: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))

結果是

準確率: 0.719 (0.101)

對比之下,決策樹似乎更適合和AdaBoost搭配(當然,具體問題具體分析),後面我就先使用決策樹作爲元分類器來進行實驗。

確定元分類器數量

默認情況下,我們是將50個決策樹進行串聯組合,當然我們也可以按照需求調整分類器數量,下面我們做一個模擬:

def get_models():
	models = dict()
	models['10'] = AdaBoostClassifier(n_estimators=10)
	models['50'] = AdaBoostClassifier(n_estimators=50)
	models['100'] = AdaBoostClassifier(n_estimators=100)
	models['500'] = AdaBoostClassifier(n_estimators=500)
	models['1000'] = AdaBoostClassifier(n_estimators=1000)
	models['5000'] = AdaBoostClassifier(n_estimators=5000)
	return models

我們將get_models()函數更換一下,來測試元分類器數量和最後的總體精確率之間有什麼關係。結果如下

>10 0.773 (0.039)
>50 0.806 (0.041)
>100 0.801 (0.032)
>500 0.793 (0.028)
>1000 0.791 (0.032)
>5000 0.782 (0.031)

在這裏插入圖片描述
可見,並不是說分類器越多,AdaBoost效果就越好,而且隨着分類器數量增加,AdaBoost的執行效率也會大大下降,複雜度急劇上升。

確定學習率

學習率是最基本的機器學習超參數,我們關注學習率變化對結果準確度的影響。

def get_models():
    models = dict()
    for i in np.arange(0.1, 2.1, 0.1):
        key = '%.3f' % i
        models[key] = AdaBoostClassifier(learning_rate=i)
    return models

還是更換get_models()函數。
結果

>0.100 0.767 (0.049)
>0.200 0.786 (0.042)
>0.300 0.802 (0.040)
>0.400 0.798 (0.037)
>0.500 0.805 (0.042)
>0.600 0.795 (0.031)
>0.700 0.799 (0.035)
>0.800 0.801 (0.033)
>0.900 0.805 (0.032)
>1.000 0.806 (0.041)
>1.100 0.801 (0.037)
>1.200 0.800 (0.030)
>1.300 0.799 (0.041)
>1.400 0.793 (0.041)
>1.500 0.790 (0.040)
>1.600 0.775 (0.034)
>1.700 0.767 (0.054)
>1.800 0.768 (0.040)
>1.900 0.736 (0.047)
>2.000 0.682 (0.048)

在這裏插入圖片描述

使用鳶尾花數據集檢驗

完成了上面的一些基本操作後,我使用鳶尾花數據集來測試AdaBoost的集成學習策略效果,併合單個決策樹分類器的效果進行對比。
AdaBoost(決策樹)

# 隨機創建一個預測問題
# X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=6)
X, y = get_dataset(iris=True)
# 調用AdaBoost分類策略
model = AdaBoostClassifier()
# 交叉檢驗
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# 計算準確率
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
print('準確率: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))

結果:

準確率: 0.947 (0.056)

AdaBoost(SVC)

# 隨機創建一個預測問題
# X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=6)
X, y = get_dataset(iris=True)
# 建立支持向量機元分類器
svc = SVC(probability=True, kernel='linear')
# 調用AdaBoost分類策略
model = AdaBoostClassifier(base_estimator=svc)
# 交叉檢驗
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# 計算準確率
n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')
print('準確率: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))

結果:

準確率: 0.964 (0.037)

決策樹
具體代碼見機器學習算法——手動搭建決策樹分類器(代碼+作圖)
結果:

算法的平均準確率: 94.000%
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章