【机器学习笔记】——Bagging、Boosting、Stacking(RF / Adaboost / Boosting Tree / GBM / GBDT / XGBoost / LightGBM)

目 录

集成学习

概念

  首先,让我们先来了解一下,什么是集成学习(Ensemble Learning,写作银桑,读作昂桑)。集成学习由训练数据构建一组基分类器,然后通过对每个基分类器的预测进行投票来进行分类,对每个个体学习器的预测进行(加权)平均来进行回归,有时也被称为多分类器系统、基于委员会的学习等。如果把单个分类器比作一个决策者的话,集成学习的方法就相当于多个决策者共同进行一项决策。严格来说,集成学习并不算是一种分类器,而是一种分类器结合的方法。

在这里插入图片描述

  • 集成学习将多个分类方法聚集在一起,以提高分类的准确率。通常一个集成分类器的分类性能会好于单个分类器

  对于二分类问题,假设基分类器的错误率为 ϵ \epsilon ϵ
P ( h i ( x ≠ y ) ) = ϵ P(h_i(\mathcal{x} \ne \mathcal{y})) = \epsilon P(hi(x̸=y))=ϵ

  通过投票我们得到集成学习的分类预测:
H ( x ) = s i g n ( ∑ i = 1 T h i ( x ) ) H(\mathcal{x}) = sign\left(\sum_{i = 1}^{T} h_i(\mathcal{x})\right) H(x)=sign(i=1Thi(x))

  假设分类器的错误率相互独立,则由Hoeffding不等式有:
P ( H ( x ≠ y ) ) = ∑ k = 0 ⌊ T / 2 ⌋ ( T k ) ( 1 − ϵ ) k ϵ T − k ≤ e x p ( − 1 2 T ( 1 − 2 ϵ ) 2 ) P(H(\mathcal{x} \ne \mathcal{y})) = \sum_{k = 0}^{\lfloor T/2 \rfloor} \dbinom{T}{k}(1 - \epsilon)^k \epsilon^{T - k} \le exp\left(-\frac{1}{2}T(1-2\epsilon)^2 \right) P(H(x̸=y))=k=0T/2(kT)(1ϵ)kϵTkexp(21T(12ϵ)2)

  即随着集成中基分类器数目 T T T增大,集成的错误率会指数级下降,最终趋于0。当然实际中个体学习器错误率独立的假设是不成立的

  • 集成学习的很多理论研究都是针对弱分类器(精度略高于50%)进行的,但在实践中往往会使用较强的分类器

  • 个体学习器要有一定的“准确性”,并且要有“多样性”。一般的,准确性很高之后,要增加多样性就需牺牲准确性。如何产生并结合“好而不同”的个体学习器,恰是集成学习研究的核心

  下面这个例子,图(a)中每个学习器只有67%的精度,但集成学习却达到了100%;图(b)中三个学习器完全一样,集成之后性能没有提高;图©中每个学习器只有33%的精度集成学习的效果更差。

在这里插入图片描述

思维导图

在这里插入图片描述

Bagging算法

概念

  Bagging算法(Bootstrap AGGregatING)是一种并行式集成算法。它基于自助采样法(Bootstrap sampling)采样出T个含有m个训练样本的采样集,然后基于每个采样集训练出一个基学习器,再将这些基学习器进行结合。

在这里插入图片描述

  算法的伪代码如下:

在这里插入图片描述

  从偏差-方差分解的角度看,降低一个估计的方差的方式是把多个估计平均起来,所以Bagging主要关注降低方差,因此它在不剪枝决策树、神经网络等易受样本扰动的学习器上效用更为明显。同时,Bagging并不能减小模型的偏差,所以应尽量选择偏差较小的基分类器,如未剪枝的决策树。

编程(分类)

  参考:https://github.com/vsmolyakov/experiments_with_python/blob/master/chp01/ensemble_methods.ipynb

  我们用iris数据集来看一下不同基分类器Bagging的效果

import itertools
import numpy as np

import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

from sklearn import datasets

from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier

from sklearn.ensemble import BaggingClassifier
from sklearn.model_selection import cross_val_score, train_test_split

from mlxtend.plotting import plot_learning_curves
from mlxtend.plotting import plot_decision_regions

np.random.seed(0)

  导入数据

iris = datasets.load_iris()
X, y = iris.data[:, 0:2], iris.target

X.shape, y.shape

((150, 2), (150,))

  设置基分类器和集成方法

