一、概念
AdaBoost(自适应提升)是一种集成学习(Ensemble Learning)算法 ,属于Boosting家族。其核心思想是:通过迭代训练一系列"弱分类器"(性能略优于随机猜测,如决策树桩),并根据每个弱分类器的表现赋予不同权重,最终将它们加权组合成一个"强分类器"。
"自适应"体现在:每个弱分类器训练时,会自适应地调整样本权重------前一个分类器错分的样本权重会被放大,使得下一个分类器更关注这些难分样本,从而逐步提升整体性能。
二、核心理论
AdaBoost的工作流程可概括为4步迭代过程:
- 初始化样本权重 :所有样本初始权重相等(如 wi=1/Nw_i = 1/Nwi=1/N,NNN 为样本数)。
- 训练弱分类器 :基于当前样本权重,训练一个弱分类器 hm(x)h_m(x)hm(x)(第 mmm 轮迭代的分类器),目标是最小化带权重的分类错误。
- 计算弱分类器权重 :根据弱分类器的错误率 ϵm\epsilon_mϵm,计算其在最终强分类器中的权重 αm\alpha_mαm(错误率越低,权重越高)。
- 更新样本权重:对正确分类的样本降低权重,错分样本提高权重(使下一轮更关注错分样本),并归一化权重以保证总和为1。
重复步骤2-4,直到训练出预设数量的弱分类器(如 MMM 个),最终强分类器为所有弱分类器的加权投票(分类任务)或加权求和(回归任务)。
三、数学公式
1. 样本权重初始化
设训练集为 {(x1,y1),(x2,y2),...,(xN,yN)}\{(x_1,y_1), (x_2,y_2), ..., (x_N,y_N)\}{(x1,y1),(x2,y2),...,(xN,yN)},其中 yi∈{−1,1}y_i \in \{-1, 1\}yi∈{−1,1}(二分类,正类1,负类-1),初始权重为:
w1,i=1N(i=1,2,...,N) w_{1,i} = \frac{1}{N} \quad (i=1,2,...,N) w1,i=N1(i=1,2,...,N)
2. 弱分类器错误率
第 mmm 轮迭代中,弱分类器 hm(x):X→{−1,1}h_m(x): X \to \{-1, 1\}hm(x):X→{−1,1} 的带权重错误率为:
ϵm=∑i=1Nwm,i⋅I(hm(xi)≠yi) \epsilon_m = \sum_{i=1}^N w_{m,i} \cdot I(h_m(x_i) \neq y_i) ϵm=i=1∑Nwm,i⋅I(hm(xi)=yi)
其中 I(⋅)I(\cdot)I(⋅) 为指示函数(条件成立时为1,否则为0),wm,iw_{m,i}wm,i 为第 mmm 轮样本 iii 的权重。
3. 弱分类器权重
第 mmm 个弱分类器的权重 αm\alpha_mαm 由其错误率决定(错误率越低,权重越高):
αm=12log(1−ϵmϵm) \alpha_m = \frac{1}{2} \log\left( \frac{1 - \epsilon_m}{\epsilon_m} \right) αm=21log(ϵm1−ϵm)
(推导见下文,核心是最小化损失函数)。
4. 样本权重更新
第 mmm 轮迭代后,样本 iii 的权重更新为:
wm+1,i=wm,i⋅exp(−αm⋅yi⋅hm(xi))Zm w_{m+1,i} = \frac{w_{m,i} \cdot \exp\left( -\alpha_m \cdot y_i \cdot h_m(x_i) \right)}{Z_m} wm+1,i=Zmwm,i⋅exp(−αm⋅yi⋅hm(xi))
其中 ZmZ_mZm 为归一化因子(确保权重和为1):
Zm=∑i=1Nwm,i⋅exp(−αm⋅yi⋅hm(xi)) Z_m = \sum_{i=1}^N w_{m,i} \cdot \exp\left( -\alpha_m \cdot y_i \cdot h_m(x_i) \right) Zm=i=1∑Nwm,i⋅exp(−αm⋅yi⋅hm(xi))
更新逻辑:若 hm(xi)=yih_m(x_i) = y_ihm(xi)=yi(正确分类),则 yi⋅hm(xi)=1y_i \cdot h_m(x_i) = 1yi⋅hm(xi)=1,权重乘以 exp(−αm)\exp(-\alpha_m)exp(−αm)(降低);若错分,则乘以 exp(αm)\exp(\alpha_m)exp(αm)(升高)。
5. 强分类器
MMM 个弱分类器加权组合得到强分类器 H(x)H(x)H(x):
H(x)=sign(∑m=1Mαm⋅hm(x)) H(x) = \text{sign}\left( \sum_{m=1}^M \alpha_m \cdot h_m(x) \right) H(x)=sign(m=1∑Mαm⋅hm(x))
其中 sign(⋅)\text{sign}(\cdot)sign(⋅) 为符号函数(输出1或-1)。
四、推导过程(核心公式推导)
AdaBoost的推导基于指数损失函数 (Exponential Loss),目标是通过最小化损失函数确定弱分类器权重 αm\alpha_mαm 和样本权重更新规则。
1. 指数损失函数
设强分类器在第 mmm 轮的输出为 Hm(x)=Hm−1(x)+αmhm(x)H_m(x) = H_{m-1}(x) + \alpha_m h_m(x)Hm(x)=Hm−1(x)+αmhm(x)(逐步叠加弱分类器),损失函数定义为:
L(Hm)=∑i=1Nexp(−yiHm(xi)) L(H_m) = \sum_{i=1}^N \exp\left( -y_i H_m(x_i) \right) L(Hm)=i=1∑Nexp(−yiHm(xi))
2. 弱分类器权重 αm\alpha_mαm 的推导
将 Hm(x)=Hm−1(x)+αmhm(x)H_m(x) = H_{m-1}(x) + \alpha_m h_m(x)Hm(x)=Hm−1(x)+αmhm(x) 代入损失函数:
L(Hm)=∑i=1Nexp(−yi(Hm−1(xi)+αmhm(xi)))=∑i=1Nexp(−yiHm−1(xi))⋅exp(−αmyihm(xi)) L(H_m) = \sum_{i=1}^N \exp\left( -y_i (H_{m-1}(x_i) + \alpha_m h_m(x_i)) \right) = \sum_{i=1}^N \exp\left( -y_i H_{m-1}(x_i) \right) \cdot \exp\left( -\alpha_m y_i h_m(x_i) \right) L(Hm)=i=1∑Nexp(−yi(Hm−1(xi)+αmhm(xi)))=i=1∑Nexp(−yiHm−1(xi))⋅exp(−αmyihm(xi))
令 wm,i=exp(−yiHm−1(xi))/Zm−1w_{m,i} = \exp\left( -y_i H_{m-1}(x_i) \right) / Z_{m-1}wm,i=exp(−yiHm−1(xi))/Zm−1(归一化后的权重,Zm−1Z_{m-1}Zm−1 为常数),则损失函数可写为:
L(Hm)=Zm−1∑i=1Nwm,i⋅exp(−αmyihm(xi)) L(H_m) = Z_{m-1} \sum_{i=1}^N w_{m,i} \cdot \exp\left( -\alpha_m y_i h_m(x_i) \right) L(Hm)=Zm−1i=1∑Nwm,i⋅exp(−αmyihm(xi))
忽略常数 Zm−1Z_{m-1}Zm−1,对 αm\alpha_mαm 求导并令导数为0,最小化损失:
- 当 hm(xi)=yih_m(x_i) = y_ihm(xi)=yi 时,yihm(xi)=1y_i h_m(x_i) = 1yihm(xi)=1,项为 wm,iexp(−αm)w_{m,i} \exp(-\alpha_m)wm,iexp(−αm);
- 当 hm(xi)≠yih_m(x_i) \neq y_ihm(xi)=yi 时,yihm(xi)=−1y_i h_m(x_i) = -1yihm(xi)=−1,项为 wm,iexp(αm)w_{m,i} \exp(\alpha_m)wm,iexp(αm)。
总损失为 L(αm)=(1−ϵm)exp(−αm)+ϵmexp(αm)L(\alpha_m) = (1 - \epsilon_m) \exp(-\alpha_m) + \epsilon_m \exp(\alpha_m)L(αm)=(1−ϵm)exp(−αm)+ϵmexp(αm),求导得:
dLdαm=−(1−ϵm)exp(−αm)+ϵmexp(αm)=0 \frac{dL}{d\alpha_m} = -(1 - \epsilon_m) \exp(-\alpha_m) + \epsilon_m \exp(\alpha_m) = 0 dαmdL=−(1−ϵm)exp(−αm)+ϵmexp(αm)=0
解得:
exp(2αm)=1−ϵmϵm ⟹ αm=12log(1−ϵmϵm) \exp(2\alpha_m) = \frac{1 - \epsilon_m}{\epsilon_m} \implies \alpha_m = \frac{1}{2} \log\left( \frac{1 - \epsilon_m}{\epsilon_m} \right) exp(2αm)=ϵm1−ϵm⟹αm=21log(ϵm1−ϵm)
3. 样本权重更新推导
第 m+1m+1m+1 轮的样本权重 wm+1,iw_{m+1,i}wm+1,i 与 exp(−yiHm(xi))\exp(-y_i H_m(x_i))exp(−yiHm(xi)) 成正比:
wm+1,i∝exp(−yiHm(xi))=exp(−yi(Hm−1(xi)+αmhm(xi)))=wm,i⋅Zm−1⋅exp(−αmyihm(xi)) w_{m+1,i} \propto \exp(-y_i H_m(x_i)) = \exp\left( -y_i (H_{m-1}(x_i) + \alpha_m h_m(x_i)) \right) = w_{m,i} \cdot Z_{m-1} \cdot \exp\left( -\alpha_m y_i h_m(x_i) \right) wm+1,i∝exp(−yiHm(xi))=exp(−yi(Hm−1(xi)+αmhm(xi)))=wm,i⋅Zm−1⋅exp(−αmyihm(xi))
归一化后即为:
wm+1,i=wm,i⋅exp(−αmyihm(xi))Zm w_{m+1,i} = \frac{w_{m,i} \cdot \exp\left( -\alpha_m y_i h_m(x_i) \right)}{Z_m} wm+1,i=Zmwm,i⋅exp(−αmyihm(xi))
五、Python实现(AdaBoost分类器,基于决策树桩)
以决策树桩(深度为1的决策树,最简单的弱分类器)为例实现AdaBoost:
python
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification
from sklearn.metrics import accuracy_score
# 弱分类器:决策树桩(单特征阈值分类)
class DecisionStump:
def __init__(self):
self.theta = None # 阈值
self.feature_idx = None # 特征索引
self.sign = 1 # 符号(1或-1,决定阈值方向)
def fit(self, X, y, weights):
n_samples, n_features = X.shape
min_error = float('inf')
# 遍历所有特征
for idx in range(n_features):
X_col = X[:, idx]
thresholds = np.unique(X_col) # 用特征的唯一值作为候选阈值
# 遍历所有阈值
for theta in thresholds:
# 尝试两种符号(大于阈值为1或-1)
for sign in [1, -1]:
y_pred = sign * np.where(X_col >= theta, 1, -1) # 预测
error = np.sum(weights * (y_pred != y)) # 带权重的错误率
# 记录最优参数
if error < min_error:
min_error = error
self.theta = theta
self.feature_idx = idx
self.sign = sign
self.error = min_error
def predict(self, X):
X_col = X[:, self.feature_idx]
return self.sign * np.where(X_col >= self.theta, 1, -1)
# AdaBoost分类器
class AdaBoost:
def __init__(self, n_estimators=50):
self.n_estimators = n_estimators # 弱分类器数量
self.estimators = [] # 弱分类器列表
self.alphas = [] # 弱分类器权重
def fit(self, X, y):
n_samples = X.shape[0]
# 初始化样本权重
weights = np.full(n_samples, 1 / n_samples)
for _ in range(self.n_estimators):
# 1. 训练弱分类器(决策树桩)
stump = DecisionStump()
stump.fit(X, y, weights)
self.estimators.append(stump)
# 2. 计算弱分类器权重
epsilon = stump.error
if epsilon >= 0.5: # 弱分类器性能需优于随机猜测
break
alpha = 0.5 * np.log((1 - epsilon) / epsilon)
self.alphas.append(alpha)
# 3. 更新样本权重
y_pred = stump.predict(X)
weights *= np.exp(-alpha * y * y_pred) # 错分样本权重增大
weights /= np.sum(weights) # 归一化
def predict(self, X):
# 所有弱分类器加权求和
final_pred = np.sum(alpha * clf.predict(X) for alpha, clf in zip(self.alphas, self.estimators))
return np.sign(final_pred) # 符号函数输出分类结果
# 测试代码
if __name__ == "__main__":
# 生成二分类数据(标签转为-1和1)
X, y = make_classification(n_samples=1000, n_features=10, n_classes=2, random_state=42)
y = np.where(y == 0, -1, 1) # AdaBoost通常用-1/1表示标签
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 训练模型
model = AdaBoost(n_estimators=50)
model.fit(X_train, y_train)
# 预测与评估
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"自定义AdaBoost准确率:{accuracy:.4f}") # 约 0.90-0.95
六、sklearn实现
sklearn的 AdaBoostClassifier 支持多类分类,默认弱分类器为决策树桩(DecisionTreeClassifier(max_depth=1)),主要参数包括:
base_estimator:弱分类器类型(默认决策树桩);n_estimators:弱分类器数量(默认50);learning_rate:学习率(缩放弱分类器权重,默认1.0)。
示例(乳腺癌分类数据集)
python
from sklearn.ensemble import AdaBoostClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 加载数据(标签转为-1和1,或保持0/1均可,sklearn内部兼容)
data = load_breast_cancer()
X, y = data.data, data.target
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.2, random_state=42)
# 初始化模型(50个弱分类器,学习率1.0)
model = AdaBoostClassifier(n_estimators=50, learning_rate=1.0, random_state=42)
# 训练
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
# 评估
accuracy = accuracy_score(y_test, y_pred)
print(f"sklearn AdaBoost准确率:{accuracy:.4f}") # 约 0.96-0.98
七、总结
- 优点:无需手动设计弱分类器(默认决策树桩即可);对噪声不敏感(相比其他Boosting算法);可解释性较强(弱分类器权重反映重要性)。
- 缺点:训练时间随弱分类器数量增加而增长;对异常值敏感(错分样本权重持续放大);难以处理高维稀疏数据(需配合特征选择)。
- 适用场景:二分类/多分类任务(如欺诈检测、图像识别),尤其适合中等规模数据集。