Boosting算法原理与AdaBoost
Boosting原理
Boosting方法是使用同一组数据集进行反复学习得到的弱学习器来最终产生预测性能强大的学习器。
Boosting是通过不断减少偏差的形式来提高最终的预测效果,与之前介绍的Bagging有着本质的不同。Bagging是采用通过全样本抽样子集进行训练投票得出最终的预测,而Boosting是全样本训练优化。
Bagging和Boosting的区别
- 样本选择:
Bagging:训练集是有放回的选取出子集的,各子集独立训练。
Boosting:训练集不变,分类器中的权重发生变化。而权重是根据上一轮的结果进行调整。 - 样例权重:
Bagging:使用均匀取样,每个样例的权重相等。
Boosting:根据错误率不断调整样例的权值,错误率越大则权重越大。 - 预测函数:
Bagging:所有预测函数的权重相等。
Boosting:每个弱分类器都有相应的权重,分类误差小的分类器会有更大的权重。 - 并行计算:
Bagging:各个预测函数可以并行生成。
Boosting:各个预测函数只能顺序生成,后一个模型参数需要前一轮模型的结果。
Boosting有多种方式:
AdaBoost(Adaptive Boosting)
Gradient Boosting 又称GBDT (Gradient Boosting Decision Tree )
XGBoost (Extreme Gradient Boosting) 改进的GBDT
LightGBM
Adaboost算法
采用Boosting提升预测性能有两大问题需要解决:
1.在每一轮学习如何改变数据权值或概率分布
2.如何将弱分类器组合成一个强分类器
AdaBoost的解决方式是
1.提高前一轮分类器错误分类的样本权重,降低正确分类样本权重,后一轮分类器就会更加关注没被正确分类的样本。
2.采用加权多数表决法, 加大误差率小的弱分类器权值,减小误差率大的弱分类器权值,使表决结果更倾向于误差率小的分类器
下面给出了Adaboost直观的算法描述
假设给定一个二分类训练样本集为
T
=
{
(
x
,
y
1
)
,
(
x
2
,
y
2
)
,
.
.
.
(
x
m
,
y
m
)
}
T=\{(x_,y_1),(x_2,y_2), ...(x_m,y_m)\}
T={(x,y1),(x2,y2),...(xm,ym)}
其中特征
x
i
∈
X
⊆
R
n
x_{i} \in {X} \subseteq \mathbf{R}^{n}
xi∈X⊆Rn,类别
y
i
∈
Y
=
{
−
1
,
+
1
}
y_{i} \in {Y}=\{-1,+1\}
yi∈Y={−1,+1},输出最终分类器
G
(
x
)
G(x)
G(x)。
第k个弱学习器的输出权重为
D
k
=
(
w
k
1
,
w
k
2
,
.
.
.
w
k
m
)
;
D_{k} = (w_{k1}, w_{k2}, ...w_{km}) ;\;\;
Dk=(wk1,wk2,...wkm);
- 初始权重我们设为 D 1 = ( w 11 , w 12 , . . . w 1 m ) ; w 1 i = 1 m ; i = 1 , 2... m D_{1} = (w_{11}, w_{12}, ...w_{1m}) ;\;\;w_{1i}=\frac{1}{m};\;\; i =1,2...m D1=(w11,w12,...w1m);w1i=m1;i=1,2...m
- 对于
k
=
1...
N
k=1...N
k=1...N
- 在具有权值分布的 D k D_{k} Dk的训练集上训练,得到基分类器 G k ( x ) G_{k}(x) Gk(x)
- 计算第k个分类器在训练集上的加权误差率为
e k = P ( G k ( x i ) ≠ y i ) = ∑ i = 1 m w k i I ( G k ( x i ) ≠ y i ) e_k = P(G_k(x_i) \neq y_i) = \sum\limits_{i=1}^{m}w_{ki}I(G_k(x_i) \neq y_i) ek=P(Gk(xi)=yi)=i=1∑mwkiI(Gk(xi)=yi) - 计算第k个分类器
G
k
(
x
)
G_{k}(x)
Gk(x)的权重系数
α k = 1 2 l o g 1 − e k e k \alpha_k = \frac{1}{2}log\frac{1-e_k}{e_k} αk=21logek1−ek - 更新
k
+
1
k+1
k+1轮的权重分布
w k + 1 , i = w k i Z k e x p ( − α k y i G k ( x i ) ) w_{k+1,i} = \frac{w_{ki}}{Z_k}exp(-\alpha_ky_iG_k(x_i)) wk+1,i=Zkwkiexp(−αkyiGk(xi))
这里的 Z k Z_{k} Zk是规范化因子
Z k = ∑ i = 1 m w k i e x p ( − α k y i G k ( x i ) ) Z_k = \sum\limits_{i=1}^{m}w_{ki}exp(-\alpha_ky_iG_k(x_i)) Zk=i=1∑mwkiexp(−αkyiGk(xi))
从 w k + 1 , i w_{k+1,i} wk+1,i计算公式可以看出,如果第i个样本分类错误,则 y i G k ( x i ) < 0 y_iG_k(x_i) < 0 yiGk(xi)<0,导致样本的权重在第k+1个弱分类器中增大,如果分类正确,则权重在第k+1个弱分类器中减小。
- 集成基分类器,得到最终的强分类器
G ( x ) = s i g n ( ∑ k = 1 N α k G k ( x ) ) G(x) = sign(\sum\limits_{k=1}^{N}\alpha_kG_k(x)) G(x)=sign(k=1∑NαkGk(x))
Adaboost应用示例
以UCI机器学习库的葡萄酒数据集为例,该数据集可以在 ( https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data )上获得。该数据集包含了178个样本和13个特征,包含不同的角度不同的化学特性的特征,根据这些数据预测红酒属于哪一个类别。
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.preprocessing import LabelEncoder
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.ensemble import AdaBoostClassifier
from sklearn.model_selection import train_test_split
# 获取数据集,划分训练集及测试集
# 数据文件
data_file='https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data'
# 数据列名
wine_columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash', 'Alcalinity of ash','Magnesium', 'Total phenols',
'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins','Color intensity', 'Hue','OD280/OD315 of diluted wines','Proline']
wine=pd.read_csv(data_file,header=None,names=wine_columns)
# 仅做二分类演示,排除类别为1的数据
wine = wine[wine['Class label'] != 1]
y = wine['Class label'].values
# 仅选取部分特征进行实验
X = wine[['Alcohol', 'Malic acid', 'Magnesium', 'Total phenols']].values
le = LabelEncoder()
y = le.fit_transform(y)
# 按8:2比拆分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8, random_state=1, stratify=y)
# 使用单一决策树训练并展示效果
tree = DecisionTreeClassifier(criterion='entropy', random_state=1, max_depth=1)
tree = tree.fit(X_train, y_train)
y_train_pred = tree.predict(X_train)
y_test_pred = tree.predict(X_test)
tree_train = accuracy_score(y_train, y_train_pred)
tree_test = accuracy_score(y_test,y_test_pred)
print('Decision tree train/test accuracies {:.3f}/{:.3f}'.format(tree_train, tree_test))
运行结果
Decision tree train/test accuracies 0.853/0.750
# 使用Adaboost训练并展示效果
tree = DecisionTreeClassifier(criterion='entropy', random_state=1, max_depth=1)
ada = AdaBoostClassifier(base_estimator=tree, n_estimators=1000, learning_rate=0.1, random_state=1)
ada = ada.fit(X_train, y_train)
y_train_pred = ada.predict(X_train)
y_test_pred = ada.predict(X_test)
ada_train = accuracy_score(y_train, y_train_pred)
ada_test = accuracy_score(y_test, y_test_pred)
print('Adaboost train/test accuracies {:.3f}/{:.3f}'.format(ada_train, ada_test))
运行结果
Adaboost train/test accuracies 1.000/0.917