# 配置基分类器的参数
clf1 = DecisionTreeClassifier(criterion='entropy', max_depth=1)    # 深度为1的决策树
clf2 = KNeighborsClassifier(n_neighbors=1)    # k=1的k近邻

# 每个Bagging有10个基分类器
bagging1 = BaggingClassifier(base_estimator=clf1, n_estimators=10, max_samples=0.8, max_features=0.8)
bagging2 = BaggingClassifier(base_estimator=clf2, n_estimators=10, max_samples=0.8, max_features=0.8)

  查看单个学习器和Bagging后的效果

label = ['Decision Tree(depth = 1)', 'K-NN(k = 1)', 'Bagging Tree', 'Bagging K-NN']
clf_list = [clf1, clf2, bagging1, bagging2]

fig = plt.figure(figsize=(10, 8))
gs = gridspec.GridSpec(2, 2)    # 创建 2x2 的画布
grid = itertools.product([0,1],repeat=2)    # 返回参数的笛卡尔积的元组,每个元素可以用 2 次

for clf, label, grd in zip(clf_list, label, grid):        
    scores = cross_val_score(clf, X, y, cv=3, scoring='accuracy')    # Array of scores of the estimator for each run of the cross validation.
    print("Accuracy: %.2f (+/- %.2f) [%s]" %(scores.mean(), scores.std(), label))
        
    clf.fit(X, y)
    ax = plt.subplot(gs[grd[0], grd[1]])
    fig = plot_decision_regions(X=X, y=y, clf=clf, legend=2)    # 绘制决策边界
    plt.title(label)

plt.show()

Accuracy: 0.63 (+/- 0.02) [Decision Tree(depth = 1)]
Accuracy: 0.70 (+/- 0.02) [K-NN(k = 1)]
Accuracy: 0.66 (+/- 0.02) [Bagging Tree]
Accuracy: 0.61 (+/- 0.02) [Bagging K-NN]

在这里插入图片描述

  可以发现决策树的集成有一定效果,而k近邻的效果反而变差了。这是因为k近邻是稳定学习器,不易受样本扰动影响。

  再来看看数据集的划分对训练结果的影响

#plot learning curves
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
    
plt.figure()
plot_learning_curves(X_train, y_train, X_test, y_test, bagging1, print_model=False, style='ggplot')
plt.show()

在这里插入图片描述

  虽然每次结果有较大的差异,但是我们还是能得到一些结论:对于给定的划分比例,模型在训练集上的错分率基本在30%上下,而在测试集上,当训练集较小时,模型在测试集上表现很差,当训练集比例逐渐增加时,模型在测试集上的表现慢慢变好,一般在训练集占到80%左右时,模型在训练集和测试集上都能取得较好的表现

  接下来我们看一下学习器的个数对bagging效果的影响

#Ensemble Size
num_est = np.concatenate(([1],np.arange(5,105,5)))
bg_clf_cv_mean = []
bg_clf_cv_std = []

for n_est in num_est:    
    bg_clf = BaggingClassifier(base_estimator=clf1, n_estimators=n_est, max_samples=0.8, max_features=0.8)
    scores = cross_val_score(bg_clf, X, y, cv=3, scoring='accuracy')
    bg_clf_cv_mean.append(scores.mean())
    bg_clf_cv_std.append(scores.std())
    

plt.figure()
# 绘制误差棒图,横轴为num_est,纵轴为scores.mean(),误差为scores.std()
(_, caps, _) = plt.errorbar(num_est, bg_clf_cv_mean, yerr=bg_clf_cv_std, c='blue', fmt='-o', capsize=5)
for cap in caps:
    cap.set_markeredgewidth(1)                                                           
plt.ylabel('Accuracy'); plt.xlabel('Ensemble Size'); plt.title('Bagging Tree Ensemble');
plt.show()

在这里插入图片描述

  基于交叉验证的结果,我们可以看到在基分类器数量达到20后,集成的效果不再有明显的提升

