文章目录
1. 概念
1.1 League of Legends 还是 AdaBoost?
LOL打团的思想是这样的:对面开团时,五个英雄各自有各自的作用,坦克要够肉,ADC要足够猥琐输出……所以,类型越全面,对面越容易团灭。
其实AdaBoost模型和LOL打团是一样一样的。面对数据集,每个基学习器(英雄)都有各自关注的部分,覆盖的越全面,学习效果越好。而且,有一定的先后顺序:先控再输出。。。
1.2 真正的AdaBoost
1.2.1 样本空间
假定给定一个二分类的训练数据集 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x N , y N ) } T=\{(\boldsymbol{x_1}, y_1),(\boldsymbol{x_2}, y_2),...,(\boldsymbol{x_N}, y_N)\} T={(x1,y1),(x2,y2),...,(xN,yN)},其中 x i \boldsymbol{x_i} xi是一个 1 ∗ d 1*d 1∗d维的向量,标签 y i ∈ Y = { − 1 , 1 } y_i \in Y=\{-1, 1\} yi∈Y={−1,1}。
1.2.2 表达式
F
T
(
x
)
=
∑
t
=
1
T
α
t
f
t
(
x
)
(1.1)
\begin{aligned} F_T(\boldsymbol{x})=\sum_{t=1}^{T} \alpha_tf_t(\boldsymbol{x})\tag{1.1} \end{aligned}
FT(x)=t=1∑Tαtft(x)(1.1)
在公式
(
1.1
)
(1.1)
(1.1)中,
f
t
(
x
)
f_t(\boldsymbol{x})
ft(x)是弱学习器的计算结果,
f
t
f_t
ft是弱学习器模型,
T
T
T是弱学习器的数量。
在每迭代过程中,每次迭代都会选择一个弱学习器,并且给其分配一个权重
α
t
\alpha_t
αt,这样的话,对于第
i
i
i个样本而言
(
i
≤
N
)
(i\leq N)
(i≤N),整个AdaBoost模型在第
t
t
t轮时的训练误差
E
t
E_t
Et可以表达为:
E
t
=
∑
i
=
1
N
E
[
F
t
−
1
(
x
i
)
+
α
t
f
t
(
x
i
)
]
(1.2)
\begin{aligned} E_t=\sum_{i=1}^{N}E[F_{t-1}(\boldsymbol{x_i})+\alpha_t f_t(\boldsymbol{x_i})]\tag{1.2} \end{aligned}
Et=i=1∑NE[Ft−1(xi)+αtft(xi)](1.2)
在公式
(
1.2
)
(1.2)
(1.2)中
F
t
−
1
(
x
i
)
F_{t-1}(\boldsymbol{x_i})
Ft−1(xi)是根据之前
t
−
1
t-1
t−1次迭代得到的模型,
f
t
(
x
i
)
f_t(\boldsymbol{x_i})
ft(xi)是本轮学习的弱学习器,在学习完成之后会添加到最终模型中。
1.2.3 AdaBoost的损失函数
函数表达式:
L
(
y
,
f
(
x
)
)
=
e
[
−
y
f
(
x
)
]
(1.3)
L(y, f(x))=e^{[-yf(x)]} \tag{1.3}
L(y,f(x))=e[−yf(x)](1.3)
这里多说一句:为什么损失函数是公式(1.3)的样子,而不是我们常见的
L
(
y
,
f
(
x
)
)
=
1
2
(
y
−
f
(
x
)
)
2
L(y, f(x))=\frac{1}{2}(y-f(x))^2
L(y,f(x))=21(y−f(x))2?
解答:在AdaBoost算法中,我们所关心的只是每一个弱分类器结果的符号,而真正影响模型最后输出结果的是那些离群值所对应的权重。
1.2.4 AdaBoost 的前生今世
假设经过了
m
−
1
m-1
m−1代之后(
m
<
T
m<T
m<T),对于第
i
i
i个样本而言,公示
(
1.1
)
(1.1)
(1.1)可以表示为
F
m
−
1
(
x
i
)
=
α
1
f
1
(
x
i
)
+
α
2
f
2
(
x
i
)
+
.
.
.
+
α
m
−
1
f
m
−
1
(
x
i
)
(1.4)
\begin{aligned} F_{m-1}(\boldsymbol{x_i})=&\alpha_1f_1(\boldsymbol{x_i})+\alpha_2f_2(\boldsymbol{x_i})+...+\alpha_{m-1}f_{m-1}(\boldsymbol{x_i}) \tag{1.4} \end{aligned}
Fm−1(xi)=α1f1(xi)+α2f2(xi)+...+αm−1fm−1(xi)(1.4)
根据公式
(
1.3
)
(1.3)
(1.3)有
F
m
(
x
i
)
=
F
m
−
1
(
x
i
)
+
α
m
f
m
(
x
i
)
(1.5)
\begin{aligned} F_{m}(\boldsymbol{x_i})=F_{m-1}(\boldsymbol{x_i})+\alpha_{m}f_{m}(\boldsymbol{x_i}) \tag{1.5} \end{aligned}
Fm(xi)=Fm−1(xi)+αmfm(xi)(1.5)
当损失函数为Exponential loss的时候:
E
=
∑
i
=
1
N
e
−
y
i
F
m
(
x
i
)
=
∑
i
=
1
N
e
−
y
i
(
F
m
−
1
(
x
i
)
+
α
m
f
m
(
x
i
)
)
=
∑
i
=
1
N
e
−
y
i
F
m
−
1
(
x
i
)
−
y
i
α
m
f
m
(
x
i
)
=
∑
i
=
1
N
e
−
y
i
F
m
−
1
(
x
i
)
e
−
y
i
α
m
f
m
(
x
i
)
(1.6)
\begin{aligned} E=&\sum_{i=1}^{N}e^{-y_iF_{m}(\boldsymbol{x_i})}\\ =&\sum_{i=1}^{N}e^{-y_i(F_{m-1}(\boldsymbol{x_i})+\alpha_{m}f_{m}(\boldsymbol{x_i}))}\\ =&\sum_{i=1}^{N}e^{-y_iF_{m-1}(\boldsymbol{x_i})-y_i\alpha_{m}f_{m}(\boldsymbol{x_i})}\\ =&\sum_{i=1}^{N}e^{-y_iF_{m-1}(\boldsymbol{x_i})}e^{-y_i \alpha_{m}f_{m}(\boldsymbol{x_i})}\tag{1.6} \end{aligned}
E====i=1∑Ne−yiFm(xi)i=1∑Ne−yi(Fm−1(xi)+αmfm(xi))i=1∑Ne−yiFm−1(xi)−yiαmfm(xi)i=1∑Ne−yiFm−1(xi)e−yiαmfm(xi)(1.6)
公式
(
1.6
)
(1.6)
(1.6)中,由于
e
−
y
i
F
m
−
1
(
x
i
)
e^{-y_iF_{m-1}(\boldsymbol{x_i})}
e−yiFm−1(xi)是一个定值,记为
w
i
w_i
wi。所以,假设
w
i
(
1
)
=
1
w_i^{(1)}=1
wi(1)=1,且当
m
>
1
m>1
m>1时,有
w
i
(
m
)
=
e
−
y
i
F
m
−
1
(
x
i
)
w_i^{(m)}=e^{-y_iF_{m-1}(\boldsymbol{x_i})}
wi(m)=e−yiFm−1(xi),则公式
(
1.6
)
(1.6)
(1.6)可以记为:
E
=
∑
i
=
1
N
w
i
(
m
)
e
−
y
i
α
m
f
m
(
x
i
)
(1.7)
\begin{aligned} E=&\sum_{i=1}^{N}w_i^{(m)}e^{-y_i\alpha_{m}f_{m}(\boldsymbol{x_i})}\tag{1.7} \end{aligned}
E=i=1∑Nwi(m)e−yiαmfm(xi)(1.7)
如果在样本空间中,AdaBoost模型能够正确分类的情况下,有:
y
i
f
m
(
x
i
)
=
1
y_if_{m}(\boldsymbol{x_i})=1
yifm(xi)=1;当分类错误时:
y
i
f
m
(
x
i
)
=
−
1
y_if_{m}(\boldsymbol{x_i})=-1
yifm(xi)=−1。因此,公式
(
1.7
)
(1.7)
(1.7)可以写为:
E
=
∑
y
i
=
f
m
(
x
i
)
N
w
i
(
m
)
e
−
α
m
+
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
e
α
m
=
∑
y
i
=
f
m
(
x
i
)
N
w
i
(
m
)
e
−
α
m
+
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
e
α
m
−
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
e
−
α
m
+
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
e
−
α
m
=
∑
i
=
1
N
w
i
(
m
)
e
−
α
m
+
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
e
α
m
−
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
e
−
α
m
=
∑
i
=
1
N
w
i
(
m
)
e
−
α
m
+
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
(
e
α
m
−
e
−
α
m
)
(1.8)
\begin{aligned} E=&\sum_{y_i=f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)} e^{-\alpha_{m}}+ \sum_{y_i \neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)} e^{\alpha_{m}} \\ =& \sum_{y_i = f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}e^{-\alpha_{m}}+ \sum_{y_i \neq f_{m}(\boldsymbol{x_i})}^{N} w_i^{(m)}e^{\alpha_{m}}- \sum_{y_i \neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}e^{-\alpha_{m}}+ \sum_{y_i \neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}e^{-\alpha_{m}}\\ \\ =&\sum_{i=1}^{N} w_i^{(m)} e^{- \alpha_{m}}+ \sum_{y_i \neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)} e^{\alpha_{m}}- \sum_{y_i \neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)} e^{-\alpha_{m}} \\ \\ =&\sum_{i=1}^{N}w_i^{(m)} e^{-\alpha_{m}}+ \sum_{y_i \neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}(e^{\alpha_{m}}-e^{-\alpha_{m}})\tag{1.8} \end{aligned}
E====yi=fm(xi)∑Nwi(m)e−αm+yi=fm(xi)∑Nwi(m)eαmyi=fm(xi)∑Nwi(m)e−αm+yi=fm(xi)∑Nwi(m)eαm−yi=fm(xi)∑Nwi(m)e−αm+yi=fm(xi)∑Nwi(m)e−αmi=1∑Nwi(m)e−αm+yi=fm(xi)∑Nwi(m)eαm−yi=fm(xi)∑Nwi(m)e−αmi=1∑Nwi(m)e−αm+yi=fm(xi)∑Nwi(m)(eαm−e−αm)(1.8)
在公式
(
1.8
)
(1.8)
(1.8)中,要使AdaBoost模型分类尽可能的正确,即要找到一个
α
m
\alpha_{m}
αm使得
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
\sum_{y_i \neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}
∑yi=fm(xi)Nwi(m)项尽可能的小(假设
α
m
>
0
\alpha_{m}>0
αm>0),因此对
α
m
\alpha_{m}
αm求导有:
∂
E
/
∂
α
m
=
−
∑
i
=
1
N
w
i
(
m
)
e
−
α
m
+
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
(
e
α
m
+
e
−
α
m
)
(1.9)
\begin{aligned} \partial{E}/\partial{\alpha_{m}}=&-\sum_{i=1}^{N}w_i^{(m)} e^{-\alpha_{m}}+ \sum_{y_i \neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}(e^{\alpha_{m}}+e^{-\alpha_{m}})\tag{1.9} \end{aligned}
∂E/∂αm=−i=1∑Nwi(m)e−αm+yi=fm(xi)∑Nwi(m)(eαm+e−αm)(1.9)
令公式
(
1.9
)
(1.9)
(1.9)为
0
0
0:
0
=
−
∑
i
=
1
N
w
i
(
m
)
e
−
α
m
+
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
(
e
α
m
+
e
−
α
m
)
e
−
α
m
∑
y
i
=
f
m
(
x
i
)
N
w
i
(
m
)
=
e
α
m
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
(1.10)
\begin{aligned} 0=-\sum_{i=1}^{N}w_i^{(m)} e^{-\alpha_{m}}+ \sum_{y_i \neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}(e^{\alpha_{m}}+e^{-\alpha_{m}})\\ e^{-\alpha_{m}} \sum_{y_i=f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)} = e^{\alpha_{m}} \sum_{y_i\neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}\tag{1.10} \end{aligned}
0=−i=1∑Nwi(m)e−αm+yi=fm(xi)∑Nwi(m)(eαm+e−αm)e−αmyi=fm(xi)∑Nwi(m)=eαmyi=fm(xi)∑Nwi(m)(1.10)
由于
e
−
α
m
e^{-\alpha_{m}}
e−αm与
i
i
i无关,公式
(
1.10
)
(1.10)
(1.10)左右同时取对数:
−
α
m
+
I
n
(
∑
y
i
=
f
m
(
x
i
)
N
w
i
(
m
)
)
=
α
m
+
I
n
(
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
)
2
α
m
=
I
n
(
∑
y
i
=
f
m
(
x
i
)
N
w
i
(
m
)
)
−
I
n
(
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
)
α
m
=
1
2
I
n
(
∑
y
i
=
f
m
(
x
i
)
N
w
i
(
m
)
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
)
(1.11)
\begin{aligned}\\ -\alpha_{m}+In(\sum_{y_i=f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}) =& \alpha_{m}+In(\sum_{y_i\neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)})\\ 2\alpha_{m} =& In(\sum_{y_i=f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}) - In(\sum_{y_i\neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}) \\ \alpha_{m} =& \frac{1}{2} In(\frac{\sum_{y_i=f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}}{\sum_{y_i\neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}}) \tag{1.11} \end{aligned}
−αm+In(yi=fm(xi)∑Nwi(m))=2αm=αm=αm+In(yi=fm(xi)∑Nwi(m))In(yi=fm(xi)∑Nwi(m))−In(yi=fm(xi)∑Nwi(m))21In(∑yi=fm(xi)Nwi(m)∑yi=fm(xi)Nwi(m))(1.11)
又因
m
m
m次之后,错误率
ε
m
\varepsilon_m
εm为:
ε
m
=
∑
y
i
≠
f
m
(
x
i
)
N
w
i
(
m
)
∑
i
=
1
N
w
i
(
m
)
(1.12)
\begin{aligned} \varepsilon_m=\frac{\sum_{y_i \neq f_{m}(\boldsymbol{x_i})}^{N}w_i^{(m)}}{\sum_{i=1}^{N}w_i^{(m)}} \tag{1.12} \end{aligned}
εm=∑i=1Nwi(m)∑yi=fm(xi)Nwi(m)(1.12)
所以公式
(
1.11
)
(1.11)
(1.11)为
α
m
=
1
2
I
n
(
1
−
ε
m
ε
m
)
(1.11)
\begin{aligned}\\ \alpha_{m} =& \frac{1}{2} In(\frac{1-\varepsilon_m}{\varepsilon_m}) \tag{1.11} \end{aligned}
αm=21In(εm1−εm)(1.11)
最终,通过更新
F
m
−
1
F_{m-1}
Fm−1为
F
m
(
x
i
)
=
F
m
−
1
(
x
i
)
+
α
m
f
m
(
x
i
)
F_{m}(\boldsymbol{x_i})=F_{m-1}(\boldsymbol{x_i})+\alpha_mf_m(\boldsymbol{x_i})
Fm(xi)=Fm−1(xi)+αmfm(xi)即可提升AdaBoost模型的性能。
1.2.5 基本流程
2. AdaBoost的另一种理解
3. 提升树(Boosting Tree)
其实提升树并没有那么高大上,就是采用了决策树作为上述AdaBoost模型中的弱学习器,而且严格意义上来说,是决策树桩,下面通过一个栗子来说明,基于分类的提升树是怎么构建出来的。
3.1 数据
假定我们有数据集如图1所示。目标:用boosting tree去预测是否有心脏病(绿色列),三个特征(Chest Pain, Blocked Arteries, Patient Weight)。
- 给每一个样本同样的权重,表示他们一开始对于分类器是同等重要的。
w = 1 d a t a s i z e = 1 8 w=\frac{1}{data_size} = \frac{1}{8} w=datasize1=81 - 计算不同特征值下正确与错误分类的数量,并计算其基尼系数。
由于特征Patient Weight的基尼系数最小,因此,选择该特征所构成的决策树桩作为第一个分类器。
以特征Patient Weight作为决策树桩时,在整个训练集上仅
1
1
1个错误,即
ε
1
=
1
8
\varepsilon_1=\frac{1}{8}
ε1=81。根据公式
(
1.11
)
(1.11)
(1.11),可以计算出该分类器的权重为:
α
1
=
1
2
I
n
(
1
−
ε
1
ε
1
)
=
1
2
I
n
(
1
−
1
8
1
8
)
=
0.97
\begin{aligned}\\ \alpha_{1} =& \frac{1}{2} In(\frac{1-\varepsilon_1}{\varepsilon_1})\\ =& \frac{1}{2} In(\frac{1-\frac{1}{8}}{\frac{1}{8}}) \\ =& 0.97 \end{aligned}
α1===21In(ε11−ε1)21In(811−81)0.97
- 通过权重重新调整数据分布。
-
对于错误的样本,增加权重。
w 3 = 1 8 ∗ e − 0.97 ∗ ( 1 ∗ − 1 ) = 0.33 w_3 = \frac{1}{8} * e^{-0.97*(1*-1)}=0.33 w3=81∗e−0.97∗(1∗−1)=0.33 -
对于分类正确的样本,减少权重。
w 0 = w 1 = w 2 = 1 8 ∗ e − 0.97 ∗ ( 1 ∗ 1 ) = 0.05 w_0=w_1=w_2=\frac{1}{8} * e^{-0.97*(1*1)}=0.05 w0=w1=w2=81∗e−0.97∗(1∗1)=0.05
w 4 = w 5 = w 6 = w 7 = 1 8 ∗ e − 0.97 ∗ ( − 1 ∗ − 1 ) = 0.05 w_4=w_5=w_6=w_7=\frac{1}{8} * e^{-0.97*(-1*-1)}=0.05 w4=w5=w6=w7=81∗e−0.97∗(−1∗−1)=0.05 -
正则化权重.
w i = w i ∑ j = 0 7 w j = w i 0.68 w_i=\frac{w_i}{\sum_{j=0}^{7}w_j}=\frac{w_i}{0.68} wi=∑j=07wjwi=0.68wi
- 创建新的数据分布(要与原数据具有同样的shape)
此时,将图3.5中的数据当成概率分布。随机选择一个 ( 0 , 1 ) (0,1) (0,1)内的数字 n n n:
- 若 n 1 ∈ ( 0 , 0.07 ] n_1 \in (0, 0.07] n1∈(0,0.07],则将第0条数据(Yes, Yes, 205, Yes)添加进新数据集;
- 若 n ∈ ( 0.07 , 0.14 ] n \in (0.07, 0.14] n∈(0.07,0.14],则将第2条数据(No, Yes, 180, Yes)添加进新数据集;
- 若
n
∈
(
0.21
,
0.7
]
n \in (0.21, 0.7]
n∈(0.21,0.7],则将第2条数据(Yes, Yes, 167, Yes)添加进新数据集;
… 以此类推
很明显,被第一个分类器分错的数据很入选新数据集的概率极大,可能有多条。假设新数据集是这样的:
跳转步骤1 。直到模型中有指定数量的分类器后结束。
4. 代码
class AdaBoost(object):
def __init__(self, n_estimator, weaker_learner, column_type):
'''
AdaBoost 模型初始化
:param n_estimator: 选取n_estimator个弱学习器
'''
# 弱学习器的数量
self.n_estimator = n_estimator
# 每一列数据的类型(连续/离散)
self.column_type = column_type
# 初始化每个学习器权重
self.alpha = [1] * n_estimator
# 初始弱学习器数组
self.weaker_learners = []
# 初始化样本数据集大小以及特征数量
self.data_size, self.feature_size = 0, 0
# 特征的索引值
self.feature_indices = []
# 初始化弱学习器
self.weaker_learner = weaker_learner
# 初始化训练集的权值分布
self.w = None
def __initArgs__(self, _X, _Y):
'''
相关参数初始化
:param _X: 训练集特征值
:param _Y: 训练集标签值
:return:
'''
self.train_x = _X
self.train_y = _Y
self.data_size, self.feature_size = _X.shape
self.feature_indices = [_ for _ in range(self.feature_size)]
def getErrorRate(self, true_y, fake_y):
'''
计算第ith_estimator个弱学习器的误差
:param fake_y: 弱学习器的编号
:return: 弱学习器的错误率
'''
aggErrors = np.multiply(np.mat(true_y) != np.mat(fake_y), np.ones(fake_y.shape))
return aggErrors.sum() / true_y.shape[0]
def getAlpha(self, error_rate):
'''
计算第ith_estimator个弱学习器的权重
:param error_rate: 错误率
:return: 弱学习器对应的权重
'''
return 0.5 * np.log((1-error_rate)/error_rate)
def fit(self, _X, _Y):
'''
AdaBoost 模型训练
:param _X: 特征值
:param _Y: 标签值
:return:
'''
self.__initArgs__(_X, _Y)
for ith_estimator in range(self.n_estimator):
print('%d\'s estimator:' % ith_estimator)
# 初始化分布
self.w = 1 / self.data_size * np.ones((self.data_size, 1))
# 新建一个弱学习器
# 寻找最优的划分节点
weaker_learner = self.weaker_learner(ith_estimator, self.column_type)
weaker_learner.fit(_X, _Y)
weaker_learner_result = weaker_learner.predict(_X)
self.weaker_learners.append((weaker_learner.__root__.feature_index, weaker_learner))
# 计算错误率
error_rate = self.getErrorRate(self.train_y, weaker_learner_result)
print('error_rate:', error_rate)
# 计算该弱学习器的权重
ith_alpha = self.getAlpha(error_rate)
print('alpha:', ith_alpha)
self.alpha[ith_estimator] = ith_alpha
print(self.train_y)
print(weaker_learner_result)
# 更新w
w_tmp = - ith_alpha * np.multiply(self.train_y, weaker_learner_result)
self.w = np.multiply(self.w, np.exp(w_tmp))
print('update weights:', self.w)
# 规范化w
self.w /= self.w.sum()
print('normal weights:', self.w)
# 如果错误率比随机猜还差,那就停止
if error_rate > 0.5:
break
else:
_X, _Y = self.resampleData()
print('resample data')
print(_X)
print(_Y)
print('train done')
def resampleData(self):
'''
数据重采样,先计算每个样本需要被抽取的次数,
然后列索引按照抽取次数从大到小排序(注意是列)
:return:
'''
# 确定每个样本需要抽取的次数
nums = list(np.multiply(self.w.T[0], self.data_size))
# 将权重的索引按 权重的大小排序(从大到小)
idx = list(np.argsort(self.w.T[0]))
idx.reverse()
new_index = []
for id in idx:
num_arr = (int(nums[id]) + 1) * [id]
new_index.extend(num_arr)
if len(new_index) == self.data_size:
break
return self.train_x[new_index], self.train_y[new_index]
def predict(self, X):
'''
预测
:param x: 1*d 维的特征值
:return: 预测结果
'''
print('predict')
result = []
for x in X:
res = 0
for index, weaker_learner in enumerate(self.weaker_learners):
res += self.alpha[index] * weaker_learner[1].predict(
np.array([x])
)
result.append(1 if res > 0 else -1)
return np.array([result]).T
5. 小结
机器学习中最大的问题在于要面临数据集中维度灾难的问题,一般来说,减少了特征数量之后,虽然计算速度有所提升,但是鬼知道你去掉特征之后模型拟合优度有没有下降。AdaBoost模型不同于SVM和神经网络这两大算法,在AdaBoost模型中,你只要选择你认为有用的特征就好了,只要够小弟(基学习器)够多,啥样的模型都能画出来(当然这种过拟合的模型不要也罢)。
PS:用惯了pandas的行列索引之后,再使用Numpy简直就是个坑。