跳到主要内容
4704 字
24 分钟
24 分钟读完

ARTICLE NOTE

Adaptive Boosting (AdaBoost) —— 自适应提升
浏览 0
热度 0

Adaptive Boosting (AdaBoost) —— 自适应提升

引言

上一篇文章中,我们讨论了 Bagging 与随机森林 —— 通过 Bootstrap 采样构建多棵并行的决策树,以投票方式降低方差。这种并行集成的策略有效驯服了单棵决策树的高方差问题,其核心在于“让多棵树独立生长,平等表决”。

AdaBoost 则走向了另一条截然不同的路径 —— 串行集成。它不再让基学习器独立生长,而是让它们按顺序依次生成,每一棵新树都聚焦于前序模型犯错的样本。这种“串行纠错”的直觉,可以用一个生动的比喻来概括:“错题本机制” —— 做错的题标记出来重点复习,再做新题,再标记新错题,反复迭代,最终将一系列“表现平平”的弱分类器组合成一个强分类器

AdaBoost 由 Freund 和 Schapire 于 1997 年正式提出,是 Boosting 家族最具影响力的奠基之作。其数学框架可被精炼地概括为“前向分步加法模型 + 指数损失函数” —— 每一轮通过解析优化指数损失,同时推导出两个核心更新公式:弱分类器的权重 αt\alpha_t(错误率越低、话语权越大)和样本权重 DtD_t(被错分的样本下一轮获得更高关注)。

我们将从这一框架出发,完成从损失函数到两个权重更新公式的完整推导,并揭示其与后续 GBM 之间的深层联系 —— AdaBoost 本质上是 GBM 在指数损失下的特例,而 GBM 则将损失函数从指数泛化为任意可微损失,将优化方式从解析求解扩展为函数空间中的梯度下降

Note

读完本文,你将彻底理解“串行纠错”的数学本质,并厘清 AdaBoost 与 GBM 之间的继承与泛化关系。

下一篇文章,我们将进入 Gradient Boosting Machine(GBM) ——它将 AdaBoost 的指数损失泛化为任意可微损失,把“错题本”的直觉升级为“梯度下降”的通用框架,为 XGBoost 与 LightGBM 等工程级实现奠定理论基础。


一、从决策树到Boosting

1.1 单棵决策树的困境

在上一篇文章中,我们详细讨论了决策树的构建与剪枝。单棵完全生长的决策树具有以下特点:

  • 低偏差:能够完美拟合训练数据
  • 高方差:训练数据的微小变化会导致完全不同的树

这就是决策树容易过拟合的根本原因。如果我们直接用一棵完整的决策树去做分类,在训练集上可能表现完美,但在测试集上往往“原形毕露”。

1.2 两个集成方向:并行 vs 串行

如何克服单棵决策树的不稳定性?集成学习给出了两个不同的答案:

并行集成(Bagging)串行集成(Boosting)
代表算法随机森林AdaBoost、GBM
构建方式多棵树独立生长多棵树串行生成
核心思想平等投票,降低方差串行纠错,降低偏差
树的特点完全生长的深树浅层弱学习器

Bagging(随机森林) :让多棵树并行生长,每棵树都是“独立的专家”,最后平等投票。就像专家会诊 —— 多位专家独立诊断后投票决定。

Boosting(AdaBoost) :让多棵树串行生长,后一棵树专门用来修正前一棵树的错误。就像渐进式诊疗 —— 先做初步诊断,发现错误后针对性复查,不断修正。

AdaBoost属于后者——串行集成。它的核心思想是:用一系列弱分类器(每棵树的深度都很浅,分类能力仅比随机猜测稍好一点点),通过串行地调整样本权重让每个新的弱分类器都重点关注前一轮被分错的样本,最终将这些弱分类器加权组合成一个强分类器

1.3 “错题本”的直觉

AdaBoost最直观的理解方式就是 “错题本”机制