随机森林

  随机森林(Random Forest, RF)可以看成是改进的Bagging算法,它可以更好地解决决策树的过拟合问题。随机森林以CART树作为基分类器,对比决策树的Bagging,它有一个明显的特点——随机选择特征,对于普通的决策树,我们会在每个节点在当前的所有特征(假设有n个)中寻找最优特征,而随机森林的决策树会在每个节点在随机选取的特征集合(推荐 n r f = log ⁡ 2 n n_{rf} = \log_2 n nrf=log2n)中寻找最优特征。这样做的好处是如果训练集中的几个特征对输出的结果有很强的预测性,那么这些特征会被每个决策树所应用,这样会导致树之间具有相关性,这样并不会减小模型的方差,但同时随机森林会不可避免的增加偏差。

  RF的主要优点有:

  1. 训练可以高度并行化,对于大数据时代的大样本训练速度有优势。个人觉得这是的最主要的优点。

  2. 由于可以随机选择决策树节点划分特征,这样在样本特征维度很高的时候,仍然能高效的训练模型。

  3. 在训练后,可以给出各个特征对于输出的重要性

  4. 由于采用了随机采样,训练出的模型的方差小,泛化能力强。

  5. 相对于Boosting系列的Adaboost和GBDT, RF实现比较简单。

  6. 对部分特征缺失不敏感。

  RF的主要缺点有:

  1. 在某些噪音比较大的样本集上,RF模型容易陷入过拟合。

  2. 取值划分比较多的特征容易对RF的决策产生更大的影响,从而影响拟合的模型的效果。

扩展

  RF还有很多变种,其目的都是为了进一步降低方差。

Extremely randomized Trees

  Extremely randomized Trees(以下简称Extra Trees)放弃了Boostrap sampling的方式,而选择使用原始数据集,而且在特征选择时更加暴力的随机选择一个特征直接作为最优特征

*Totally Random Trees Embedding

  参考:http://www.cnblogs.com/pinard/p/6156009.html

  Totally Random Trees Embedding(以下简称 TRTE)是一种非监督学习的数据转化方法。它将低维的数据集映射到高维,从而让映射到高维的数据更好的运用于分类回归模型。我们知道,在支持向量机中运用了核方法来将低维的数据集映射到高维,此处TRTE提供了另外一种方法。

  TRTE在数据转化的过程也使用了类似于RF的方法,建立T个决策树来拟合数据。当决策树建立完毕以后,数据集里的每个数据在T个决策树中叶子节点的位置也定下来了。比如我们有3颗决策树,每个决策树有5个叶子节点,某个数据特征xx划分到第一个决策树的第2个叶子节点,第二个决策树的第3个叶子节点,第三个决策树的第5个叶子节点。则x映射后的特征编码为(0,1,0,0,0, 0,0,1,0,0, 0,0,0,0,1), 有15维的高维特征。这里特征维度之间加上空格是为了强调三颗决策树各自的子编码。

  映射到高维特征后,可以继续使用监督学习的各种分类回归算法了。

*Isolation Forest

  Isolation Forest(以下简称IForest)是一种异常点检测的方法。它也使用了类似于RF的方法来检测异常点。

  对于在T个决策树的样本集,IForest也会对训练集进行随机采样,但是采样个数不需要和RF一样,对于RF,需要采样到采样集样本个数等于训练集个数。但是IForest不需要采样这么多,一般来说,采样个数要远远小于训练集个数?为什么呢?因为我们的目的是异常点检测,只需要部分的样本我们一般就可以将异常点区别出来了。

  对于每一个决策树的建立, IForest采用随机选择一个划分特征,对划分特征随机选择一个划分阈值。这点也和RF不同。

  另外,IForest一般会选择一个比较小的最大决策树深度max_depth,原因同样本采集,用少量的异常点检测一般不需要这么大规模的决策树。

  对于异常点的判断,则是将测试样本点 x x x拟合到 T T T颗决策树。计算在每颗决策树上该样本的叶子节点的深度 h t ( x ) h_t(x) ht(x),从而可以计算出平均高度 h ( x ) h(x) h(x)。此时我们用下面的公式计算样本点xx的异常概率:

s ( x , m ) = 2 − h ( x ) c ( m ) s(x,m)=2^{−\frac{h(x)}{c(m)}} s(x,m)=2c(m)h(x)

  其中,m为样本个数。 c ( m ) c(m) c(m)的表达式为:

c ( m ) = 2 ln ⁡ ( m − 1 ) + ξ − 2 m − 1 m c(m)=2\ln (m−1)+\xi−2\frac{m−1}{m} c(m)=2ln(m1)+ξ2mm1

ξ \xi ξ为欧拉常数, s ( x , m ) s(x,m) s(x,m)的取值范围是 [ 0 , 1 ] [0,1] [0,1],取值越接近于1,则是异常点的概率也越大。

编程(分类)

import time

# DecisionTree
clf3 = DecisionTreeClassifier(criterion='entropy', max_depth=2)

# Tree Bagging
tree_bagging = BaggingClassifier(base_estimator=clf3, n_estimators=100)

# Random Forest
random_forest = RandomForestClassifier(n_estimators=100, criterion='entropy', max_depth = 2)

