AdaBoost算法之推导过程
1 课程概览
本课讲解AdaBoost算法的推导过程。通过具体案例演示如何计算错误率、模型权重和样本权重更新。重点理解切分点选择、错误率计算和权重更新公式。
2 核心概念与定义
- 错误率:预测错误样本数占总样本数的比例。
- 模型权重:弱学习器的权重,$\alpha = \frac{1}{2}\ln\frac{1-\epsilon}{\epsilon}$。
- 样本权重:每个样本的权重,预测对降低,预测错提升。
- 归一化:所有样本权重之和为1。
- 切分点:特征值的中位数。
3 算法与模型详解
3.1 推导准备
数据:10个样本
约定:
- 左边:正样本,用1表示
- 右边:负样本,用-1表示
切分点:
- 序号0和1之间:0.5
- 序号1和2之间:1.5
- 以此类推
3.2 错误率计算
规则:在切分点划分,计算错误样本数
示例:在0.5切分
- 左边:1个样本(正样本,预测对)
- 右边:9个样本(应该是负样本,但有5个正样本错了)
- 错误率:5/10 = 0.5
示例:在2.5切分
- 左边:3个样本(都是正样本,预测对)
- 右边:7个样本(应该是负样本,但有3个正样本错了)
- 错误率:3/10 = 0.3
选择:错误率最小的切分点
3.3 模型权重计算
公式: $$\alpha_t = \frac{1}{2} \ln \frac{1 - \epsilon_t}{\epsilon_t}$$
其中:
- $\alpha_t$:第t个弱学习器的权重
- $\epsilon_t$:错误率
示例:错误率$\epsilon = 0.3$ $$\alpha = \frac{1}{2} \ln \frac{1 - 0.3}{0.3} = \frac{1}{2} \ln \frac{0.7}{0.3} = \frac{1}{2} \ln 2.33 \approx 0.42$$
3.4 样本权重更新
预测正确: $$w_i^{(t+1)} = w_i^{(t)} \cdot e^{-\alpha_t}$$
权重降低($e^{-\alpha_t} < 1$)
预测错误: $$w_i^{(t+1)} = w_i^{(t)} \cdot e^{\alpha_t}$$
权重提升($e^{\alpha_t} > 1$)
3.5 归一化
公式: $$Z_t = \sum_{i=1}^{N} w_i^{(t+1)}$$
$$\hat{w}_i^{(t+1)} = \frac{w_i^{(t+1)}}{Z_t}$$
目的:保证所有样本权重之和为1
3.6 推导流程
- 初始化样本权重(均匀分布)
- 选择切分点,计算错误率
- 计算模型权重$\alpha$
- 更新样本权重
- 归一化
- 重复2-5,训练下一个弱学习器
- 加权组合所有弱学习器
4 数学原理与推导
4.1 模型权重
$$\alpha_t = \frac{1}{2} \ln \frac{1 - \epsilon_t}{\epsilon_t}$$
推导:
- 错误率$\epsilon_t$越小,$\alpha_t$越大
- 错误率$\epsilon_t$越大,$\alpha_t$越小
- $\epsilon_t = 0.5$时,$\alpha_t = 0$(无信息)
4.2 样本权重更新
$$w_i^{(t+1)} = \frac{w_i^{(t)}}{Z_t} \exp(-\alpha_t y_i h_t(x_i))$$
其中:
- $y_i$:真实标签(+1或-1)
- $h_t(x_i)$:预测标签(+1或-1)
- $y_i h_t(x_i)$:预测正确为+1,预测错误为-1
预测正确:$y_i h_t(x_i) = 1$,$\exp(-\alpha_t) < 1$,权重降低 预测错误:$y_i h_t(x_i) = -1$,$\exp(\alpha_t) > 1$,权重提升
4.3 归一化因子
$$Z_t = \sum_{i=1}^{N} w_i^{(t)} \exp(-\alpha_t y_i h_t(x_i))$$
4.4 最终分类器
$$H(x) = \text{sign}\left(\sum_{t=1}^{T} \alpha_t h_t(x)\right)$$
5 代码示例
import numpy as np
# 1. 示例数据
print("=== AdaBoost推导示例 ===")
# 10个样本
X = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
y = np.array([1, 1, 1, 1, 1, -1, -1, -1, -1, -1]) # 前5正,后5负
print(f"X: {X}")
print(f"y: {y}")
# 2. 初始化样本权重(均匀分布)
n = len(y)
w = np.ones(n) / n
print(f"\n初始权重: {w}")
# 3. 计算各切分点的错误率
print("\n=== 各切分点错误率 ===")
split_points = [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5]
best_error = float('inf')
best_split = None
for sp in split_points:
# 左边预测为正(1),右边预测为负(-1)
y_pred = np.where(X <= sp, 1, -1)
# 计算加权错误率
error = np.sum(w * (y_pred != y))
print(f"切分点{sp}: 错误率={error:.4f}")
if error < best_error:
best_error = error
best_split = sp
print(f"\n最优切分点: {best_split}, 错误率: {best_error:.4f}")
# 4. 计算模型权重
alpha = 0.5 * np.log((1 - best_error) / best_error)
print(f"\n模型权重 alpha: {alpha:.4f}")
# 5. 更新样本权重
y_pred = np.where(X <= best_split, 1, -1)
correct = (y_pred == y)
# 预测正确:权重 * exp(-alpha)
# 预测错误:权重 * exp(alpha)
w_new = w * np.exp(-alpha * y * y_pred)
# 归一化
Z = np.sum(w_new)
w_normalized = w_new / Z
print(f"\n更新后权重:")
for i in range(n):
status = "正确" if correct[i] else "错误"
print(f" 样本{i}: 原权重={w[i]:.4f}, {status}, 新权重={w_normalized[i]:.4f}")
# 6. 完整AdaBoost过程
print("\n=== 完整AdaBoost过程 ===")
def adaboost_train(X, y, T=5):
"""AdaBoost训练过程"""
n = len(y)
w = np.ones(n) / n # 初始化权重
alphas = []
classifiers = []
for t in range(T):
# 找最优切分点
best_error = float('inf')
best_split = None
for sp in np.arange(0.5, len(X)-0.5, 1):
y_pred = np.where(X <= sp, 1, -1)
error = np.sum(w * (y_pred != y))
if error < best_error:
best_error = error
best_split = sp
# 计算模型权重
alpha = 0.5 * np.log((1 - best_error) / (best_error + 1e-10))
# 预测
y_pred = np.where(X <= best_split, 1, -1)
# 更新样本权重
w = w * np.exp(-alpha * y * y_pred)
w = w / np.sum(w) # 归一化
alphas.append(alpha)
classifiers.append(best_split)
print(f"第{t+1}轮: 切分点={best_split}, 错误率={best_error:.4f}, alpha={alpha:.4f}")
return alphas, classifiers
# 运行
alphas, classifiers = adaboost_train(X, y, T=5)
# 7. 最终分类器
print("\n=== 最终分类器 ===")
print(f"模型权重: {alphas}")
print(f"切分点: {classifiers}")
# 预测
def adaboost_predict(x, alphas, classifiers):
"""AdaBoost预测"""
result = 0
for alpha, sp in zip(alphas, classifiers):
h = 1 if x <= sp else -1
result += alpha * h
return 1 if result > 0 else -1
# 测试
print("\n=== 预测测试 ===")
test_points = [0, 2, 4, 6, 8]
for x in test_points:
pred = adaboost_predict(x, alphas, classifiers)
print(f"X={x}: 预测={'正样本' if pred == 1 else '负样本'}")
输出示例:
=== AdaBoost推导示例 ===
X: [0 1 2 3 4 5 6 7 8 9]
y: [ 1 1 1 1 1 -1 -1 -1 -1 -1]
初始权重: [0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]
=== 各切分点错误率 ===
切分点0.5: 错误率=0.5000
切分点1.5: 错误率=0.4000
切分点2.5: 错误率=0.3000
切分点3.5: 错误率=0.2000
切分点4.5: 错误率=0.0000
最优切分点: 4.5, 错误率: 0.0000
模型权重 alpha: 9.9048
=== 完整AdaBoost过程 ===
第1轮: 切分点=4.5, 错误率=0.0000, alpha=9.9048
...
6 重难点与易错提醒
- ❗重点:错误率 = 预测错误样本数 / 总样本数。
- ❗重点:模型权重 $\alpha = \frac{1}{2}\ln\frac{1-\epsilon}{\epsilon}$。
- ❗重点:预测对权重降低,预测错权重提升。
- ❗重点:每次更新权重后要归一化。
- ⚠️易错:切分点选择错误。
- ⚠️易错:忘记归一化。
- 💡深入理解:通过权重调整,让后续模型关注错误样本。
7 课堂问答精选
Q: AdaBoost如何计算模型权重?
A: 模型权重公式:$\alpha = \frac{1}{2}\ln\frac{1-\epsilon}{\epsilon}$ 其中$\epsilon$是错误率。错误率越小,模型权重越大;错误率越大,模型权重越小。当错误率为0.5时,模型权重为0(无信息)。
Q: 样本权重如何更新?
A:
- 预测正确:$w_i^{(t+1)} = w_i^{(t)} \cdot e^{-\alpha}$(权重降低)
- 预测错误:$w_i^{(t+1)} = w_i^{(t)} \cdot e^{\alpha}$(权重提升)
- 归一化:$\hat{w}_i = w_i / Z$,保证权重之和为1
8 本课小结
- 错误率:预测错误样本数 / 总样本数。
- 模型权重:$\alpha = \frac{1}{2}\ln\frac{1-\epsilon}{\epsilon}$。
- 样本权重更新:预测对降低,预测错提升。
- 归一化:保证权重之和为1。
- 最终分类器:加权组合所有弱学习器。
9 延伸思考与实践
- 实践:手动计算AdaBoost的权重更新。
- 预习:AdaBoost葡萄酒案例。
- 思考:为什么错误率越小,模型权重越大?