这篇文章将从以下四个方面讲解机器学习中的提升方法,完整的代码我整理在我的GitHub项目Machine-Learning-code中,可以自行前往下载,要是能star就更好了呀~
提升方法的基本思想
依旧从三个方面理解提升方法,然后从抽象到具体,给出提升方法的两个具体实例Adaboost方法和提升树,进一步加深对提升方法的理解
模型:提升方法的基本模型是加法模型,既可以用作分类也可以用作回归,取决于基本函数,模型可以用数学表达式表示为:
f
(
x
)
=
∑
m
=
1
M
β
m
b
(
x
;
γ
m
)
f(x)=\sum_{m=1}^{M}\beta_mb(x;\gamma_m)
f(x)=m=1∑Mβmb(x;γm)
其中
b
(
x
;
γ
m
)
b(x;\gamma_m)
b(x;γm)为基函数,
γ
m
\gamma_m
γm为基函数的参数,
β
m
\beta_m
βm为基函数的系数,通过上面的式子我们可以这样理解提升方法:原来的数据没有办法通过一个分类(回归)器解决,可以通过多个分类(回归)器各自解决一部分数据,然后通过不同的系数将这些分类(回归)器组合在一起,从而达到提升原来的分类(回归)器的效果
策略:提升方法的策略就是在给定损失函数的情况下,使经验风险最小化,即:
min
β
m
,
γ
m
∑
i
=
1
N
L
(
y
i
,
∑
m
=
1
M
β
m
b
(
x
i
;
γ
m
)
)
\min\limits_{\beta_m,\gamma_m}\sum_{i=1}^{N}L(y_i,\sum_{m=1}^{M}\beta_mb(x_i;\gamma_m))
βm,γmmini=1∑NL(yi,m=1∑Mβmb(xi;γm))
不同的损失函数和基函数组合就可以得到不同的提升方法,Adaboost方法和提升回归树方法就是损失函数分别取指数函数和平方损失函数得到的特例
算法:要求解上述最下化问题比较复杂,因为涉及到多个基函数的参数和系数,因此我们采用前向分步算法来求解上述问题,因为模型是加法模型,我们可以从前向后,每次只求解一个基函数和对应的系数,然后固定前面的基函数和系数求解后面的函数和系数,这样逐步逼近优化目标函数,这样在具体的第m步我们只需要求解下面的损失函数:
min
β
m
,
γ
m
∑
i
=
1
N
L
(
y
i
,
β
m
b
(
x
i
;
γ
m
)
)
\min\limits_{\beta_m,\gamma_m}\sum_{i=1}^{N}L(y_i,\beta_mb(x_i;\gamma_m))
βm,γmmini=1∑NL(yi,βmb(xi;γm))
Adaboost方法
我们取损失函数为对数损失函数:
L
(
y
,
f
(
x
)
)
=
exp
[
−
y
f
(
x
)
]
L(y,f(x))=\exp[-yf(x)]
L(y,f(x))=exp[−yf(x)]
基函数为分段函数:
b
(
x
;
γ
m
)
=
{
1
x
<
γ
m
−
1
x
>
γ
m
b(x;\gamma_m)=\left\{ \begin{array}{lr} 1&x<\gamma_m\\ -1&x>\gamma_m \end{array} \right.
b(x;γm)={1−1x<γmx>γm
就可以得到adaboost方法,运用前向分步算法求解损失函数最小化,整理后可以得到如下求解过程:
提升树
这里我们以提升回归树举例,首先写出提升算法的模型表示:
f
M
(
x
)
=
∑
m
=
1
M
T
(
x
;
Θ
m
)
f_M(x)=\sum_{m=1}^{M}T(x;\Theta_m)
fM(x)=m=1∑MT(x;Θm)
这里
T
(
x
;
θ
m
)
T(x;\theta_m)
T(x;θm)为决策树,我们取只有两个叶节点的简单决策树,然后损失函数取平方损失函数,利用前向分步算法,得到每一步需要优化的函数:
Θ
^
m
=
arg min
Θ
m
∑
i
=
1
N
L
(
y
i
,
f
m
−
1
(
x
i
)
+
T
(
x
i
;
Θ
m
)
)
=
arg min
Θ
m
∑
i
=
1
N
(
y
i
−
f
m
−
1
(
x
i
)
−
T
(
x
i
;
Θ
m
)
)
2
=
arg min
Θ
m
∑
i
=
1
N
(
r
i
−
T
(
x
i
;
Θ
m
)
)
2
\begin{aligned}\hat{\Theta}_m&=\argmin_{{\Theta}_m}\sum_{i=1}^{N}L(y_i,f_{m-1}(x_i)+T(x_i;\Theta_m))\\&=\argmin_{{\Theta}_m}\sum_{i=1}^{N}(y_i-f_{m-1}(x_i)-T(x_i;\Theta_m))^2\\&=\argmin_{{\Theta}_m}\sum_{i=1}^{N}(r_i-T(x_i;\Theta_m))^2 \end{aligned}
Θ^m=Θmargmini=1∑NL(yi,fm−1(xi)+T(xi;Θm))=Θmargmini=1∑N(yi−fm−1(xi)−T(xi;Θm))2=Θmargmini=1∑N(ri−T(xi;Θm))2
其中
f
m
−
1
(
x
)
=
∑
i
=
1
m
−
1
T
(
x
;
Θ
i
)
f_{m-1}(x)=\sum_{i=1}^{m-1}T(x;\Theta_i)
fm−1(x)=∑i=1m−1T(x;Θi),
r
i
=
y
i
−
f
m
−
1
(
x
i
)
r_i=y_i-f_{m-1}(x_i)
ri=yi−fm−1(xi)为当前模型预测的误差,所以对决策树
T
(
x
;
Θ
m
)
T(x;\Theta_m)
T(x;Θm)来说只需要拟合误差就可以了,于是可以得到下面的求解算法:
如何拟合误差呢,尝试不同的决策点,取使得平方损失最小的决策点即可
代码实现
下面主要给出训练过程的代码:
def train(self):
predict = np.zeros(self.n)
for i in range(self.treenum):
tree = {'e': 1}
for r in self.rule:
if r == 'lessOne':
L, H = 1, -1
else:
L, H = -1, 1
for d in self.div:
for i in range(self.m):
#计算误差率和Gm(x)的输出
Gx, e = self.cal_E_Gx(L, H, d, i)
if e < tree['e']:
tree['div'] = d
tree['rule'] = r
tree['feature'] = i
tree['e'] = e
tree['Gx'] = Gx
e = tree['e']
#计算alpha
alpha = 1 / 2 * np.log((1-e) / e)
tree['alpha'] = alpha
Gx = tree['Gx']
#更新权重
self.W = self.W * np.exp(-alpha * self.label * Gx)
self.W /= sum(self.W)
predict += alpha * Gx
self.trees.append(tree)
if sum((np.sign(predict) != self.label).astype('int')) == 0:
break
print('total tree num is {}'.format(len(self.trees)))
完整代码可以去我的GitHub项目Machine-Learning-code中下载,欢迎star~