label = ['Decision Tree', 'Tree Bagging', 'Random Forest']
clf_list = [clf3, tree_bagging, random_forest]

fig = plt.figure(figsize=(15, 4))
gs = gridspec.GridSpec(1, 3)
grid = itertools.product([0], [0, 1, 2])

for clf, label, grd in zip(clf_list, label, grid):
    b = time.time()
    scores = cross_val_score(clf, X, y, cv=3, scoring='accuracy')
    runtime = time.time() - b
    print("Accuracy: %.2f (+/- %.2f) [%s] Runtime: %.2f s" %(scores.mean(), scores.std(), label, runtime))
        
    clf.fit(X, y)
    ax = plt.subplot(gs[grd[0], grd[1]])
    fig = plot_decision_regions(X=X, y=y, clf=clf, legend=2)
    plt.title(label)

plt.show()

Accuracy: 0.63 (+/- 0.04) [Decision Tree] Runtime: 0.01 s
Accuracy: 0.77 (+/- 0.03) [Tree Bagging] Runtime: 0.40 s
Accuracy: 0.76 (+/- 0.04) [Random Forest] Runtime: 0.36 s

在这里插入图片描述

  从结果可以看到随机森林的运行速度比Tree Bagging要快一点,这是因为在选择最优特征时,随机森林并没有从全部特征中进行选择

rf_label = ['DecisionTree','1 Trees','5 Trees','10 Trees','20 Trees','100 Trees']

random_forest1 = RandomForestClassifier(n_estimators=1, criterion='entropy', max_depth = 2)
random_forest5 = RandomForestClassifier(n_estimators=5, criterion='entropy', max_depth = 2)
random_forest10 = RandomForestClassifier(n_estimators=10, criterion='entropy', max_depth = 2)
random_forest20 = RandomForestClassifier(n_estimators=20, criterion='entropy', max_depth = 2)
random_forest100 = RandomForestClassifier(n_estimators=100, criterion='entropy', max_depth = 2)

clf_list = [clf3, random_forest1, random_forest5, random_forest10, random_forest20, random_forest100]

fig = plt.figure(figsize=(15, 8))
gs = gridspec.GridSpec(2, 3)
grid = itertools.product([0, 1], [0, 1, 2])

for clf, label, grd in zip(clf_list, rf_label, grid):
    scores = cross_val_score(clf, X, y, cv=3, scoring='accuracy')
    print("Accuracy: %.2f (+/- %.2f) [%s]" %(scores.mean(), scores.std(), label))
        
    clf.fit(X, y)
    ax = plt.subplot(gs[grd[0], grd[1]])
    fig = plot_decision_regions(X=X, y=y, clf=clf, legend=2)
    plt.title(label)

plt.show()

Accuracy: 0.63 (+/- 0.04) [DecisionTree]
Accuracy: 0.59 (+/- 0.08) [1 Trees]
Accuracy: 0.69 (+/- 0.02) [5 Trees]
Accuracy: 0.71 (+/- 0.06) [10 Trees]
Accuracy: 0.74 (+/- 0.04) [20 Trees]
Accuracy: 0.79 (+/- 0.02) [100 Trees]

在这里插入图片描述

  可以看到随着树的增加,随机森林的决策边界越来越光滑,精度越来越高。而且当树为1个时随机森林色精度是比决策树要差的,这很容易理解,有可能重要的特征被排除在外了,所以同样是一棵树,随机森林分类效果更差。我们再通过误差棒图看一下决策树数量对精度的影响

num_est = np.concatenate(([1],np.arange(5,105,5)))
rf_clf_cv_mean = []
rf_clf_cv_std = []

for n_est in num_est:    
    rf_clf = RandomForestClassifier(n_estimators=n_est, criterion='entropy', max_depth = 2)
    scores = cross_val_score(rf_clf, X, y, cv=3, scoring='accuracy')
    rf_clf_cv_mean.append(scores.mean())
    rf_clf_cv_std.append(scores.std())
    

plt.figure()
(_, caps, _) = plt.errorbar(num_est, rf_clf_cv_mean, yerr=rf_clf_cv_std, c='blue', fmt='-o', capsize=5)
for cap in caps:
    cap.set_markeredgewidth(1)                                                           
plt.ylabel('Accuracy')
plt.xlabel('Trees Number')
plt.show()

在这里插入图片描述
  可以看到随着树的数量增加,随机森林一开始有明显的提升,但是当树到达10个后就基本趋于稳定了

  下面我们比较一下随着学习器的增加,Tree Bagging和Random Forest的差异

