在sklearn中,AdaBoost既可以实现分类也可以实现回归,可以使用如下两个类来调用它们:
-
sklearn.ensemble.AdaBoostClassifier(base_estimator=None, *, n_estimators=50, learning_rate=1.0, algorithm=‘SAMME.R’, random_state=None)
-
sklearn.ensemble.AdaBoostRegressor(base_estimator=None, *, n_estimators=50, learning_rate=1.0, loss=‘linear’, random_state=None)
| 参数 | 参数含义 |
|---|---|
| base_estimator | 弱评估器 |
| n_estimators | 集成算法中弱评估器的数量 |
| learning_rate | 迭代中所使用的学习率 |
| algorithm(分类器专属) | 用于指定分类ADB中使用的具体实现方法 |
| loss(回归器专属) | 用于指定回归ADB中使用的损失函数 |
| random_state | 用于控制每次建树之前随机抽样过程的随机数种子 |
- base_estimator
默认的弱评估器还是决策树;
- learning_rate
对于第 t t t次迭代来说:
H t ( x i ) = H t − 1 ( x i ) + η ϕ t f t ( x i ) H_t(x_i) = H_{t-1}(x_i) + boldsymbol{color{red}eta} phi_tf_t(x_i) Ht(xi)=Ht−1(xi)+ηϕtft(xi)
其中, ϕ t phi_t ϕt为第t棵树的权重; η color{red}eta η表示为第t棵树加入整体集成算法时的学习率。该学习率参数控制Boosting集成过程中 H ( x i ) H(x_i) H(xi)的增长速度,是相当关键的参数。当学习率很大时, H ( x i ) H(x_i) H(xi)增长得更快,我们所需的 n _ e s t i m a t o r s color{red}n_estimators n_estimators更少,当学习率较小时, H ( x i ) H(x_i) H(xi)增长较慢,我们所需的n_estimators就更多,因此boosting算法往往会需要在n_estimators与learning_rate当中做出权衡(以XGBoost算法为例)。
需要注意的是,以上式子为boosting算法中计算方式的一般规则,并不是具体到AdaBoost或任意Boosting集成算法的具体公式。
- algorithm
首先,参数algorithm是针对分类器设置的参数,其中备选项有“SAMME"与"SAMME.R”。
- SAMME是基于算法输出的具体分类结果(例如-1,1,2)进行计算;
- SAMME.R则是在SAMME基础上改进过后、基于弱分配器输出的概率值进行计算;
两种方法都支持在AdaBoost上完成多分类任务,但SAMME.R往往能够得到更好的结果,因此sklearn中的默认值是SAMME.R,因此sklearn中默认可以输入的base_estimators也需要是能够输出预测概率的弱评估器。实际在预测时,AdaBoost输出的 H ( x ) H(x) H(x)也针对于某一类别的概率。
SAMME与SAMME.R使用了相同的损失函数:二分类指数损失(Exponential Loss Function)与多分类指数损失(Multi-class Exponential loss function)。
- 二分类指数损失
L ( H ( x ) , y ) = e − y H ∗ ( x ) L(H(x),y) = e^{-yH^*(x)} L(H(x),y)=e−yH∗(x)
其中y为真实分类, H ∗ ( x ) H^*(x) H∗(x)则是从集成算法输出的概率结果 H ( x ) H(x) H(x)转换来的向量。转换规则如下:
H ∗ ( x ) = { 1 i f H ( x ) > 0.5 − 1 i f H ( x ) < 0.5 H^*(x)= begin{cases} 1& if H(x)>0.5 \ -1& if H(x) < 0.5 end{cases} H∗(x)={1−1if H(x)>0.5if H(x)<0.5
在sklearn当中,由于 H ( x ) H(x) H(x)是概率值,因此需要转换为 H ∗ ( x ) H^*(x) H∗(x),如果在其他实现AdaBoost的算法库中, H ( x ) H(x) H(x)输出直接为预测类别,则可以不执行转换流程。
根据指数损失的特殊性质,二分类状况下的类别取值只能为-1或1,因此 y y y的取值只能为-1或1。当算法预测正确时, y H ∗ ( x ) yH^*(x) yH∗(x)的符号为正,则在函数 e − x e^{-x} e−x上损失很小。当算法预测错误时, y H ∗ ( x ) yH^*(x) yH∗(x)的符号为负,则在函数 e − x e^{-x} e−x上损失较大。二分类指数损失是AdaBoost最经典的损失函数,它在数学推导上的有效性以及在实践过程中很强的指导性让其沿用至今。
- 多分类指数损失
L
(
H
(
x
)
,
y
)
=
e
x
p
(
−
1
K
y
∗
⋅
H
∗
(
x
)
)
=
e
x
p
(
−
1
K
(
y
∗
1
H
∗
1
(
x
)
+
y
∗
2
H
∗
2
(
x
)
+
.
.
.
+
y
∗
k
H
∗
k
(
x
)
)
)
begin{aligned} L(H(x),y) &=exp left( -frac{1}{K}boldsymbol{y^* · H^*(x)} right) \ & = exp left( -frac{1}{K}(y^{*1}H^{*1}(x)+y^{*2}H^{*2}(x) + ... + y^{*k}H^{*k}(x)) right) end{aligned}
L(H(x),y)=exp(−K1y∗⋅H∗(x))=exp(−K1(y∗1H∗1(x)+y∗2H∗2(x) + ...+y∗kH∗k(x)))
其中,
K
K
K为总类别数,如四分类[0,1,2,3]的情况时,
K
=
4
K=4
K=4,
y
∗
boldsymbol{y^*}
y∗与
H
∗
(
x
)
boldsymbol{H^*(x)}
H∗(x)都是根据多分类具体情况、以及集成算法实际输出
H
(
x
)
H(x)
H(x)转化出的向量,其中
y
∗
1
y^{*1}
y∗1与
H
∗
1
(
x
)
H^{*1}(x)
H∗1(x)的上标1都表示当前类别。
在二分类算法中,算法会直接针对二分类中的其中一个类别输出概率,因为在二分类中 P ( Y = 1 ) = 1 − P ( Y = − 1 ) P(Y=1) = 1 - P(Y=-1) P(Y=1)=1−P(Y=−1),所以只计算出一类的概率即可判断预测的标签。但在多分类算法中,算法必须针对所有可能的取值类型都输出概率,才能够从中找出最大概率所对应的预测标签。
对一棵决策树我们会输出k个概率,对于boosting集成中的每一棵树,在任意样本上都会得到 f c = 0 ( x ) f^{c=0}(x) fc=0(x)、 f c = 1 ( x ) f^{c=1}(x) fc=1(x)、 f c = 2 ( x ) f^{c=2}(x) fc=2(x)……数个不同的结果。在集成算法当中,每个样本在第t次建树过程中,都会生成针对于不同类别的结果:
H
t
0
(
x
i
)
=
H
t
−
1
0
(
x
i
)
+
ϕ
t
f
t
0
(
x
i
)
H_{t}^0(x_i) = H_{t-1}^0(x_i) + phi_tf_t^0(x_i)
Ht0(xi)=Ht−10(xi)+ϕtft0(xi)
H
t
1
(
x
i
)
=
H
t
−
1
1
(
x
i
)
+
ϕ
t
f
t
1
(
x
i
)
H_{t}^1(x_i) = H_{t-1}^1(x_i) + phi_tf_t^1(x_i)
Ht1(xi)=Ht−11(xi)+ϕtft1(xi)
H
t
2
(
x
i
)
=
H
t
−
1
2
(
x
i
)
+
ϕ
t
f
t
2
(
x
i
)
H_{t}^2(x_i) = H_{t-1}^2(x_i) + phi_tf_t^2(x_i)
Ht2(xi)=Ht−12(xi)+ϕtft2(xi)
…
…
……
……
H
t
k
(
x
i
)
=
H
t
−
1
k
(
x
i
)
+
ϕ
t
f
t
k
(
x
i
)
H_{t}^k(x_i) = H_{t-1}^k(x_i) + phi_tf_t^k(x_i)
Htk(xi)=Ht−1k(xi)+ϕtftk(xi)
因此,我们可以得到向量 [ H 0 ( x ) , H 1 ( x ) , H 2 ( x ) , . . . , H k ( x ) ] [H^0(x),H^1(x),H^2(x),...,H^k(x)] [H0(x),H1(x),H2(x),...,Hk(x)],表示当前集成算法计算出的、针对多个类别的概率(也是对全部弱分类器输出的、针对多个类别的概率进行的加权求和)。针对该向量,一定可以得到向量中的一个最大值,该最大值所对应的标签类别就是多分类算法中的预测标签类别。根据该向量,以及指数损失的特性,我们规定:
H ∗ ( x ) = { 1 i f k = a r g m a x H ( x ) − 1 K − 1 i f k ≠ a r g m a x H ( x ) H^*(x)= begin{cases} 1& if k = argmaxH(x) \ -frac{1}{K-1}& if k neq argmaxH(x) end{cases} H∗(x)={1−K−11if k=argmaxH(x)if k=argmaxH(x)
其中, a r g m a x H ( x ) argmaxH(x) argmaxH(x)对应的是预测标签, k k k为所有预选标签类别。
另外一方面,
y
∗
boldsymbol{y^*}
y∗一般来说都是真实标签经过上述处理后的结果:
y
∗
=
{
1
i
f
k
=
y
i
−
1
K
−
1
i
f
k
≠
y
i
y^*= begin{cases} 1& if k=y_i \ -frac{1}{K-1}& if kneq y_i end{cases}
y∗={1−K−11if k=yiif k=yi
其中
y
i
y_i
yi为样本的真实标签,
k
k
k为所有预选标签类别.
在此规则下,此时向量 y ∗ boldsymbol{y^*} y∗以及向量 H ∗ ( x ) boldsymbol{H^*(x)} H∗(x)的和永远是0,因为向量内部总是1与(K-1)个 − 1 K − 1 -frac{1}{K-1} −K−11相加。
假设在4分类情况下,集成算法针对样本 i i i的各个分类输出的概率如下所示,则向量 H ∗ ( x ) boldsymbol{H^*(x)} H∗(x)的取值如下所示:
| 0 0 0 | 1 1 1 | 2 2 2 | 3 3 3 | |
|---|---|---|---|---|
| H t k ( x i ) H_t^k(x_i) Htk(xi) | 0.1 0.1 0.1 | 0.2 0.2 0.2 | 0.2 0.2 0.2 | 0.5 0.5 0.5 |
| H ∗ ( x ) H^*(x) H∗(x) | − 1 3 -frac{1}{3} −31 | − 1 3 -frac{1}{3} −31 | − 1 3 -frac{1}{3} −31 | 1 1 1 |
| y ∗ boldsymbol{y^*} y∗ | − 1 3 -frac{1}{3} −31 | − 1 3 -frac{1}{3} −31 | 1 ( 真 实 值 ) 1(真实值) 1(真实值) | − 1 3 -frac{1}{3} −31 |
则:
L
=
e
−
1
4
(
−
1
3
∗
−
1
3
+
−
1
3
∗
−
1
3
+
−
1
3
∗
1
+
1
∗
−
1
3
)
L =e^{-frac{1}{4}(-frac{1}{3}*-frac{1}{3}+-frac{1}{3}*-frac{1}{3}+-frac{1}{3}*1+1*-frac{1}{3})}
L=e−41(−31∗−31+−31∗−31+−31∗1+1∗−31)
当K=2时,多分类指数损失的值与二分类指数损失完全一致:
,
L = e x p ( − 1 K ( y ∗ 1 H ∗ 1 ( x ) + y ∗ 2 H ∗ 2 ( x ) ) ) begin{aligned} L = exp left( -frac{1}{K} left( y^{*1}H^{*1}(x)+y^{*2}H^{*2}(x) right) right) end{aligned} L=exp(−K1(y∗1H∗1(x)+y∗2H∗2(x)))
假设预测分类 = 真实分类 = 1,
| 1 1 1 | 2 2 2 | |
|---|---|---|
| H t k ( x i ) H_t^k(x_i) Htk(xi) | 0.7 0.7 0.7 | 0.3 0.3 0.3 |
| H ∗ ( x ) H^*(x) H∗(x) | 1 1 1 | − 1 2 − 1 -frac{1}{2-1} −2−11 |
| y ∗ boldsymbol{y^*} y∗ | 1 1 1 | − 1 2 − 1 -frac{1}{2-1} −2−11 |
− 1 K ( y ∗ 1 H ∗ 1 ( x ) + y ∗ 2 H ∗ 2 ( x ) ) = − 1 2 ( 1 ∗ 1 + − 1 2 − 1 ∗ − 1 2 − 1 ) = − 1 2 ( 1 + 1 ) = − 1 begin{aligned} -frac{1}{K}&left( y^{*1}H^{*1}(x)+y^{*2}H^{*2}(x) right)\ &= -frac{1}{2} left( 1 * 1 + frac{-1}{2-1} * frac{-1}{2-1} right)\ &= -frac{1}{2} left( 1 + 1 right)\ &= -1 end{aligned} −K1(y∗1H∗1(x)+y∗2H∗2(x))=−21(1∗1+2−1−1∗2−1−1)=−21(1+1)=−1
二分类指数损失,y=1,由于预测正确,所以 H ∗ ( x ) H^*(x) H∗(x) = 1
− y H ∗ ( x ) = − ( 1 ∗ 1 ) = − 1 begin{aligned} -y&H^*(x)\ & = -(1 * 1)\ & = -1 end{aligned} −yH∗(x)=−(1∗1)=−1
在多分类算法当中,我们常常求解类似于 y ∗ boldsymbol{y^*} y∗或 H ∗ ( x ) boldsymbol{H^*(x)} H∗(x)的向量,比如在softmax函数中,当预测值或真实值不等于 k k k时,我们赋予的向量值为0,而不是 − 1 K − 1 -frac{1}{K-1} −K−11。
在实践中,无论是SAMME还是SAMME.R,我们都无法改变使用的损失函数,因此参数中没有为我们提供相应的选择
- loss
在AdaBoost回归当中,能够使用的算法是唯一的,即AdaBoost.R2,在R2算法下,可以选择三种损失函数,分别是"linear"(线性),“square”(平方),“exponential”(指数)。
在算法AdaBoost.R2当中,三种损失函数如下定义:
首先:
D
=
s
u
p
∣
H
(
x
i
)
−
y
i
∣
,
i
=
1
,
2
,
.
.
.
,
N
D = sup|H(x_i) - y_i|, i = 1,2,...,N
D=sup∣H(xi)−yi∣,i=1,2,...,N
其中 y i y_i yi为真实标签, H ( x i ) H(x_i) H(xi)为预测标签,sup表示“取最大值”,但它与直接写作max的函数的区别在于,max中的元素已是固定的数值,而sup中的元素可以是一个表达式、并让该表达式在i的备选值中循环。上述式子表示,取出1~N号样本中真实值与预测值差距最大的那一组差异来作为D的值。
R2算法线性损失——
L i = ∣ H ( x i ) − y i ∣ D L_i = frac{|H(x_i) - y_i|}{D} Li=D∣H(xi)−yi∣
R2算法平方损失——
L i = ∣ H ( x i ) − y i ∣ 2 D 2 L_i = frac{|H(x_i) - y_i|^2}{D^2} Li=D2∣H(xi)−yi∣2
R2算法指数损失——
L i = 1 − e x p ( − ∣ H ( x i ) − y i ∣ D ) L_i = 1 - exp left( frac{-|H(x_i) - y_i|}{D} right) Li=1−exp(D−∣H(xi)−yi∣)
不难发现,其实线性损失就是我们常说的MAE的变体,平方损失就是MSE的变体,而指数损失也与分类中的指数损失高度相似。在R2算法当中,这些损失函数特殊的地方在于分母D。由于D是所有样本中真实值与预测值差异最大的那一组差异,因此任意样本的 L i L_i Li在上述线性与平方损失定义下,取值范围都只有[0,1](当真实值=预测值时,取值为0,当真实值-预测值=D时,取值为1)。
特别的,对于指数损失来说,自变量的部分是在[0,1]中取值,因此 e − x e^{-x} e−x的在该定义域上的值域也为[0,1],因此 1 − e − x 1-e^{-x} 1−e−x的值域为[0,1]。
在AdaBoost的参数空间中,n_estimators与learning_rate是最为重要的两个参数。当我们在进行超参数调整时,注意对这两个参数的组合进行同时调整即可。
from sklearn.ensemble import AdaBoostClassifier as ABC from sklearn.ensemble import AdaBoostRegressor as ABR from sklearn.tree import DecisionTreeClassifier as DTC from sklearn.tree import DecisionTreeRegressor as DTR from sklearn.datasets import load_digits #用于分类的数据 data_c = load_digits() X_c = data_c.data y_c = data_c.target # 自建弱评估器 base_estimator = DTC(max_depth=10,max_features=30) clf = ABC(base_estimator = base_estimator, n_estimators=3).fit(X_c,y_c) clf.base_estimator_ clf.estimators_ #多分类预测输出的概率结果,取前5个样本 pd.DataFrame(clf.predict_proba(X_c)).iloc[:5,:] # 每一个样本的K类个概率中,最大概率所对应的类别就是预测类别 np.argmax(pd.DataFrame(clf.predict_proba(X_c)).iloc[0,:])



