目錄
- 1. 作者介紹
- 2. 什么是AdaBoost?
- 2.1 什么是弱分類器
- 2.2 什么是強分類器
- 2.3 如何自適應增強
- 2.4 如何組合弱分類器成為一個強分類器?
- 3. 什么是Wine數據集
- 3.1 Wine 數據集
- 3.2 Wine 數據集結構
- 4. 使用AdaBoost分類方法實現對Wine數據集分類
- 5. 完整代碼
1. 作者介紹
趙俊旗,男,西安工程大學電子信息學院,2023級研究生
研究方向:水下目標檢測與信號處理
電子郵件:2230648022@qq.com
徐達,男,西安工程大學電子信息學院,2023級研究生,張宏偉人工智能課題組
研究方向:機器視覺與人工智能
電子郵件:1374455905@qq.com
2. 什么是AdaBoost?
AdaBoost (Adaptive Boosting-自適應增強), AdaBoost通過組合多個弱分類器(那些比隨機猜測略好的分類器)來構建一個強分類器。
這短短一句話讀完就會發現信息量挺大的,什么是弱分類器?什么是強分類器?是如何進行自適應增強的?以及怎么組合成一個強分類器的?把這四個問題搞懂,可能就會更容易理解AdaBoost.
2.1 什么是弱分類器
弱分類器是指分類準確率在 60% 到 80% 之間的分類器,即比隨機預測略好,但準確率不高。比如一個二分類問題,隨機猜測進行分類的正確率都有50%,所以弱分類器比隨即猜測略好一些。
弱分類器的常用類型包括:決策樹樁、K近鄰分類器、樸素貝葉斯分類器等。
如決策樹樁:
2.2 什么是強分類器
強分類器是指分類準確率在 90% 以上的分類器。
2.3 如何自適應增強
這是理解Adaboost的一個重點!其核心思想是關注那些被前一輪弱分類器錯誤分類的樣本,通過逐步調整樣本的權重,使后續的弱分類器更注重這些困難樣本,從而提高整體分類器的準確性。
抽象的概念不容易理解? 舉個例子:
有一個簡單的分類任務,將5個顏色分別為紅色(標簽+1)和藍色(標簽-1)的圓點分開,使用3個決策樹樁作為弱分類器。
STEP1:使用第一個弱分類器h1(即使用第1個決策樹)
(1)初始化樣本權重(使所有樣本權重相等),因為共5個圓點,所以共5個樣本,每個樣本的權重為wi =1/5。
(2)計算第一個弱分類器的錯誤率?1和權重α1
①計算第一個弱分類器錯誤率?1:
其中wi為樣本權重(即上述的1/5), I(yi≠hi(xi))為指示函數, hi(xi)為弱分類器的預測, yi為真實值,指示函數在這里的意義是當預測與真實值相等時,指示函數為0;當預測與真實值不相等時,指示函數為1,所以在這里就相當于增加了錯誤樣本的權重,對應上述“更注重分類錯誤的樣本”。
如我們這5個樣本里有兩個被分類錯誤,分別是第1個和第3個,則錯誤率?1計算為:
②計算第一個弱分類器的權重α1
其中?t為第①步計算出來的錯誤率。可以根據表達式看到,錯誤率越大,此弱分類器的權重越小,此弱分類器在所有的3個弱分類器的話語權也就越低。反之,錯誤率越小,其權重越大,此弱分類器在所有的3個弱分類器的話語權也就越高。
所以第一個弱分類器的權重α1計算為:
(3)更新樣本權重
根據初始樣本權重wi和計算出來的第一個弱分類器的權重α1以及其是否被真實預測可得到新的樣本權重。其中若被真實預測, yiht(xi)的值為11或(-1)(-1)均為1,若沒有被真實預測,則yiht(xi)的值為1*(-1)或(-1)*1均為-1,可以根據表達式觀察到,當其沒有被真實預測時,其下一次的權重將會增大。
所以經過第一個弱分類器得到新的樣本權重為:
可以看到,在第1個和第3個樣本被錯誤分類時,其樣本的權重會增大,回扣AdaBoost核心思想里“更注重分類錯誤的樣本”。
現在經過第一個分類器后,可以得到其樣本新的權重 和第1個弱分類器的權重α1。
STEP2: 使用第二個弱分類器h2(即使用第2個決策樹),此時不再使所有樣本權重相等,而是使用經第一個弱分類器更新完成的新的權重wi(2),計算第2個弱分類器的錯誤率?2從而得到權重α2,進而可以得到一個更新的樣本權重wi(3)(即重復STEP1)。
STEP3:使用第三個弱分類器h3(即使用第3個決策樹),此時使用經第二個弱分類器更新完成的更新的權重wi(3),計算第3個弱分類器的錯誤率?3從而得到權重α3,進而可以得到一個最新的樣本權重wi(4)(即重復STEP1)。
好了,現在得到了三個弱分類器的權重,是時候要將他們組合在一起了。
2.4 如何組合弱分類器成為一個強分類器?
強分類器𝐻(𝑥)的預測結果通過弱分類器加權投票決定。
現在有三個弱分類器 h1,h2,h3 及其對應的權重 α1,α2,α3,每個弱分類器會對輸入樣本進行分類,得到的結果是要么是+1要么是-1(即二分類任務中的類別標簽)。
現在有一個輸入樣本x,
1.弱分類器1(h1)對輸入樣本x的預測是 -1,權重α1 = 0.2027
2.弱分類器2(h2)對輸入樣本x的預測是 +1,權重α2= 0.5
3.弱分類器3(h3)對輸入樣本x的預測是 +1,權重α3 =0.8
組合最終的強分類器
強分類器 𝐻(𝑥)的預測結果通過加權投票決定:
其中sign(x)為符號函數,當x大于0時值為+1,x小于0時值為-1。所以加權投票組成強分類器分類結果為:
至此我們更能清晰地理解何為AdaBoost自適應增強。
注意:一般的AdaBoost自適應增強需要多個弱分類器才能達到最好的效果,此處為了簡便理解,選擇3個弱分類器;同時要注意理解樣本的權重和弱分類器的權重,樣本權重是為了下一個弱分類器更關注上一個分類錯誤的樣本,弱分類器的權重是為了看出其在構建強分類器時話語權的強弱。
AdaBoost的部分優點如下:
簡單且靈活:AdaBoost可以與任何弱分類器一起使用,且易于實現。
無需調整參數:AdaBoost對弱分類器的選擇和參數設定相對不敏感。
自動聚焦難分類樣本:通過動態調整樣本權重,AdaBoost使后續的分類器更關注難分類的樣本。
AdaBoost的部分缺點如下:
對噪聲敏感:因為錯誤分類的樣本權重會增加,數據集中存在的噪聲點可能會導致模型過擬合。
需要多個弱分類器:AdaBoost的性能依賴于多個弱分類器的結合,單個弱分類器的性能不能太差。
3. 什么是Wine數據集
Wine 數據集是一個經典的機器學習數據集,用于多分類任務。該數據集包含來自意大利同一地區的三種不同類型的葡萄酒的化學分析結果。每種葡萄酒的特征和類別標簽都已標注,用于分類模型的訓練和評估。
3.1 Wine 數據集
3.2 Wine 數據集結構
在python的scikit-learn 庫中,Wine 數據集可以直接通過 load_wine 函數加載,其中alcohol, malic_acid, ash,等是特征列,target 是目標變量,表示紅酒的類別。
導入并查看前5行數據(以圖片展示,完整程序附后):
其數據集結構為:
4. 使用AdaBoost分類方法實現對Wine數據集分類
(1)首先pip安裝scikit-learn 和 pandas 庫
pip install scikit-learn pandas
(2) 加載并預處理數據集
? 使用 scikit-learn 自帶的 Wine 數據集,它已經分為特征數據x和目標標簽y
? 對特征數據進行標準化處理,確保每個特征的均值為0,方差為 1,有助于提升模型的性能。
? 將數據集劃分為訓練集(70%)和測試集(30%)
(3)構建并訓練 AdaBoost 模型
? 使用決策樹樁作為弱分類器
? 構建一個 AdaBoost 分類器,并用訓練集數據訓練模型n_estimators=50 表示使用 50 個弱分類器
(4)預測與評估
對測試集進行預測,并使用準確率來評估模型的性能。
打印輸出:
(5)可視化分類結果
①混淆矩陣
③決策邊界
④學習曲線
⑤特征重要性
另外:可以考慮改變訓練集和測試集比例對結果的影響,以及改變迭代次數(弱分類器個數)對結果的影響。
5. 完整代碼
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, confusion_matrix, ConfusionMatrixDisplay# 加載數據集
wine = load_wine()
X, y = wine.data, wine.target# 數據標準化處理
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)# 使用PCA將數據降維到2D以便可視化
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)# 分割數據集為訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X_pca, y, test_size=0.3, random_state=42)# 使用決策樹樁作為弱分類器
base_estimator = DecisionTreeClassifier(max_depth=1)# 初始化AdaBoost分類器,訓練模型n_estimators=50,即為50個弱分類器(可更改分類器個數觀察分類效果)
clf = AdaBoostClassifier(base_estimator=base_estimator, n_estimators=50, random_state=42)
clf.fit(X_train, y_train)# 評估模型,觀察準確率
y_pred = clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy:.2f}")# 繪制混淆矩陣
cm = confusion_matrix(y_test, y_pred, labels=clf.classes_)
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=clf.classes_)
disp.plot()
plt.title("Confusion Matrix")
plt.show()# 繪制決策邊界函數
def plot_decision_boundary(X, y, clf, ax, title=""):x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),np.arange(y_min, y_max, 0.02))Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])Z = Z.reshape(xx.shape)ax.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.RdYlBu)scatter = ax.scatter(X[:, 0], X[:, 1], c=y, s=30, edgecolor='k', cmap=plt.cm.RdYlBu)legend = ax.legend(*scatter.legend_elements(), title="Classes")ax.add_artist(legend)ax.set_title(title)# 初始化決策樹樁分類器并訓練初始模型
initial_clf = DecisionTreeClassifier(max_depth=1)
initial_clf.fit(X_train, y_train)# 繪制初始狀態和每10次迭代的決策邊界觀察第1、10、20、30、40、50次迭代的決策邊界
fig, axes = plt.subplots(3, 2, figsize=(20, 15))
axes = axes.flatten()plot_decision_boundary(X_test, y_test, initial_clf, axes[0], title="Initial State")for i in range(1, 6):n_estimators = i * 10clf_partial = AdaBoostClassifier(base_estimator=base_estimator, n_estimators=n_estimators, random_state=42)clf_partial.fit(X_train, y_train)plot_decision_boundary(X_test, y_test, clf_partial, axes[i], title=f"After {n_estimators} Estimators")plt.tight_layout()
plt.show()# 提取和顯示特征重要性
original_clf = AdaBoostClassifier(base_estimator=base_estimator, n_estimators=50, random_state=42)
original_clf.fit(X_scaled, y)feature_importances = np.mean([tree.feature_importances_ for tree in original_clf.estimators_
], axis=0)# 特征重要性可視化,觀察數據集哪幾個特征為主要影響因素
features = wine.feature_names
indices = np.argsort(feature_importances)[::-1]plt.figure(figsize=(10, 6))
plt.title("Feature Importances")
plt.bar(range(X.shape[1]), feature_importances[indices], align="center")
plt.xticks(range(X.shape[1]), np.array(features)[indices], rotation=90)
plt.xlim([-1, X.shape[1]])
plt.show()# 繪制學習曲線,觀察其錯誤率隨迭代次數的變化
n_estimators = len(clf.estimators_)
error_rate = np.zeros(n_estimators)for i, y_pred_iter in enumerate(clf.staged_predict(X_test)):error_rate[i] = 1 - accuracy_score(y_test, y_pred_iter)plt.figure(figsize=(10, 6))
plt.plot(range(1, n_estimators + 1), error_rate, marker='o', label='Test Error Rate')
plt.xlabel('Number of Estimators')
plt.ylabel('Error Rate')
plt.title('AdaBoost Test Error Rate vs. Number of Estimators')
plt.legend(loc='best')
plt.show()