num_est = np.concatenate(([1],np.arange(10,1005,10)))
bg_arr = []
rf_arr = []

for n_est in num_est:    
    rf_clf = RandomForestClassifier(n_estimators=n_est, criterion='entropy', max_depth = 2)
    rf_scores = cross_val_score(rf_clf, X, y, cv=3, scoring='accuracy')
    rf_arr.append(rf_scores.mean())
    
    bg_clf = BaggingClassifier(base_estimator=clf3, n_estimators=n_est, max_samples=0.8, max_features=0.8)
    bg_scores = cross_val_score(bg_clf, X, y, cv=3, scoring='accuracy')
    bg_arr.append(bg_scores.mean())
    

plt.figure()
plt.plot(num_est, bg_arr,  color='blue', label='Bagging')
plt.plot(num_est, rf_arr, color='red', label='Random Forest')
plt.legend()
plt.ylabel('Accuracy')
plt.xlabel('Learner Number')
plt.show()

在这里插入图片描述

  可以看到Bagging和随机森林有相似的收敛性,但是随着个体学习器数量的增加,随机森林的泛化性能要更好。

为什么说Bagging通过减小方差来提升精度

  因为Bagging是同质集成并且数据集也相同,因此各个学习器的偏差 b i a s ( h t ( x ) ) bias(h_t (x)) bias(ht(x))和方差 V a r ( h t ( x ) ) Var(h_t (x)) Var(ht(x))近似相等,但是各个学习器并不是独立的,于是
b i a s ( H ( x ) ) = b i a s ( 1 T ∑ t = 1 T h t ( x ) ) = b i a s ( h t ( x ) ) bias(H(x)) = bias \left(\frac{1}{T}\sum_{t = 1}^{T} h_t (x)\right) = bias(h_t (x)) bias(H(x))=bias(T1t=1Tht(x))=bias(ht(x))

V a r ( H ( x ) ) = V a r ( 1 T ∑ t = 1 T h t ( x ) ) = 1 T V a r ( h t ( x ) ) Var(H(x)) = Var \left(\frac{1}{T}\sum_{t = 1}^{T} h_t (x)\right) = \frac{1}{T}Var(h_t (x)) Var(H(x))=Var(T1t=1Tht(x))=T1Var(ht(x))

所以Bagging不能降低偏差,而是会降低方差(因为学习器之间的相关性,方差不会下降到 1 T V a r ( h t ( x ) ) \frac{1}{T}Var(h_t (x)) T1Var(ht(x))),如果各个学习器完全相同,即有 1 T ∑ t = 1 T h t ( x ) = h t ( x ) \frac{1}{T}\sum_{t = 1}^{T} h_t (x) = h_t (x) T1t=1Tht(x)=ht(x),那么方差也不会降低,这也就是为什么要求学习器之间要有“多样性”。随机森林通过随机选取特征的方式降低了各决策树的相关性,使得方差进一步降低。

Boosting

  不同于bagging方法,boosting方法通过分步迭代(stage-wise)的方式来构建模型,在迭代的每一步构建的弱学习器都是为了弥补已有模型的不足。Boosting算法先从初始训练集训练出一个基学习器,再根据基学习器的表现对训练样本进行调整,使得先前基学习器做错的训练样本在后续受到更多关注,然后基于调整后的样本分布来训练下一个基学习器;如此重复进行,直至基学习器数目达到事先指定的值T,最终将这T个基学习器进行加权。从偏差—方差分解的角度看,Boosting主要关注降低偏差,因此Boosting能基于泛化性能相当弱的学习器构建出很强的集成。下图以Adaboost分类为例简要说明了Boosting的机制

在这里插入图片描述

Adaboost

  Boosting算法最著名的代表是Adaboost(Adaptive Boosting)算法。Adaboost不改变所给的训练数据,而不断改变训练数据的权值分布,使得训练数据在基本分类器的学习中起不同的作用,然后利用基本分类器的线性组合构建最终的分类器。Adaboost的二类分类算法的描述如下图所示,其中 y i ∈ { − 1 , + 1 } y_i\in\{-1,+1\} yi{ 1,+1} i = 1 , 2 , . . . , m i = 1,2,...,m i=1,2,...,m f f f是真实函数, D t \mathcal{D}_t Dt是调整后用于进行第 t t t次训练的样本分布, h t h_t ht 是基于分布 D t \mathcal{D}_t Dt从数据集 D D D中训练出的分类器, ϵ t \epsilon_t ϵt h t h_t ht误差的估计, α t \alpha_t αt是分类器 h t h_t ht的权重, Z t Z_t Zt是规范化因子,以确保 D t + 1 \mathcal{D}_{t+1} Dt+1是一个分布, t = 1 , 2 , . . . , T t=1,2,...,T t=1,2,...,T