想象你在准备一场考试:

  • 第一轮:你做完一套模拟卷(训练一个弱分类器),发现某些题做错了
  • 第二轮:你翻开错题本,重点复习那些做错的题(提高错题的权重),再做一套新卷子
  • 第三轮:又产生了新的错题,继续重点复习……
  • 最终:你把所有做过的卷子的经验综合起来(加权组合),形成一套完整的知识体系

AdaBoost的每一轮迭代都在做同样的事情 —— 增加前一个基学习器在训练过程中预测错误样本的权重,使得后续基学习器更加关注这些被错误标注的训练样本,尽可能纠正这些错误。

但需要注意的是,AdaBoost并不是只关注错题。它只是更偏向错题,而不是只看错题。就像复习时不能只看错题,也得看看做对的题 —— 只是错题的权重大一些。


二、AdaBoost的算法流程

2.1 符号约定

在正式进入算法之前,首先需要约定符号:

  • 训练集:{(x1,y1),(x2,y2),...,(xN,yN)}\{(x_1, y_1), (x_2, y_2), ..., (x_N, y_N)\},其中 yi{1,+1}y_i \in \{-1, +1\}
  • TT迭代次数(弱分类器的数量)
  • Dt(i)D_t(i):第 tt 轮中第 ii 个样本的权重
  • ht(x)h_t(x):第 tt 轮训练出的弱分类器
  • αt\alpha_t:第 tt 个弱分类器在最终集成模型中的权重
  • ϵt\epsilon_t:第 tt 个弱分类器的加权错误率

2.2 完整算法步骤

步骤1:初始化样本权重

将所有样本的权重设为相等:D1(i)=1N,i=1,2,...,ND_1(i) = \frac{1}{N}, \quad i = 1, 2, ..., N

步骤2:对 t=1,2,...,Tt = 1, 2, ..., T 迭代

(a) 训练弱分类器:在当前样本权重分布 DtD_t 下,训练一个弱分类器 ht(x)h_t(x)

(b) 计算加权错误率

ϵt=i=1NDt(i)I(ht(xi)yi)\epsilon_t = \sum_{i=1}^{N} D_t(i) \cdot \mathbb{I}(h_t(x_i) \neq y_i)

其中 I()\mathbb{I}(\cdot) 是指示函数,条件成立时为1,否则为0。

(c) 计算弱分类器的权重

αt=12ln(1ϵtϵt)\alpha_t = \frac{1}{2} \ln\left(\frac{1 - \epsilon_t}{\epsilon_t}\right)

(d) 更新样本权重

Dt+1(i)=Dt(i)exp(αtyiht(xi))ZtD_{t+1}(i) = \frac{D_t(i) \cdot \exp(-\alpha_t y_i h_t(x_i))}{Z_t}

其中 Zt=i=1NDt(i)exp(αtyiht(xi))Z_t = \sum_{i=1}^{N} D_t(i) \cdot \exp(-\alpha_t y_i h_t(x_i)) 是归一化因子,保证 iDt+1(i)=1\sum_i D_{t+1}(i) = 1

步骤3:输出最终强分类器

H(x)=sign(t=1Tαtht(x))H(x) = \text{sign}\left(\sum_{t=1}^{T} \alpha_t h_t(x)\right)

代码实现

import numpy as np
from sklearn.tree import DecisionTreeClassifier
class AdaBoost:
"""从零实现AdaBoost算法"""
def __init__(self, n_estimators=50):
self.n_estimators = n_estimators
self.alphas = []
self.weak_classifiers = []
def fit(self, X, y):
"""
X: shape (n_samples, n_features)
y: shape (n_samples,), 取值 {-1, +1}
"""
n_samples = X.shape[0]
# 步骤1:初始化样本权重
D = np.ones(n_samples) / n_samples
for t in range(self.n_estimators):
# 步骤2(a):训练弱分类器(决策树桩,深度为1)
weak_clf = DecisionTreeClassifier(max_depth=1)
weak_clf.fit(X, y, sample_weight=D)
predictions = weak_clf.predict(X)
# 步骤2(b):计算加权错误率
misclassified = (predictions != y)
epsilon = np.sum(D * misclassified)
# 防止除零或数值不稳定
if epsilon == 0:
epsilon = 1e-10
if epsilon == 1:
epsilon = 1 - 1e-10
# 步骤2(c):计算弱分类器的权重
alpha = 0.5 * np.log((1 - epsilon) / epsilon)
# 步骤2(d):更新样本权重
# 正确分类: 权重乘以 exp(-alpha),错误分类: 权重乘以 exp(alpha)
D = D * np.exp(-alpha * y * predictions)
D = D / np.sum(D) # 归一化
# 保存结果
self.alphas.append(alpha)
self.weak_classifiers.append(weak_clf)
return self
def predict(self, X):
"""预测:加权投票"""
# 计算所有弱分类器的加权预测之和
weighted_sum = np.zeros(X.shape[0])
for alpha, clf in zip(self.alphas, self.weak_classifiers):
weighted_sum += alpha * clf.predict(X)
return np.sign(weighted_sum)

