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]]}")
\text{AdaBoost 权重更新公式}\(\alpha_t = \frac{1}{2} \ln\left(\frac{1 - \epsilon_t}{\epsilon_t}\right), \quad w_i^{(t+1)} = \frac{w_i^{(t)} \exp(-\alpha_t y_i h_t(x_i))}{Z_t}\)
大白话 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("最终模型 = 所有砖块的加权和")
\text{指数损失下的贝叶斯最优解}\(F^*(x) = \frac{1}{2} \ln\frac{P(y=1|x)}{P(y=-1|x)} \quad \Rightarrow \quad \text{sign}(F^*(x)) = \text{sign}\left(\ln\frac{P(y=1|x)}{P(y=-1|x)}\right)\)
大白话 指数损失函数就像是一个「严苛的考官」——对错题罚得特别重(损失约 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 方法(并行训练,降低方差)。两者都可做分类和回归。