在这里插入图片描述

  Adaboost是一种比较有特点的算法,可以总结如下:

  1. 每次迭代改变的是样本的分布,而不是重复采样(re weight)。

  2. 样本分布的改变取决于样本是否被正确分类:总是分类正确的样本权值低,总是分类错误的样本权值高(通常是边界附近的样本)。

  3. 最终的结果是弱分类器的加权组合,权值表示该弱分类器的性能。

  我们通过一个例子来感受一下Adaboost的机制

实例

  我们有如下数据集,其中有红色圆形和绿色三角形共10个样本,希望建立一个分类器,能判断出任意位置样本属于哪一类,我们指定基学习器个数 T T T为3

在这里插入图片描述

  我们初始化样本权值分布 D 1 = 0.1 , 0.1 , ⋯   , 0.1 \mathcal{D}_1 = {0.1, 0.1, \cdots, 0.1} D1=0.1,0.1,,0.1,并基于该分布从训练集中训练出分类器 h 1 h_1 h1(理论上 h 1 h_1 h1应使分类错误率达到最小,这里仅用一条线代表分类结果,并未给出这条线是怎么得到的,但是不代表这条线是随意做出的),之后估计 h 1 h_1 h1的误差 ϵ 1 \epsilon_1 ϵ1,确定 h 1 h_1 h1的权重 α 1 \alpha_1 α1,并更新样本的权值分布

在这里插入图片描述

  重复上面操作依次训练出基学习器 h 2 h_2 h2 h 3 h_3 h3,此时基学习器个数达到我们预先指定的值。可以按照基学习器的权重给出输出公式。并据此预测其他样本的分类

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  每个区域是属于哪个类别,由这个区域所在分类器的权值综合决定。比如左下角的区域的样本,属于绿色分类区的权重为 h 1 h_1 h1中的0.42和 h 2 h_2 h2 中的0.65,其和为1.07;属于红色分类区域的权重为 h 3 h_3 h3中的0.92;属于红色分类区的权重小于属于绿色分类区的权值,因此左下角属于绿

  从结果中看,即使简单的分类器,组合起来也能获得很好的分类效果。

模型推导

  Adaboost算法有多种推导方式,一种比较容易理解的是基于“加性模型”,即基学习器的线性组合

H ( x ) = ∑ t = 1 T α t h t ( x ) H(x) = \sum_{t = 1}^{T} \alpha_t h_t(x) H(x)=t=1Tαtht(x)

最小化指数损失函数

L o s s ( H ∣ D ) = E D [ e − y H ( x ) ] = e − H ( x ) P ( y = 1 ∣ x ) + e H ( x ) P ( y = − 1 ∣ x ) Loss(H | \mathcal{D}) = \mathbb{E}_{\mathcal{D}}[e^{-yH(x)}] = e^{-H(x)}P(y = 1 | x) + e^{H(x)}P(y = -1 | x) Loss(HD)=ED[eyH(x)]=eH(x)P(y=1x)+eH(x)P(y=1x)


什么是前向分步算法(forward stagewise algorithm)?

  前向分步算法是求解加法模型损失函数( ∑ i = 1 N L o s s ( y i , α h ( x i ) ) \sum_{i = 1}^{N}Loss(y_i, \alpha h(x_i)) i=1NLoss(yi,αh(xi)))最小化的一种算法,简单来说就是在每一次学习一个基学习器,然后逐步逼近目标函数:

f 0 ( x ) = 0 f 1 ( x ) = f 0 ( x ) + α 1 h 1 ( x ) = α 1 h 1 ( x ) f 2 ( x ) = f 1 ( x ) + α 2 h 2 ( x ) = α 1 h 1 ( x ) + α 2 h 2 ( x ) ⋯ f M ( x ) = f M − 1 ( x ) + α M h M ( x ) = ∑ m = 1 M α m h m ( x ) \begin{array}{lcl} f_0(x) & = & 0 \\ f_1(x) & = & f_0(x) + \alpha_1 h_1(x) & = & \alpha_1 h_1(x) \\ f_2(x) & = & f_1(x) + \alpha_2 h_2(x) & = & \alpha_1 h_1(x) + \alpha_2 h_2(x) \\ \cdots \\ f_M(x) & = & f_{M-1}(x) + \alpha_M h_M(x) & = & \sum_{m = 1}^{M}\alpha_m h_m(x) \end{array} f0(x)f1(x)f2(x)fM(x)====0f0(x)+α1h1(x)f1(x)+α2h2(x)fM1(x)+αMhM(x)===α1h1(x)α1h1(x)+α2h2(x)m=1Mαmhm(x)