三、前向分步加法模型:AdaBoost的数学框架

3.1 加法模型

AdaBoost最终得到的模型是一个加法模型(Additive Model)—— 多个基学习器的线性组合

H(x)=t=1Tαtht(x)H(x) = \sum_{t=1}^{T} \alpha_t h_t(x)

其中 ht(x)h_t(x) 是第 tt弱分类器αt\alpha_t 是其权重

这个形式看起来简单,但问题在于如何确定每一轮的 αt\alpha_thth_t

3.2 前向分步算法

前向分步算法(Forward Stagewise Algorithm) 是解决这个问题的核心策略。此算法的核心思想是:从前向后,每一步只优化当前这一个基分类器,固定之前已经选好的所有基分类器不变

具体来说:

  1. 初始化 H0(x)=0H_0(x) = 0
  2. t=1,2,...,Tt = 1, 2, ..., T
    • 固定 Ht1(x)H_{t-1}(x) 不变
    • 选择 (αt,ht)(\alpha_t, h_t) 使得损失函数最小:(αt,ht)=argminα,hi=1NL(yi,Ht1(xi)+αh(xi))(\alpha_t, h_t) = \arg\min_{\alpha, h} \sum_{i=1}^{N} L(y_i, H_{t-1}(x_i) + \alpha h(x_i))
    • 更新:Ht(x)=Ht1(x)+αtht(x)H_t(x) = H_{t-1}(x) + \alpha_t h_t(x)

由此可见:前向分步算法将一个复杂的全局优化问题(同时优化所有 αt\alpha_thth_t)转化为 TT 个相对简单的局部优化问题(每一步只优化一个 αt\alpha_thth_t)。

3.3 指数损失函数

AdaBoost使用的损失函数 —— 指数损失函数(Exponential Loss)

L(y,H(x))=eyH(x)L(y, H(x)) = e^{-y H(x)}

其中 y{1,+1}y \in \{-1, +1\}H(x)H(x) 是模型的预测值(实数,不一定是 ±1)。

使用指数损失的原因

  1. 数学性质好:指数函数连续可微,便于优化
  2. 与0-1损失一致:最小化指数损失等价于最小化分类错误率
  3. 推导简洁:指数损失天然导出了AdaBoost的权重更新公式

定理:AdaBoost算法是前向分步加法算法在以指数函数为损失函数时的特例


四、完整推导:从指数损失到AdaBoost的更新公式

4.1 推导弱分类器的权重 αt\alpha_t

假设在第 tt 轮,我们已经有了前 t1t-1 轮的集成模型 Ht1(x)H_{t-1}(x)。现在要选择新的弱分类器 ht(x)h_t(x)权重 αt\alpha_t,使得指数损失最小

(αt,ht)=argminα,hi=1Nexp(yi(Ht1(xi)+αh(xi)))(\alpha_t, h_t) = \arg\min_{\alpha, h} \sum_{i=1}^{N} \exp\left(-y_i \left(H_{t-1}(x_i) + \alpha h(x_i)\right)\right)

wi(t)=exp(yiHt1(xi))w_i^{(t)} = \exp(-y_i H_{t-1}(x_i))(上一轮更新后的样本权重,未归一化),则目标函数变为:

i=1Nwi(t)exp(αyih(xi))\sum_{i=1}^{N} w_i^{(t)} \exp(-\alpha y_i h(x_i))

对于固定的 α\alpha,最小化上式等价于最小化加权错误率:

ϵt=i=1Nwi(t)I(h(xi)yi)i=1Nwi(t)\epsilon_t = \frac{\sum_{i=1}^{N} w_i^{(t)} \mathbb{I}(h(x_i) \neq y_i)}{\sum_{i=1}^{N} w_i^{(t)}}

现在推导 αt\alpha_t 的表达式

将样本分为两类:被 hh 正确分类的(yih(xi)=1y_i h(x_i) = 1)和错误分类的(yih(xi)=1y_i h(x_i) = -1)。

目标函数可以写成:

i:yi=h(xi)wi(t)eα+i:yih(xi)wi(t)eα=(1ϵt)eα+ϵteα\sum_{i: y_i = h(x_i)} w_i^{(t)} e^{-\alpha} + \sum_{i: y_i \neq h(x_i)} w_i^{(t)} e^{\alpha} = (1 - \epsilon_t) e^{-\alpha} + \epsilon_t e^{\alpha}

(这里假设权重已经归一化,即 wi(t)=1\sum w_i^{(t)} = 1

α\alpha 求导并令其为零:

ddα[(1ϵt)eα+ϵteα]=(1ϵt)eα+ϵteα=0\frac{d}{d\alpha} \left[(1 - \epsilon_t) e^{-\alpha} + \epsilon_t e^{\alpha}\right] = -(1 - \epsilon_t) e^{-\alpha} + \epsilon_t e^{\alpha} = 0

解得:

αt=12ln(1ϵtϵt)\boxed{\alpha_t = \frac{1}{2} \ln\left(\frac{1 - \epsilon_t}{\epsilon_t}\right)}

这就是AdaBoost中弱分类器权重的计算公式。

4.2 推导样本权重的更新公式

下列推导样本权重 wi(t)=exp(yiHt1(xi))w_i^{(t)} = \exp(-y_i H_{t-1}(x_i)) 的更新规律

在得到 hth_tαt\alpha_t 后:

wi(t+1)=exp(yiHt(xi))=exp(yi(Ht1(xi)+αtht(xi)))=wi(t)exp(αtyiht(xi))w_i^{(t+1)} = \exp(-y_i H_t(x_i)) = \exp(-y_i (H_{t-1}(x_i) + \alpha_t h_t(x_i))) = w_i^{(t)} \cdot \exp(-\alpha_t y_i h_t(x_i))
  • ht(xi)=yih_t(x_i) = y_i(分类正确)时:wi(t+1)=wi(t)eαtw_i^{(t+1)} = w_i^{(t)} \cdot e^{-\alpha_t}

  • ht(xi)yih_t(x_i) \neq y_i(分类错误)时:wi(t+1)=wi(t)eαtw_i^{(t+1)} = w_i^{(t)} \cdot e^{\alpha_t}

由于 αt>0\alpha_t > 0(因为 ϵt<0.5\epsilon_t < 0.5),所以分类正确的样本权重减小(乘以 eαt<1e^{-\alpha_t} < 1),分类错误的样本权重增大(乘以 eαt>1e^{\alpha_t} > 1

这正是AdaBoost “错题本”机制的数学本质 —— 被分错的样本在下一轮获得更高的权重

统一写成:

wi(t+1)=wi(t)exp(αtyiht(xi))\boxed{w_i^{(t+1)} = w_i^{(t)} \cdot \exp(-\alpha_t y_i h_t(x_i))}

加上归一化因子 ZtZ_t 后:

Dt+1(i)=Dt(i)exp(αtyiht(xi))Zt\boxed{D_{t+1}(i) = \frac{D_t(i) \cdot \exp(-\alpha_t y_i h_t(x_i))}{Z_t}}

其中 Zt=i=1NDt(i)exp(αtyiht(xi))Z_t = \sum_{i=1}^{N} D_t(i) \exp(-\alpha_t y_i h_t(x_i))

代码实现

# 验证权重更新公式的正确性
def verify_weight_update():
np.random.seed(42)
N = 10
y = np.random.choice([-1, 1], N)
h = np.random.choice([-1, 1], N)
epsilon = 0.3
alpha = 0.5 * np.log((1 - epsilon) / epsilon)
D = np.ones(N) / N
# 更新权重
D_new_raw = D * np.exp(-alpha * y * h)
D_new = D_new_raw / np.sum(D_new_raw)
# 检查:错误分类的样本权重是否增大
misclassified = (h != y)
correct = (h == y)
print(f"错误分类样本的平均权重变化: {np.mean(D_new[misclassified] / D[misclassified]):.4f}")
print(f"正确分类样本的平均权重变化: {np.mean(D_new[correct] / D[correct]):.4f}")
# 错误分类的权重变化 > 1,正确分类的权重变化 < 1
verify_weight_update()

4.3 指数损失与0-1损失的一致性

考虑期望指数损失 E[eyH(x)]\mathbb{E}[e^{-y H(x)}],对其关于 H(x)H(x) 求偏导:

HE[eyH(x)]=E[yeyH(x)]=0\frac{\partial}{\partial H} \mathbb{E}[e^{-y H(x)}] = \mathbb{E}[-y e^{-y H(x)}] = 0

展开期望公式得:

P(y=1)eHP(y=1)eH=0P(y=1) \cdot e^{-H} - P(y=-1) \cdot e^{H} = 0

整理得:

P(y=1)P(y=1)=e2H两边取自然对数H(x)=12lnP(y=1)P(y=1)\frac{P(y=1)}{P(y=-1)} = e^{2H} \quad \xrightarrow{\text{两边取自然对数}} \quad H(x) = \frac{1}{2} \ln \frac{P(y=1)}{P(y=-1)}

因此:

sign(H(x))={+1,P(y=1)>P(y=1)1,P(y=1)<P(y=1)\text{sign}(H(x)) = \begin{cases} +1, & P(y=1) > P(y=-1) \\ -1, & P(y=1) < P(y=-1) \end{cases}

这意味着:最小化指数损失得到的分类器,恰好是贝叶斯最优分类器。指数损失是0-1损失的一个一致的替代损失函数(Surrogate Loss Function)


五、AdaBoost与GBM的底层联系

5.1 GBM是AdaBoost的泛化

在后续文章中,我们会详细讨论了梯度提升机(GBM) 。GBM的核心思想是每一轮用基学习器去拟合损失函数的负梯度

AdaBoost和GBM之间有着深刻的联系 —— AdaBoost可以被视为GBM在“指数损失函数 + 特定的坐标下降优化”下的一个特例。更准确地说,如果GBM选择了指数损失函数 L(y,f(x))=eyf(x)L(y, f(x)) = e^{-y f(x)},那么GBM就退化成了AdaBoost算法。

这个联系可以从两个角度理解:

  • 角度一:损失函数。GBM允许使用任意可微的损失函数,而AdaBoost固定使用指数损失函数。从这个意义上说,GBM是AdaBoost在损失函数维度上的泛化——它把AdaBoost的指数损失替换成了任意可微损失

  • 角度二:优化算法。AdaBoost使用前向分步加法模型(每一步解析地求解最优αt\alpha_thth_t),而GBM使用函数空间中的梯度下降(每一步用基学习器拟合负梯度)。从这个意义上说,GBM是AdaBoost在优化算法维度上的泛化——它把解析求解替换成了梯度下降

5.2 指数损失的优缺点

优点

  • 数学性质好,推导简洁
  • 0-1损失一致
  • 天然导出AdaBoost的权重更新公式

缺点

  • 对异常点非常敏感。指数损失对大误差的惩罚是指数级的——如果一个样本被严重分错(yH(x)y H(x) 是一个很大的负数),它的损失会爆炸式增长
  • 这也是为什么AdaBoost在噪声较多的数据集上表现可能不如GBM。

5.3 从AdaBoost到GBM:一条清晰的脉络

我们可以把从AdaBoost到GBM的演进看作一条清晰的脉络:

阶段算法损失函数优化方法
第一阶段AdaBoost指数损失前向分步(解析求解)
第二阶段GBM任意可微损失函数空间梯度下降

AdaBoost 证明了“串行纠错”这个思路是有效的,并用指数损失给出了一个优雅的数学框架。

GBM 则把这个框架泛化了 —— 把“指数损失”换成“任意可微损失”,把“解析求解”换成“梯度下降”,从而把AdaBoost从一个具体的算法变成了一个通用的算法框架


六、完整代码实现

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.tree import DecisionTreeClassifier
class AdaBoost:
"""完整的AdaBoost实现(含训练过程记录)"""
def __init__(self, n_estimators=50):
self.n_estimators = n_estimators
self.alphas = []
self.weak_classifiers = []
self.training_errors = []
self.epsilon_history = []
def fit(self, X, y):
n_samples = X.shape[0]
D = np.ones(n_samples) / n_samples
for t in range(self.n_estimators):
# 训练弱分类器
weak_clf = DecisionTreeClassifier(max_depth=1)
weak_clf.fit(X, y, sample_weight=D)
predictions = weak_clf.predict(X)
# 计算加权错误率
misclassified = (predictions != y)
epsilon = np.sum(D * misclassified)
if epsilon == 0:
epsilon = 1e-10
if epsilon == 1:
epsilon = 1 - 1e-10
# 计算弱分类器权重
alpha = 0.5 * np.log((1 - epsilon) / epsilon)
# 更新样本权重
D = D * np.exp(-alpha * y * predictions)
D = D / np.sum(D)
# 记录历史
self.alphas.append(alpha)
self.weak_classifiers.append(weak_clf)
self.epsilon_history.append(epsilon)
# 计算当前集成的训练误差
train_pred = self.predict(X)
self.training_errors.append(np.mean(train_pred != y))
return self
def predict(self, X):
weighted_sum = np.zeros(X.shape[0])
for alpha, clf in zip(self.alphas, self.weak_classifiers):
weighted_sum += alpha * clf.predict(X)
return np.sign(weighted_sum)
# ============ 生成数据并训练 ============
np.random.seed(42)
X, y = make_classification(
n_samples=500, n_features=2, n_informative=2, n_redundant=0,
n_clusters_per_class=1, random_state=42
)
y = np.where(y == 0, -1, 1) # 转换为 {-1, +1}
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
# 训练AdaBoost
adaboost = AdaBoost(n_estimators=100)
adaboost.fit(X_train, y_train)
# 评估
train_acc = accuracy_score(y_train, adaboost.predict(X_train))
test_acc = accuracy_score(y_test, adaboost.predict(X_test))
print(f"训练集准确率: {train_acc:.4f}")
print(f"测试集准确率: {test_acc:.4f}")
# ============ 可视化:训练过程 ============
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
# 1. 弱分类器权重 α_t 的变化
axes[0].plot(adaboost.alphas, 'b-')
axes[0].set_xlabel('迭代轮次 t')
axes[0].set_ylabel('弱分类器权重 α_t')
axes[0].set_title('弱分类器权重的变化')
axes[0].grid(True)
# 2. 加权错误率 ε_t 的变化
axes[1].plot(adaboost.epsilon_history, 'r-')
axes[1].set_xlabel('迭代轮次 t')
axes[1].set_ylabel('加权错误率 ε_t')
axes[1].set_title('加权错误率的变化')
axes[1].axhline(y=0.5, color='gray', linestyle='--', label='随机猜测 (0.5)')
axes[1].legend()
axes[1].grid(True)
# 3. 训练误差的下降
axes[2].plot(adaboost.training_errors, 'g-')
axes[2].set_xlabel('迭代轮次 t')
axes[2].set_ylabel('训练集错误率')
axes[2].set_title('训练误差的下降')
axes[2].grid(True)
plt.tight_layout()
plt.show()
# ============ 可视化:决策边界 ============
def plot_decision_boundary(X, y, model, title):
x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.figure(figsize=(8, 6))
plt.contourf(xx, yy, Z, alpha=0.4, cmap='RdBu')
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='RdBu', edgecolors='k', s=50)
plt.xlabel('特征1')
plt.ylabel('特征2')
plt.title(title)
plt.show()
# 对比:单个弱分类器 vs AdaBoost集成
first_clf = adaboost.weak_classifiers[0]
plot_decision_boundary(X_train, y_train, first_clf,
f'第1个弱分类器的决策边界 (准确率: {accuracy_score(y_train, first_clf.predict(X_train)):.3f})')
plot_decision_boundary(X_train, y_train, adaboost,
f'AdaBoost集成的决策边界 (准确率: {accuracy_score(y_train, adaboost.predict(X_train)):.3f})')

总结
概念核心内容
Boosting思想串行训练,后一个模型修正前一个模型的错误
错题本机制被分错的样本权重增大,被分对的样本权重减小
加法模型H(x)=αtht(x)H(x) = \sum \alpha_t h_t(x)基学习器的线性组合
前向分步算法每一步只优化当前一个基分类器,固定之前的结果
指数损失L(y,H)=eyHL(y, H) = e^{-yH},AdaBoost的优化目标
弱分类器权重αt=12ln1ϵtϵt\alpha_t = \frac{1}{2}\ln\frac{1-\epsilon_t}{\epsilon_t}
样本权重更新Dt+1(i)Dt(i)exp(αtyiht(xi))D_{t+1}(i) \propto D_t(i) \cdot \exp(-\alpha_t y_i h_t(x_i))
AdaBoost与GBMAdaBoost是GBM在指数损失下的特例

核心要点回顾

  1. AdaBoost的核心思想是“错题本”:每一轮训练后,提高被分错样本的权重,降低被分对样本的权重,让下一个弱分类器重点关注上一轮的错误。
  2. AdaBoost是前向分步加法模型的特例:模型是基学习器的线性组合(加法模型),学习策略是每一步只优化当前一个基学习器(前向分步),损失函数是指数损失
  3. 指数损失函数 L(y,H)=eyHL(y, H) = e^{-yH} 是AdaBoost的数学核心。它有两个关键性质:连续可微便于优化,且与0-1损失一致(最小化指数损失等价于最小化分类错误率)。
  4. 两个权重的推导
    • 弱分类器权重 αt=12ln1ϵtϵt\alpha_t = \frac{1}{2}\ln\frac{1-\epsilon_t}{\epsilon_t}错误率越低权重越大
    • 样本权重更新 Dt+1(i)Dt(i)exp(αtyiht(xi))D_{t+1}(i) \propto D_t(i) \cdot \exp(-\alpha_t y_i h_t(x_i))被分错的样本权重增大
  5. AdaBoost与GBM的底层联系:AdaBoost是GBM在指数损失函数下的特例。GBM将AdaBoost的“指数损失”泛化为“任意可微损失”,将“解析求解”泛化为“函数空间梯度下降”。
分享:

学习路径

按顺序完成这组文章,循序渐进地掌握主题

学习进度9 / 15
  1. 1Linear Regression —— 线性回归
  2. 2Logistic Regression —— 逻辑回归与Softmax多分类
  3. 3K-Nearest Neighbor (KNN) —— K-近邻
  4. 4Naive Bayes —— 朴素贝叶斯
  5. 5Support Vector Machine (SVM) —— 支持向量机
  6. 6Kernel Trick —— 核技巧与常用核函数
  7. 7Decision Tree —— 决策树
  8. 8Bagging & Random Forest —— 随机森林
  9. 9Adaptive Boosting (AdaBoost) —— 自适应提升
  10. 10Gradient Boosting Machine (GBM) —— 梯度提升机与加法模型
  11. 11XGBoost & LightGBM —— 梯度提升框架
  12. 12Principal Component Analysis (PCA) —— 主成分分析
  13. 13K-Means Clustering —— 聚类算法
  14. 14Expectation-Maximization Algorithm —— EM算法
  15. 15Hidden Markov Model (HMM) —— 隐马尔可夫模型