AdaBoost:自适应提升算法
一句话概述
AdaBoost(Adaptive Boosting)是 Freund 和 Schapire 于 1995 年提出的第一个实用的 Boosting 算法,它的核心思想是:串行训练多个弱分类器,每一轮根据上一轮的表现自适应地调整样本权重——增大错分样本的权重,减小正确分类样本的权重——使后续分类器更关注之前难以分类的样本。最终将所有分类器加权组合,权重由各分类器的错误率决定。AdaBoost 理论优雅且效果惊人,曾被誉为「最佳开箱即用分类器」。
💡 核心要点:① AdaBoost 通过指数损失函数和前向分步加法模型实现自适应提升 ② 样本权重更新和分类器权重 α 都来自指数损失最小化的推导 ③ 只要基分类器比随机猜测略好(准确率 > 50%),AdaBoost 就能将其提升为强分类器 ④ AdaBoost 对异常值和噪声敏感,因为错分样本权重会不断增大
教学与演示
一、AdaBoost 的算法原理
是什么:AdaBoost(Adaptive Boosting 的缩写)是一种迭代式的集成学习算法。它维护一组样本权重,初始时所有样本权重相等。在每一轮迭代中:① 基于当前样本权重训练一个弱分类器,② 计算该分类器的加权错误率,③ 根据错误率计算分类器权重 α(错误率越低,α 越大),④ 更新样本权重(错分样本权重增大,正确样本权重减小),⑤ 归一化样本权重。最终预测时,所有分类器进行加权投票。
大白话 AdaBoost 就像一个严格的老师:每次考试后,把做错的题目标记为重点,下次考试这些题目占分更重。同时,老师还会看每个学生的水平——学得好的学生(分类器准确率高)发言权更大,学得差的学生发言权小。
为什么:AdaBoost 的数学基础是指数损失函数(Exponential Loss)下的前向分步加法模型。可以证明,AdaBoost 的每一步实际上是在最小化指数损失:L(y, F(x)) = exp(−y·F(x))。其中 F(x) 是加法模型,每一步新增的基分类器 h_m(x) 和权重 α_m 都是通过最小化指数损失得到的。这个框架保证了算法的收敛性和理论优良性。
怎么做:
import numpy as np
# ========== 从零实现 AdaBoost 二分类算法 ==========
np.random.seed(42)
class AdaBoostClassifier:
"""
AdaBoost 二分类器实现
基分类器使用决策树桩(单层决策树)
"""
def __init__(self, n_estimators=50):
self.n_estimators = n_estimators # 弱分类器数量(迭代轮数)
self.alphas = [] # 每个分类器的权重系数
self.stumps = [] # 每个决策树桩的参数
def _stump_predict(self, X, feat_idx, thresh, polarity):
"""决策树桩的预测函数"""
n_samples = X.shape[0]
pred = np.ones(n_samples) # 初始预测全为 1
# polarity=1: 小于阈值的预测为 -1;polarity=-1: 小于阈值的预测为 1
if polarity == 1:
pred[X[:, feat_idx] <= thresh] = -1
else:
pred[X[:, feat_idx] > thresh] = -1
return pred # 返回 {-1, 1} 的预测值
def _build_stump(self, X, y, sample_weights):
"""
在加权数据上训练最优决策树桩
返回: (最佳特征索引, 最佳阈值, 极性, 最小错误率)
"""
n_samples, n_features = X.shape
best_stump = {}
min_error = float('inf')
for feat_idx in range(n_features):
# 生成候选阈值:取该特征值范围内的等分点
feat_values = X[:, feat_idx]
thresholds = np.linspace(feat_values.min(), feat_values.max(), 30)
for thresh in thresholds:
for polarity in [1, -1]:
# 在当前参数下预测
pred = self._stump_predict(X, feat_idx, thresh, polarity)
# 计算加权错误率(y 和 pred 都在 {-1, 1} 范围内)
error = np.sum(sample_weights[y != pred])
if error < min_error:
min_error = error
best_stump = {
'feature': feat_idx,
'threshold': thresh,
'polarity': polarity
}
return best_stump, min_error
def fit(self, X, y):
"""
训练 AdaBoost 模型
X: (n_samples, n_features) 特征矩阵
y: (n_samples,) 标签,值域为 {0, 1} 或 {-1, 1}
"""
n_samples = X.shape[0]
# 将标签转换为 {-1, 1} 格式,便于 AdaBoost 公式计算
y_signed = np.where(y == 0, -1, 1) # 将 {0,1} 映射为 {-1,1}
# 初始化样本权重:每个样本权重相等
sample_weights = np.ones(n_samples) / n_samples
self.alphas = []
self.stumps = []
for t in range(self.n_estimators):
# 1. 训练当前最优决策树桩
stump, error = self._build_stump(X, y_signed, sample_weights)
# 防止错误率为 0 导致除零
error = max(error, 1e-10)
# 2. 计算当前分类器的权重 α
# α = 0.5 * ln((1 - error) / error)
# 错误率越低,α 越大;错误率 > 0.5 时 α < 0
alpha = 0.5 * np.log((1 - error) / error)
self.alphas.append(alpha)
self.stumps.append(stump)
# 3. 获取当前分类器的预测
pred = self._stump_predict(X, stump['feature'],
stump['threshold'], stump['polarity'])
# 4. 更新样本权重
# w_i ← w_i * exp(-α * y_i * h_t(x_i))
# 正确分类: y_i * h_t(x_i) = 1, 权重乘以 exp(-α) < 1 (减小)
# 错误分类: y_i * h_t(x_i) = -1, 权重乘以 exp(α) > 1 (增大)
sample_weights *= np.exp(-alpha * y_signed * pred)
# 归一化:使权重和为 1
sample_weights /= np.sum(sample_weights)
return self
def predict(self, X):
"""
预测:加权投票
所有分类器的加权和 > 0 → 预测类别 1
所有分类器的加权和 ≤ 0 → 预测类别 0
"""
n_samples = X.shape[0]
# 累加所有分类器的加权预测
final_score = np.zeros(n_samples)
for alpha, stump in zip(self.alphas, self.stumps):
pred = self._stump_predict(X, stump['feature'],
stump['threshold'], stump['polarity'])
final_score += alpha * pred # α 就是分类器的投票权重
# 将加权和转换为 {0, 1} 标签
return np.where(final_score > 0, 1, 0)
# ========== 演示 AdaBoost 在合成数据上的表现 ==========
# 生成两类数据:同心圆模式(线性不可分)
def generate_circle_data(n_points=200):
"""生成同心圆二分类数据:内圆为类别0,外环为类别1"""
np.random.seed(0)
# 类别0:内圆(半径 0~3)
r0 = np.random.uniform(0, 3, n_points // 2)
theta0 = np.random.uniform(0, 2 * np.pi, n_points // 2)
X0 = np.column_stack([r0 * np.cos(theta0), r0 * np.sin(theta0)])
y0 = np.zeros(n_points // 2)
# 类别1:外环(半径 4~7)
r1 = np.random.uniform(4, 7, n_points // 2)
theta1 = np.random.uniform(0, 2 * np.pi, n_points // 2)
X1 = np.column_stack([r1 * np.cos(theta1), r1 * np.sin(theta1)])
y1 = np.ones(n_points // 2)
X = np.vstack([X0, X1])
y = np.hstack([y0, y1])
return X, y
X, y = generate_circle_data(200)
# 训练 AdaBoost
ada = AdaBoostClassifier(n_estimators=50)
ada.fit(X, y)
pred = ada.predict(X)
accuracy = np.mean(pred == y)
print(f"AdaBoost 训练准确率: {accuracy:.2%}")
print(f"使用 {ada.n_estimators} 个决策树桩")
print(f"前5个分类器权重 α: {[f'{a:.3f}' for a in ada.alphas[:5]]}")
大白话 AdaBoost 有两套权重:一套是样本权重(决定每个样本的重要性),另一套是分类器权重(决定每个分类器的话语权)。错误率低的分类器话语权大,被它分错的样本下次会受到更多关注。
什么用:AdaBoost 在人脸检测领域有里程碑式的应用——Viola-Jones 人脸检测算法(2001 年)使用 AdaBoost 从数万个 Haar-like 特征中选出最有效的几百个,实现了实时人脸检测。在信用评分、客户流失预测等二分类任务中,AdaBoost 也常作为基线模型。
哪些坑:AdaBoost 对噪声和异常值非常敏感——因为噪声样本往往难以分类,其权重会不断增大,最终模型会过度关注这些噪声而偏离真实模式。迭代次数过多会导致过拟合。此外,AdaBoost 默认使用指数损失,对标签错误的样本惩罚极重。
二、指数损失函数与前向分步加法模型
是什么:从数学角度看,AdaBoost 等价于在指数损失函数 L(y, F(x)) = exp(−y·F(x)) 下,使用前向分步加法模型(Forward Stagewise Additive Modeling)进行优化。每一步固定前面的模型,只优化当前步新增的分类器及其权重。
大白话 AdaBoost 看似是一个简单的权重更新技巧,但背后有严格的数学推导。可以证明,AdaBoost 的每一步都在做同一件事:找到一个新分类器,使整体模型的指数损失函数下降最多。
为什么:指数损失函数的一个重要性质是:当模型 F(x) 使指数损失最小化时,sign(F(x)) 近似于贝叶斯最优分类器。具体来说,最小化指数损失得到的模型满足:F*(x) = ½ ln(P(y=1|x)/P(y=−1|x)),这恰好是 log-odds 的一半。因此,AdaBoost 本质上是在逼近后验概率。
怎么做:
import numpy as np
# ========== 演示指数损失函数与 AdaBoost 的等价性 ==========
def exponential_loss_demo():
"""演示指数损失函数如何驱动 AdaBoost 的权重更新"""
print("=== 指数损失函数与 AdaBoost ===")
# 模拟几个样本的预测情况
y_true = np.array([1, 1, -1, -1, 1, -1]) # 真实标签 {-1, 1}
y_pred = np.array([1, -1, -1, 1, 1, -1]) # 当前模型预测
# 计算每个样本的指数损失: exp(-y * f(x))
# 正确分类: y*f(x)=1, loss=exp(-1)≈0.368
# 错误分类: y*f(x)=-1, loss=exp(1)≈2.718
losses = np.exp(-y_true * y_pred)
print("样本真实标签:", y_true)
print("模型预测值: ", y_pred)
print("是否正确: ", y_true == y_pred)
print("指数损失: ", [f"{l:.3f}" for l in losses])
print(f"平均指数损失: {losses.mean():.3f}")
print()
print("关键观察:")
print(" - 正确分类的样本损失 ≈ 0.368(较小)")
print(" - 错误分类的样本损失 ≈ 2.718(大得多,约7.4倍)")
print(" - 指数损失对错误分类的惩罚远大于正确分类")
# 证明 AdaBoost 权重更新等价于指数损失下的优化
print("\n=== AdaBoost 权重更新与指数损失的等价性 ===")
# 假设当前模型 F(x) = α * h(x)
alpha = 0.5 # 分类器权重
h_pred = np.array([1, -1, -1, -1, 1, 1]) # 新分类器预测
# 当前指数损失
current_loss = np.mean(np.exp(-y_true * (alpha * h_pred)))
print(f"当前指数损失: {current_loss:.3f}")
# 当 α 使损失最小时,求导得到 α* = 0.5 * ln((1-ε)/ε)
# 其中 ε 是加权错误率
weighted_errors = np.where(y_true != h_pred, 1, 0) # 简化:均匀权重
epsilon = weighted_errors.mean()
optimal_alpha = 0.5 * np.log((1 - epsilon) / epsilon)
print(f"加权错误率 ε: {epsilon:.3f}")
print(f"最优 α*: {optimal_alpha:.3f}")
print(f"这与 AdaBoost 中 α=0.5*ln((1-ε)/ε) 完全一致!")
exponential_loss_demo()
# ========== 前向分步加法模型的直观理解 ==========
print("\n=== 前向分步加法模型 ===")
print("加法模型形式: F_m(x) = F_{m-1}(x) + α_m · h_m(x)")
print("前向分步: 每一步只优化 α_m 和 h_m(x),固定之前的 F_{m-1}(x)")
print("这就像建造一堵墙——每次只加一块砖,前面的砖不动")
print("最终模型 = 所有砖块的加权和")
大白话 指数损失函数就像是一个「严苛的考官」——对错题罚得特别重(损失约 2.7),对做对的题也罚但轻得多(损失约 0.37)。这种不对称的惩罚迫使模型必须把每一道题都做对,不能有短板。
三、AdaBoost 的样本权重演化
是什么:AdaBoost 的样本权重是一个动态演化的过程。初始时所有样本权重相等(1/n),每轮迭代后,错分样本的权重增大,正确样本的权重减小。经过多轮迭代,样本权重呈现出「难分样本权重高、易分样本权重低」的分布。
大白话 你可以把样本权重想象成每个样本的「音量」——初始时大家音量一样大,但每轮过后,模型搞不定的样本音量被调大,已经能搞定的样本音量被调小。这样下一轮模型就会「听到」更多难样本的声音,从而更关注它们。
为什么:样本权重的演化反映了 AdaBoost 对数据集中「困难区域」的逐步聚焦。这种机制使得 AdaBoost 能够自适应地分配计算资源——将更多注意力放在分类边界附近的样本上。但这也是一把双刃剑:如果某个样本是标签错误(噪声),其权重也会不断增大,导致模型最终被噪声「绑架」。
怎么做:
import numpy as np
# ========== 演示 AdaBoost 样本权重的演化过程 ==========
np.random.seed(42)
def sample_weight_evolution_demo():
"""追踪 AdaBoost 迭代中样本权重的变化"""
n_samples = 10
n_estimators = 20
# 生成简单数据
X = np.random.randn(n_samples, 2)
# 故意添加一个噪声样本(标签与特征矛盾)
y_true = np.array([1, 1, 1, 1, 1, -1, -1, -1, -1, -1])
# 但把第5个样本(类别1)故意放在类别-1 的区域附近
X[4] = np.array([-2, -2]) # 这个样本会成为「难样本」
# 模拟 AdaBoost 的权重演化
y_signed = y_true # 已经是 {-1, 1}
w = np.ones(n_samples) / n_samples # 初始权重
print("=== AdaBoost 样本权重演化 ===")
print(f"初始权重(均匀分布): {np.array2string(w, precision=3)}")
print(f"\n样本标签: {y_true}")
print(f"样本5是故意制造的难样本(标签1但位置在-1类区域)\n")
# 模拟多轮迭代
for t in range(1, n_estimators + 1):
# 模拟:一个简单的决策树桩总是按特征0的符号来预测
pred = np.where(X[:, 0] > 0, 1, -1)
# 样本5(X[4,0]=-2)会被预测为-1,但真实标签是1 → 总是错
# 计算加权错误率
error = np.sum(w[y_signed != pred])
error = max(error, 1e-10)
# 计算 alpha
alpha = 0.5 * np.log((1 - error) / error)
# 更新权重
w *= np.exp(-alpha * y_signed * pred)
w /= w.sum()
if t in [1, 5, 10, 20]:
print(f"第{t:2d}轮: 样本5权重={w[4]:.4f} (其他样本均值={w[[0,1,2,3,5,6,7,8,9]].mean():.4f})")
print(f"\n最终权重分布: {np.array2string(w, precision=3)}")
print(f"样本5的最终权重: {w[4]:.4f} (初始为 {1/n_samples:.4f})")
print(f"样本5权重放大倍数: {w[4] / (1/n_samples):.1f}倍")
print(f"\n这说明了为什么 AdaBoost 对噪声敏感——")
print(f"如果样本5是标签噪声,模型会过度关注它而降低整体性能")
sample_weight_evolution_demo()
大白话 样本权重就像「聚光灯」——AdaBoost 不断把灯光照向那些模型总是搞错的样本。但如果某个样本本身就是错的(标签标错了),灯光照得越亮,模型反而被带偏得越远。这就是为什么 AdaBoost 怕噪声数据。
什么用:样本权重的演化信息可用于数据清洗——迭代后期权重异常高的样本很可能是标签错误或异常值,可以被标记出来人工审核。此外,样本权重也可用于理解模型的「难度」分布,帮助识别数据集中哪些区域需要更多训练样本。
哪些坑:当数据集中存在较多噪声时,AdaBoost 的样本权重会集中在少数噪声样本上,导致模型严重过拟合。建议在噪声较大的数据上使用 AdaBoost 的变体(如 Gentle AdaBoost 或 LogitBoost),它们对噪声更鲁棒。
四、AdaBoost 的变体与改进
是什么:AdaBoost 有多种变体,主要包括:SAMME(Stagewise Additive Modeling using a Multi-class Exponential loss function,用于多分类)、Gentle AdaBoost(使用更温和的权重更新,对噪声更鲁棒)、Real AdaBoost(输出概率而非离散标签)和 LogitBoost(使用对数损失代替指数损失)。
大白话 原始的 AdaBoost 就像一把「锋利的刀」——切得准但容易切到手。后来的变体给它加了「保护套」,让它在嘈杂数据中也能稳定工作。
为什么:AdaBoost 的指数损失函数增长极快(exp(−y·F(x))),这使得它对标签错误的样本惩罚过重。Gentle AdaBoost 通过牛顿步而非指数损失来更新,Real AdaBoost 输出类别概率而非离散标签,都使算法对噪声更鲁棒。SAMME 将 AdaBoost 推广到多分类,通过修改 α 的计算公式实现多类自适应提升。
怎么做:
import numpy as np
# ========== SAMME:多分类 AdaBoost 的核心公式 ==========
def samme_alpha_demo():
"""演示 SAMME 多分类 AdaBoost 的 α 计算公式"""
print("=== SAMME 多分类 AdaBoost ===")
print("原始 AdaBoost (二分类) α = 0.5 * ln((1-ε)/ε)")
print("SAMME (多分类) α = ln((1-ε)/ε) + ln(K-1)")
print("其中 K 是类别数")
print()
for K in [2, 3, 5, 10]:
print(f"类别数 K={K}:")
for epsilon in [0.1, 0.3, 0.5]:
# 原始 AdaBoost 的 α
alpha_binary = 0.5 * np.log((1 - epsilon) / epsilon)
# SAMME 的 α
alpha_samme = np.log((1 - epsilon) / epsilon) + np.log(K - 1)
print(f" ε={epsilon:.1f}: α_binary={alpha_binary:.3f}, α_samme={alpha_samme:.3f}")
print()
print("关键观察:")
print(" - 当 K=2 时,ln(K-1)=ln(1)=0,SAMME 退化回原始 AdaBoost 的 2 倍")
print(" - 当 K>2 时,SAMME 要求基分类器准确率 > 1/K(而非 1/2)")
print(" - 这保证了多分类场景下基分类器仍然优于随机猜测")
samme_alpha_demo()
# ========== Gentle AdaBoost 的核心思想 ==========
print("\n=== Gentle AdaBoost 与原始 AdaBoost 的对比 ===")
print("原始 AdaBoost 权重更新: w_i *= exp(-α * y_i * h(x_i))")
print("Gentle AdaBoost 权重更新: w_i *= exp(-y_i * h(x_i))")
print()
print("区别:")
print(" - Gentle AdaBoost 不使用 α 系数,直接用 h(x_i) 更新")
print(" - h(x_i) 是概率输出(连续值)而非离散值")
print(" - 权重更新更「温和」——极端情况更少")
print(" - 对噪声数据的鲁棒性更好")
print()
print("选择建议:")
print(" - 数据干净 → 原始 AdaBoost(更快收敛)")
print(" - 数据有噪声 → Gentle AdaBoost(更鲁棒)")
print(" - 多分类任务 → SAMME 或 SAMME.R")
大白话 AdaBoost 的演进就像手机从「功能机」到「智能机」——原始版本功能强大但容错性差,后来的变体越来越「聪明」,能处理更复杂的情况(多分类、噪声数据等),但核心思想始终没变:让后面的模型去弥补前面的不足。
概念关系图谱
| 概念 | 说明 | 与 AdaBoost 的关系 |
|---|---|---|
| 指数损失函数 | L = exp(−y·F(x)) | AdaBoost 在此损失下做前向分步优化 |
| 决策树桩 | 单层决策树 | AdaBoost 最常用的基分类器 |
| 样本权重 | 每个样本的重要性 | 驱动 AdaBoost 自适应聚焦 |
| 分类器权重 α | 每个分类器的话语权 | 由分类器错误率决定 |
| SAMME | 多分类 AdaBoost | 修改 α 公式以适应多类 |
| Gentle AdaBoost | 温和版 AdaBoost | 对噪声数据更鲁棒 |
重点答疑
Q1: AdaBoost 为什么要求基分类器准确率 > 50%?
因为 α = 0.5·ln((1−ε)/ε),当 ε > 0.5 时,α < 0,意味着这个分类器比随机猜测还差,其「投票」权重为负——相当于「反向预测」。虽然 AdaBoost 理论上可以处理 α < 0 的情况,但实践中通常要求 ε < 0.5。如果某个基分类器不满足此条件,可以简单地将它的预测取反(即交换标签)。
Q2: AdaBoost 的迭代次数(n_estimators)如何选择?
没有固定答案,但可以通过交叉验证选择。AdaBoost 的泛化误差理论上有上界,不会随迭代次数无限增长。但实践中,使用过于复杂的基分类器(如深决策树)时,AdaBoost 仍可能过拟合。建议:① 使用浅决策树(如 max_depth=1 或 2)作为基分类器,② 通过交叉验证选择 n_estimators,③ 观察训练误差和学习曲线,当验证误差开始上升时停止。
Q3: AdaBoost 和 Gradient Boosting 有什么关系?
两者都是 Boosting 方法,但优化方式不同:AdaBoost 通过指数损失函数和样本权重更新实现,每一步找到最优的基分类器和权重;Gradient Boosting 通过梯度下降思想,每一步拟合损失函数的负梯度(残差)。可以证明,当使用指数损失时,Gradient Boosting 等价于 AdaBoost。Gradient Boosting 更通用,可以使用任意可微损失函数(如平方损失、对数损失等)。
章节单词汇总
| 英文 | 音标 | 术语/释义 |
|---|---|---|
| AdaBoost | /ˈeɪdəbuːst/ | Adaptive Boosting;自适应提升算法 |
| Decision Stump | /dɪˈsɪʒən stʌmp/ | 决策树桩;仅有一个分裂节点的决策树 |
| Exponential Loss | /ˌekspəˈnenʃəl lɔːs/ | 指数损失;对错误分类惩罚极重的损失函数 |
| Forward Stagewise | /ˈfɔːrwərd ˈsteɪdʒwaɪz/ | 前向分步;每一步只优化当前新增的模型 |
| Sample Weight | /ˈsæmpəl weɪt/ | 样本权重;每个样本在训练中的重要性 |
| Alpha (α) | /ˈælfə/ | 分类器权重;由分类器错误率决定 |
| SAMME | /ˈsæmi/ | 多分类 AdaBoost 算法 |
| Gentle AdaBoost | /ˈdʒentəl ˈeɪdəbuːst/ | 温和版 AdaBoost;对噪声更鲁棒 |
面试练习
Q1 [单选] AdaBoost 中,分类器权重 α 的计算公式是什么?
- A. α = (1−ε) / ε
- B. α = 0.5 × ln((1−ε) / ε)
- C. α = ε / (1−ε)
- D. α = ln(ε / (1−ε))
解答:AdaBoost 的分类器权重 α = 0.5 × ln((1−ε) / ε),其中 ε 是加权错误率。错误率越低,α 越大,该分类器在最终投票中的权重越大。
Q2 [单选] AdaBoost 使用什么损失函数?
- A. 平方损失(MSE)
- B. 对数损失(Log Loss)
- C. 指数损失(Exponential Loss)
- D. Hinge 损失
解答:AdaBoost 等价于在指数损失 L=exp(−y·F(x)) 下进行前向分步加法模型优化。指数损失对错误分类的惩罚远大于正确分类,驱动模型关注错分样本。
Q3 [多选] 以下关于 AdaBoost 的说法,哪些是正确的?
- A. 基分类器是串行训练的,后一个依赖前一个的结果
- B. 错分样本的权重在下一轮会增大
- C. 所有基分类器的权重是相等的
- D. 最终预测是加权投票
解答:AdaBoost 的基分类器串行训练,错分样本权重增大,最终预测是各分类器的加权投票(权重 α 由错误率决定,并非相等)。
Q4 [单选] 当 AdaBoost 中某个基分类器的错误率 ε = 0.5 时,其权重 α 是多少?
- A. 1
- B. 0.5
- C. 0
- D. −1
解答:α = 0.5 × ln((1−0.5)/0.5) = 0.5 × ln(1) = 0。当 ε = 0.5 时,分类器与随机猜测无异,权重为 0,即不参与投票。
Q5 [单选] AdaBoost 对以下哪种数据最敏感?
- A. 缺失值多的数据
- B. 标签噪声(错误标签)多的数据
- C. 特征维度高的数据
- D. 样本量大的数据
解答:AdaBoost 对标签噪声极为敏感,因为噪声样本往往难以分类,其权重会不断增大,最终模型会过度关注噪声而偏离真实模式。
Q6 [多选] 以下哪些是 AdaBoost 的变体或改进?
- A. SAMME(多分类 AdaBoost)
- B. Gentle AdaBoost
- C. Real AdaBoost
- D. AdaGrad
解答:SAMME、Gentle AdaBoost、Real AdaBoost 都是 AdaBoost 的变体。AdaGrad 是梯度下降优化器的一种,与 AdaBoost 无关。
Q7 [单选] SAMME 多分类 AdaBoost 中,α 的公式与二分类相比有什么变化?
- A. 完全相同
- B. 增加了 ln(K−1) 项,其中 K 是类别数
- C. 乘以了类别数 K
- D. 除以了类别数 K
解答:SAMME 的 α = ln((1−ε)/ε) + ln(K−1)。当 K=2 时,ln(K−1)=0,退化回原始 AdaBoost 的 2 倍。增加 ln(K−1) 确保了多分类场景下基分类器需要优于 1/K 的随机猜测水平。
Q8 [单选] AdaBoost 的样本权重在迭代过程中,错误样本的权重会如何变化?
- A. 保持不变
- B. 乘以 exp(α),即增大
- C. 乘以 exp(−α),即减小
- D. 被重置为 1/n
解答:错误样本的权重乘以 exp(α)(α > 0 时 exp(α) > 1,权重增大),正确样本的权重乘以 exp(−α)(小于 1,权重减小)。这使得后续分类器更关注难分类的样本。
Q9 [多选] 以下哪些方法可以缓解 AdaBoost 对噪声的敏感性?
- A. 使用 Gentle AdaBoost 代替原始 AdaBoost
- B. 限制迭代次数(早停)
- C. 在训练前进行数据清洗,检测并修正可能的标签错误
- D. 增加基分类器的复杂度(如使用深决策树)
解答:使用 Gentle AdaBoost、早停、数据清洗都可以缓解噪声敏感性。但增加基分类器复杂度反而可能加剧过拟合,因为复杂的基分类器更容易「记住」噪声模式。
Q10 [单选] AdaBoost 与随机森林(Random Forest)的主要区别是什么?
- A. 两者完全相同,只是名字不同
- B. AdaBoost 是串行 Boosting,随机森林是并行 Bagging
- C. AdaBoost 只能用于分类,随机森林可用于回归
- D. 随机森林使用样本权重,AdaBoost 不使用
解答:AdaBoost 是 Boosting 方法(串行训练,降低偏差),随机森林是 Bagging 方法(并行训练,降低方差)。两者都可做分类和回归。