为什么是指数损失函数?

  指数损失函数对 H ( x ) H(x) H(x)求偏导得

∂ L o s s ( H ∣ D ) ∂ H ( x ) = − e − H ( x ) P ( y = 1 ∣ x ) + e H ( x ) P ( y = − 1 ∣ x ) \frac{\partial{Loss(H | \mathcal{D})}}{\partial{H(x)}} = -e^{-H(x)}P(y = 1 | x) + e^{H(x)}P(y = -1 | x) H(x)Loss(HD)=eH(x)P(y=1x)+eH(x)P(y=1x)

令偏导数为0有

H ( x ) = 1 2 ln ⁡ P ( y = 1 ∣ x ) P ( y = − 1 ∣ x ) H(x) = \frac{1}{2} \ln \frac{P(y = 1 |x)}{P(y = -1 |x)} H(x)=21lnP(y=1x)P(y=1x)

于是有

s i g n ( H ( x ) ) = s i g n ( 1 2 ln ⁡ P ( y = 1 ∣ x ) P ( y = − 1 ∣ x ) ) = { 0 if  P ( y = 1 ∣ x ) &gt; P ( y = − 1 ∣ x ) 1 if  P ( y = 1 ∣ x ) &lt; P ( y = − 1 ∣ x ) = arg ⁡ max ⁡ y ∈ { + 1 , − 1 } P ( y ∣ x ) \begin{aligned} sign\left(H(x)\right) &amp; = sign\left(\frac{1}{2} \ln \frac{P(y = 1 |x)}{P(y = -1 |x)}\right) \\ &amp; = \begin{cases} 0&amp; \text{if } P(y = 1 |x) \gt P(y = -1 |x)\\ 1&amp; \text{if } P(y = 1 |x) \lt P(y = -1 |x) \end{cases} \\ &amp; = \mathop{\arg\max}_{y \in \{+1,-1\}} P(y | x) \end{aligned} sign(H(x))=sign(21lnP(y=1x)P(y=1x))={ 01if P(y=1x)>P(y=1x)if P(y=1x)<P(y=1x)=argmaxy{ +1,1}P(yx)

过程中忽略了 P ( y = 1 ∣ x ) = P ( y = − 1 ∣ x ) P(y = 1 |x) = P(y = -1 |x) P(y=1x)=P(y=1x)的情况,另外西瓜书中对于概率的写法是 P ( f ( x ) = y ∣ x ) P(f(x) = y|x) P(f(x)=yx),其中 f f f是真实函数。从结果可知, s i g n ( H ( x ) ) sign\left(H(x)\right) sign(H(x))达到了贝叶斯最优错误率( i f P ( ω 1 ∣ x ) &gt; P ( ω 1 ∣ x ) , &ThickSpace; t h e n   x ∈ ω 1 , &ThickSpace; e l s e   x ∈ ω 2 if P(\omega_1|x) \gt P(\omega_1|x),\; then\ x\in \omega_1,\;else\ x\in \omega_2 ifP(ω1x)>P(ω1x),then xω1,else xω2),即最小化指数损失函数等价于分类错误率最小化。因此我们可以用它替代0/1损失函数作为最优目标。有了以上结论,我们便可以进行算法的推导。


推导过程

  在算法的第 t t t次循环中,我们基于分布 D t \mathcal{D}_t Dt产生了基分类器 h t ( x ) h_t(x) ht(x)和分类器权重 α t \alpha_t αt,那么它们应该使得 H t ( x ) = ∑ k = 1 t α k h k ( x ) H_t(x) = \sum_{k = 1}^{t}\alpha_k h_k(x) Ht(x)=k=1tαkhk(x)最小化损失函数

L o s s ( H t ( x ) ∣ D t ) = L o s s ( ∑ k = 1 t α k h k ( x )   ∣   D k ) = L o s s ( H t − 1 ( x )   +   α t h t ( x )   ∣   D k ) = E D t e − y ( H t − 1 ( x )   +   α t h t ( x ) ) = ∑ i = 1 N e − y i H t − 1 ( x i ) e − y i α t h t ( x i ) \begin{aligned} Loss(H_t(x) | \mathcal{D}_t) &amp; = Loss(\sum_{k = 1}^{t}\alpha_k h_k(x) \ |\ \mathcal{D}_k) \\ &amp; = Loss(H_{t-1}(x) \ +\ \alpha_t h_t(x)\ |\ \mathcal{D}_k) \\ &amp; = \mathbb{E}_{\mathcal{D}_t} e^{-y (H_{t-1}(x) \ +\ \alpha_t h_t(x))} \\ &amp; = \sum_{i = 1}^{N} e^{-y_i H_{t-1}(x_i)} e^{-y_i\alpha_t h_t(x_i)} \end{aligned} Loss(Ht(x)Dt)=Loss(k=1tαkhk(x)  Dk)=Loss(Ht1(x) + αtht(x)  Dk)=EDtey(Ht1(x) + αtht(x))=i=1NeyiHt1(xi)eyiαtht(xi)

我们令 w t , i = e − y i H t − 1 ( x i ) w_{t,i} = e^{-y_i H_{t-1}(x_i)} wt,i=eyiHt1(xi),显然, w t , i w_{t,i} wt,i α t \alpha_t αt h t h_t ht无关,所以与最小化损失也无关,于是有

L o s s ( H t ( x ) ∣ D t ) = ∑ i = 1 N w t , i e − y i α t h t ( x i ) Loss(H_t(x) | \mathcal{D}_t) = \sum_{i = 1}^{N} w_{t,i} e^{-y_i\alpha_t h_t(x_i)} Loss(Ht(x)Dt)=i=1Nwt,ieyiαtht(xi)

h t ∗ h_t^* ht α t ∗ \alpha_t^* αt是满足要求的分类器和分类器权重,即

( h t ∗ , α t ∗ ) = arg ⁡ min ⁡ α t , h t L o s s ( H t ( x ) ∣ D t ) = arg ⁡ min ⁡ α t , h t ∑ i = 1 N w t , i e − y i α t h t ( x i ) (h_t^*,\alpha_t^*) = \mathop{\arg \min}_{\alpha_t, h_t}Loss(H_t(x) | \mathcal{D}_t) = \mathop{\arg \min}_{\alpha_t, h_t}\sum_{i = 1}^{N} w_{t,i} e^{-y_i\alpha_t h_t(x_i)} (ht,αt)=argminαt,htLoss(Ht(x)Dt)=argminαt,hti=1Nwt,ieyiαtht(xi)

对任意 α t &gt; 0 \alpha_t \gt 0 αt>0,考虑

h t ∗ ( x ) = arg ⁡ min ⁡ h t ∑ i = 1 N w t , i I ( h t ( x i ) ≠ y i ) h_t^*(x) = \mathop{\arg \min}_{h_t} \sum_{i = 1}^{N}w_{t,i}I(h_t(x_i) \ne y_i) ht(x)=argminhti=1Nwt,iI(ht(xi)̸=yi)

这意味着 h t ∗ ( x ) h_t^*(x) ht(x)是使第t轮加权训练数据分类误差最小的基本分类器,即为所求。再求 α t ∗ \alpha_t^* αt

L o s s ( H t ( x ) ∣ D t ) = ∑ i = 1 N w t , i e − y i α t h t ∗ ( x i ) = ∑ h t ∗ ( x i ) ≠ y i w t , i e α t + ∑ h t ∗ ( x i ) = y i w t , i e − α t Loss(H_t(x) | \mathcal{D}_t) = \sum_{i = 1}^{N} w_{t,i} e^{-y_i\alpha_t h_t^*(x_i)} = \sum_{h_t^*(x_i) \ne y_i}w_{t,i}e^{\alpha_t}+\sum_{h_t^*(x_i) = y_i}w_{t,i}e^{-\alpha_t} Loss(Ht(x)Dt)=i=1Nwt,ieyiαtht(xi)=ht(xi)̸=yiwt,ieαt+ht(xi)=yiwt,ieαt

损失函数对 α t \alpha_t αt求偏导得

∂ L o s s ( H t ( x ) ∣ D t ) ∂ α t = − ∑ h t ∗ ( x i ) ≠ y i w t , i e α t + ∑ h t ∗ ( x i ) = y i w t , i e − α t \frac{\partial{Loss(H_t(x) | \mathcal{D}_t)}}{\partial{\alpha_t}} = -\sum_{h_t^*(x_i) \ne y_i}w_{t,i}e^{\alpha_t}+\sum_{h_t^*(x_i) = y_i}w_{t,i}e^{-\alpha_t} αtLoss(Ht(x)Dt)=ht(xi)̸=yiwt,ieαt+ht(xi)=yiw

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值