AdaBoost (classification)

Basic

AdaBoost สำหรับการจำแนก | จากแนวคิดสู่สูตรและโค้ด

AdaBoost เป็นอัลกอริทึม Boosting ที่ให้น้ำหนักใหม่กับตัวอย่างที่โมเดลก่อนหน้าทำผิด แล้วฝึกตัวเรียนรู้แบบอ่อน (weak learner) ตัวถัดไปให้โฟกัสจุดยากมากขึ้น เมื่อรวม weak learner จำนวนมากเข้าด้วยกันจะได้ตัวจำแนกที่แข็งแรง


1. ภาพรวมเชิงสัญชาติญาณ #

  1. โมเดลตัวแรกฝึกบนข้อมูลที่ให้น้ำหนักเท่ากันทุกตัวอย่าง
  2. มองหาตัวอย่างที่ทำนายผิด เพิ่มน้ำหนักให้จุดเหล่านั้น
  3. ฝึก weak learner ตัวใหม่โดยให้จุดที่มีน้ำหนักมากมีผลกระทบต่อ loss มากขึ้น
  4. ทำซ้ำ T รอบ จากนั้นรวมผลด้วยการโหวตแบบถ่วงน้ำหนัก (ค่าถ่วงคือ \(\alpha_t\) ที่ขึ้นกับความแม่นของโมเดลย่อย)

2. สูตรสำหรับกรณีสองคลาส #

ให้ป้าย \(y_i \in {-1, +1}\) และ weak learner \(h_t(x) \in {-1, +1}\)

  • คำนวณอัตราความผิดพลาดแบบถ่วงน้ำหนัก $$ \varepsilon_t = \frac{\sum_i w_i^{(t)} ,\mathbf{1}[y_i \ne h_t(x_i)]}{\sum_i w_i^{(t)}} $$
  • น้ำหนักของ weak learner $$ \alpha_t = \tfrac{1}{2}\ln\frac{1-\varepsilon_t}{\varepsilon_t} $$
  • อัปเดตน้ำหนักตัวอย่าง $$ w_i^{(t+1)} = w_i^{(t)} \exp!\big(\alpha_t,\mathbf{1}[y_i \ne h_t(x_i)]\big) $$

การพยากรณ์สุดท้าย $$ H(x) = \operatorname{sign}!\bigg(\sum_{t=1}^T \alpha_t, h_t(x)\bigg) $$


3. มุมมองผ่านมาร์จินและ loss #

AdaBoost ลด exponential loss

$$ \mathcal{L} = \sum_{i=1}^n \exp(-y_i F(x_i)), \qquad F(x) = \sum_t \alpha_t h_t(x) $$

มาร์จิน \(m_i = y_i F(x_i)\) ใหญ่แปลว่าโมเดลมั่นใจและถูกต้อง Loss จะเล็ก ส่วนมาร์จินเล็กหรือติดลบจะโดนลงโทษหนัก

ใน scikit-learn มี algorithm="SAMME" (ใช้เมื่อโมเดลย่อยให้ผลเป็นฉลาก) และ algorithm="SAMME.R" (ใช้ผลจาก predict_proba). ค่า default คือ SAMME.R และรองรับหลายคลาส


4. ตัวอย่างโค้ด #

import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score, RocCurveDisplay
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier

X, y = make_classification(
    n_samples=2500,
    n_features=20,
    n_informative=10,
    n_redundant=4,
    n_clusters_per_class=5,
    random_state=42,
)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.33, random_state=42
)

base = DecisionTreeClassifier(max_depth=2, random_state=117117)

clf = AdaBoostClassifier(
    estimator=base,
    n_estimators=50,
    learning_rate=0.5,
    algorithm="SAMME.R",
    random_state=117117,
).fit(X_train, y_train)

y_score = clf.predict_proba(X_test)[:, 1]
auc = roc_auc_score(y_test, y_score)
print(f"ROC-AUC: {auc:.3f}")

RocCurveDisplay.from_predictions(y_test, y_score)
plt.grid(alpha=0.3)
plt.show()

5. ผลของไฮเปอร์พารามิเตอร์ #

  • learning_rate: เล็กลงจะทำให้แต่ละ weak learner มีค่าน้ำหนักน้อยลง ต้องเพิ่ม n_estimators เพื่อชดเชย
  • n_estimators: เพิ่มจำนวนโมเดลย่อย เพื่อประสิทธิภาพสูงขึ้น แต่ระวัง overfitting/เวลาเรียนรู้นาน
  • base_estimator: โดยมากใช้ decision tree ลึก 1–3 ระดับ (stumps) เพื่อให้เป็น “weak learner” จริง ๆ

สามารถวาดกราฟ learning_rate หรือนับจำนวน estimator เพื่อดูแนวโน้ม AUC ได้เหมือนในตัวอย่างต้นฉบับ


6. เชิงปฏิบัติ #

  • ใช้ sample_weight หรือ class_weight เมื่อคลาสไม่สมดุล
  • ถ้าต้องใช้ความน่าจะเป็นที่ calibrate ดีขึ้น ให้ต่อด้วย CalibratedClassifierCV
  • ตรวจ curve ของ train/test เพื่อตรวจจับ overfitting (เพิ่ม n_estimators หรือปรับ learning_rate)
  • ใช้ ROC-AUC หรือ PR-AUC เพื่อประเมินในงานที่ต้องการค่าความน่าจะเป็น

สรุป #

  • AdaBoost = การเน้นจุดที่ยากขึ้นเรื่อย ๆ + การรวมเสียงแบบถ่วงน้ำหนัก
  • มีพื้นฐานจากการเพิ่มมาร์จินและลด exponential loss
  • ปรับ learning_rate × n_estimators × ความลึกของต้นไม้ ให้เหมาะ
  • ใช้ได้ดีกับข้อมูลที่มี noise ปานกลางและแสดงผลผ่านกราฟได้ง่าย