公号:码农充电站pro
主页:https://codeshellme.github.iohtml
在机器学习算法中,有一种算法叫作集成算法,AdaBoost 算法是集成算法的一种。咱们先来看下什么是集成算法。node
一般,一个 Boss 在作一项决定以前,会听取多个 Leader 的意见。集成算法就是这个意思,它的基本含义就是集众算法之所长。python
前面已经介绍过许多算法,每种算法都有优缺点。那么是否能够将这些算法组合起来,共同作一项决定呢?答案是确定的。这就诞生了集成算法(Ensemble Methods)。git
集成算法的基本架构以下:github
算法的组合有多种形式,好比将不一样的算法集成起来,或者将同一种算法以不一样的形式集成起来。web
常见的集成算法有四大类:算法
多个算法以不一样的方式能够组合成集成算法,若是再深刻探究的话,不一样的集成方法也能够组合起来:shell
对于集成算法的集成,这里再也不过多介绍。api
bagging和 boosting是两个比较著名的集成算法。架构
bagging 算法
bagging 算法是将一个原始数据集随机抽样成 N 个新的数据集。而后将这N 个新的数据集做用于同一个机器学习算法,从而获得 N 个模型,最终集成一个综合模型。
在对新的数据进行预测时,须要通过这 N 个模型(每一个模型互不依赖干扰)的预测(投票),最终综合 N 个投票结果,来造成最后的预测结果。
boosting 算法
boosting 算法的含义为提高学习,它将多个弱分类器组合起来造成一个强分类器。
boosting 算法是将一个原始数据集使用同一个算法迭代学习 N 次,每次迭代会给数据集中的样本分配不一样的权重。
分类正确的样本会在下一次迭代中下降权重,而分类错误的样本会在下一次迭代中提升权重,这样作的目的是,使得算法可以对其不擅长(分类错误)的数据不断的增强提高学习,最终使得算法的成功率愈来愈高。
每次迭代都会训练出一个新的带有权重的模型,迭代到必定的次数或者最终模型的错误率足够低时,迭代中止。最终集成一个强大的综合模型。
在对新的数据进行预测时,须要通过这 N 个模型的预测,每一个模型的预测结果会带有一个权重值,最终综合 N 个模型结果,来造成最后的预测结果。
boosting 算法中每一个模型的权重是不相等的,而bagging 算法中每一个模型的权重是相等的。
AdaBoost 算法是很是流行的一种 boosting 算法,它的全称为 Adaptive Boosting,即自适应提高学习。
AdaBoost 算法由Freund 和 Schapire 于1995 年提出。这两位做者写了一篇关于AdaBoost 的简介论文,这应该是关于AdaBoost 算法的最权威的资料了。为了防止连接丢失,我将论文下载了,放在了这里。
AdaBoost 算法 和 SVM 算法被不少人认为是监督学习中最强大的两种算法。
AdaBoost 算法的运行过程以下:
这个过程当中,咱们假设 x 为样本,Gi(x) 为第 i 轮训练出的模型,ai 为 Gi(x) 的权重,一共迭代 n 轮,那么最终模型 G(x) 的计算公式为:
模型权重 ai 的计算公式以下,其中 ei 为第 i 轮模型的错误率:
咱们用 Dk+1 表明第 k+1 轮的样本的权重集合,用 Wk+1,1 表明第 k+1 轮中第1个样本的权重, Wk+1,N 表明第 k+1 轮中第 N 个样本的权重,用公式表示为:
样本权重 Wk+1,i 的计算公式为:
其中:
下面咱们以一个二分类问题,来看一下AdaBoost 算法的计算过程。
假设咱们有10 个样本数据,X 为特征集,Y 为目标集,以下:
X | Y |
---|---|
0 | 1 |
1 | 1 |
2 | 1 |
3 | -1 |
4 | -1 |
5 | -1 |
6 | 1 |
7 | 1 |
8 | 1 |
9 | -1 |
假设有三个分类器,分别以2.5,5.5,8.5将数据分界:
简单看下其分布图:
根据这三个分类器,咱们能够算出每一个样本对应的值:
X | Y | f1(x) | f2(x) | f3(x) |
---|---|---|---|---|
0 | 1 | 1 | -1 |
1 |
1 | 1 | 1 | -1 |
1 |
2 | 1 | 1 | -1 |
1 |
3 | -1 | -1 | -1 | 1 |
4 | -1 | -1 | -1 | 1 |
5 | -1 | -1 | -1 | 1 |
6 | 1 | -1 |
1 | 1 |
7 | 1 | -1 |
1 | 1 |
8 | 1 | -1 |
1 | 1 |
9 | -1 | -1 | 1 |
-1 |
上面表格中,对于每一个分类器分类错误的数据,我进行了标红
。
第一轮
将每一个样本的权重初始化为0.1:
(0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1)
根据 D1 计算每一个分类器的错误率:
选择错误率最小的分类器做为第1轮的分类器,由于 f1(x)和 f3(x) 的错误率都是0.3,因此能够任意选一个,好比咱们选 f1(x),因此 G1(x) = f1(x)。
计算 G1(x) 的权重 a1(x):
(1/2) * log((1-0.3)/0.3)
= 0.42这里的
log
以e
为底。
计算第2轮的样本权重D2,首先须要根据Zk 的公式来计算 Z1,先计算 -a1yiG1(xi) ,以下:
序号 i | yi | G1(xi) | -a1yiG1(xi) |
---|---|---|---|
1 | 1 | 1 | -0.42 x 1 x 1 => -0.42 |
2 | 1 | 1 | -0.42 x 1 x 1 => -0.42 |
3 | 1 | 1 | -0.42 x 1 x 1 => -0.42 |
4 | -1 | -1 | -0.42 x -1 x -1 => -0.42 |
5 | -1 | -1 | -0.42 x -1 x -1 => -0.42 |
6 | -1 | -1 | -0.42 x -1 x -1 => -0.42 |
7 | 1 | -1 | -0.42 x 1 x -1 => 0.42 |
8 | 1 | -1 | -0.42 x 1 x -1 => 0.42 |
9 | 1 | -1 | -0.42 x 1 x -1 => 0.42 |
10 | -1 | -1 | -0.42 x -1 x -1 => -0.42 |
那么 Z1 = 0.1 * (7 * e^-0.42 + 3 * e^0.42)
= 0.92
再根据样本权重的计算公式能够得出:
(0.0715, 0.0715, 0.0715, 0.0715, 0.0715, 0.0715, 0.1666, 0.1666, 0.1666, 0.0715)
第二轮
根据 D2 计算每一个分类器的错误率:
选择错误率最小的分类器做为第2轮的分类器,因此 G2(x) = f3(x)。
计算 G2(x) 的权重 a2(x):
(1/2) * log((1-0.2145)/0.2145)
= 0.65计算第3轮每一个样本的权重:
(0.0455,0.0455,0.0455,0.1667, 0.1667,0.01667,0.1060, 0.1060, 0.1060, 0.0455)
这里省略了D3 的计算过程,其计算过程与D2 同样。
第三轮
根据 D3 计算每一个分类器的错误率:
选择错误率最小的分类器做为第3轮的分类器,因此 G3(x) = f2(x)。
计算 G3(x) 的权重 a3(x):
(1/2) * log((1-0.182)/0.182)
= 0.75若是咱们只迭代三轮,那么最终的模型 G(x) = 0.42G1(x) + 0.65G2(x) + 0.75G3(x)。
有了最终的模型G(x),咱们根据G(x) 来计算每一个样本对应的值:
G0 = 0.42 + 0.65 - 0.75 = 0.32 => 1 G1 = 0.42 + 0.65 - 0.75 = 0.32 => 1 G2 = 0.42 + 0.65 - 0.75 = 0.32 => 1 G3 = -0.42 + 0.65 - 0.75 = -0.52 => -1 G4 = -0.42 + 0.65 - 0.75 = -0.52 => -1 G5 = -0.42 + 0.65 - 0.75 = -0.52 => -1 G6 = -0.42 + 0.65 + 0.75 = 0.98 => 1 G7 = -0.42 + 0.65 + 0.75 = 0.98 => 1 G8 = -0.42 + 0.65 + 0.75 = 0.98 => 1 G9 = -0.42 - 0.65 + 0.75 = -0.32 => -1
由于本例是一个二分类问题,因此对于值大于 0 均取 1,值小于 0 均取 -1。
最终能够获得以下表格:
X | Y | G(x) |
---|---|---|
0 | 1 | 1 |
1 | 1 | 1 |
2 | 1 | 1 |
3 | -1 | -1 |
4 | -1 | -1 |
5 | -1 | -1 |
6 | 1 | 1 |
7 | 1 | 1 |
8 | 1 | 1 |
9 | -1 | -1 |
能够看到通过提高学习后的模型的准确率提升到了100%。
固然对于实际问题,准确率基本达不到100%。
以上就是一个简化版的 AdaBoost 算法的计算过程。
本例的原型出自《统计学习方法 · 李航》
sklearn 库的 ensemble 模块实现了一系列的集成算法,对于集成方法的介绍,能够参看这里。
AdaBoost 算法便可用于分类问题,也可用于回归问题:
来看下 AdaBoostClassifier 类的原型:
AdaBoostClassifier( base_estimator=None, n_estimators=50, learning_rate=1.0, algorithm='SAMME.R', random_state=None)
其参数含义:
AdaBoostClassifier
默认使用的是 DecisionTreeClassifier(max_depth=1)
。AdaBoostRegressor
默认使用的是 DecisionTreeRegressor(max_depth=3)
。再来看下 AdaBoostRegressor 类的原型:
AdaBoostRegressor( base_estimator=None, n_estimators=50, learning_rate=1.0, loss='linear', random_state=None)
能够看到,回归和分类的参数基本一致,而回归算法里没有 algorithm 参数,但多了 loss 参数。
loss 参数表明损失函数,用于(每次迭代后)更新样本的权重,其共有 3 种选择,分别为:
接下来,咱们看下如何用 AdaBoost 算法进行回归分析。
以前在文章《决策树算法-实战篇-鸢尾花及波士顿房价预测》中,咱们介绍过波士顿房价数据集,这里再也不对数据自己进行过多介绍,下面咱们用 AdaBoost 算法来分析该数据集。
首先加载数据集:
from sklearn.datasets import load_boston boston = load_boston() features = boston.data # 特征集 prices = boston.target # 目标集
将数据拆分红训练集和测试集:
from sklearn.model_selection import train_test_split train_x, test_x, train_y, test_y = train_test_split( features, prices, test_size=0.25, random_state=33)
构建 AdaBoost 回归模型:
from sklearn.ensemble import AdaBoostRegressor regressor = AdaBoostRegressor() # 均采用默认参数 regressor.fit(train_x, train_y) # 拟合模型
使用模型进行预测:
pred_y = regressor.predict(test_x)
评价模型准确率:
from sklearn.metrics import mean_squared_error mse = mean_squared_error(test_y, pred_y) print "AdaBoost 均方偏差 = ", round(mse, 2) # 18.57
base_estimator_
属性是基学习器,也就是训练以前的模型:
>>> regressor.base_estimator_ DecisionTreeRegressor(criterion='mse', max_depth=3, max_features=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, presort=False, random_state=None, splitter='best')
estimators_
属性是通过训练以后的全部弱学习器,有 50 个:
>>> len(regressor.estimators_) 50
feature_importances_
属性中存储了每一个特征的重要性:
>>> regressor.feature_importances_ array([0.02104728, 0. , 0.00304314, 0. , 0.00891602, 0.2825294 , 0.00438134, 0.17308669, 0.00929782, 0.07457966, 0.02250937, 0.00592025, 0.39468902])
estimator_weights_
属性是每一个弱学习器的权重:
>>> regressor.estimator_weights_ array([2.39259487, 2.02119506, 1.68364189, 0.71892012, 2.01966649, 1.03178435, 1.14573926, 2.15335207, 1.62996738, 1.39576421, 1.42582945, 0.55214963, 1.17953337, 0.20934333, 0.3022646 , 1.73484417, 1.36590071, 0.27471584, 0.97297267, 0.21729445, 1.97061649, 0.91072652, 1.95231025, 0.11764431, 1.19301792, 0.21629414, 1.57477075, 1.23626619, 1.21423494, 0.24063141, 0.08265621, 0.17198137, 0.58300858, 0.72722721, 2.07974547, 0.61855751, 1.98179632, 0.5886063 , 0.18646107, 0.38176832, 1.11993353, 1.81984396, 1.06785584, 0.45475221, 1.85522596, 0.29177236, 1.0699074 , 1.79358974, 1.37771849, 0.15698322])
estimator_errors_
属性是每一个弱学习器的错误率:
>>> regressor.estimator_errors_ array([0.08373912, 0.11699548, 0.15661382, 0.32763082, 0.11715348, 0.26273832, 0.24126819, 0.1040184 , 0.16383483, 0.19848913, 0.19374934, 0.36536582, 0.23513611, 0.44785447, 0.42500398, 0.149969 , 0.20328296, 0.43174973, 0.27428838, 0.44588913, 0.12232269, 0.28685119, 0.12430167, 0.4706228 , 0.23271962, 0.44613629, 0.17153735, 0.22508658, 0.22895259, 0.44013076, 0.47934771, 0.45711032, 0.35824061, 0.32580349, 0.1110811 , 0.3501096 , 0.12112748, 0.3569547 , 0.45351932, 0.40570047, 0.24602361, 0.1394526 , 0.25581106, 0.38823148, 0.13526048, 0.42757002, 0.25542069, 0.14263317, 0.20137567, 0.46083459])
咱们将每一个弱学习器的权重和错误率使用 Matplotlib 画出折线图以下:
能够看到弱学习器的错误率与权重成反比:
下面分别使用决策树回归和KNN 回归来分析波士顿数据集,从而对比这三种算法的准确度。
使用决策树回归
代码以下
from sklearn.tree import DecisionTreeRegressor # 构建决策树 dec_regressor = DecisionTreeRegressor() # 拟合决策树 dec_regressor.fit(train_x, train_y) # 预测数据 pred_y = dec_regressor.predict(test_x) # 计算模型准确度 mse = mean_squared_error(test_y, pred_y) print "决策树均方偏差 = ", round(mse, 2)
使用KNN 回归
代码以下
from sklearn.neighbors import KNeighborsRegressor # 构建 KNN 模型 knn_regressor = KNeighborsRegressor() # 拟合模型 knn_regressor.fit(train_x, train_y) # 预测数据 pred_y = knn_regressor.predict(test_x) # 计算模型准确度 mse = mean_squared_error(test_y, pred_y) print "KNN 均方偏差 = ", round(mse, 2)
运行代码得出的结果是:
咱们知道均方偏差越小,准确率越高,因此 AdaBoost 算法在这三种算法中表现最好。
理想状况下,迭代次数越多,最终模型的错误率应该越低,下面咱们来探究一下是不是这样?
sklearn 中的 make_hastie_10_2 函数用于生成二分类数据。
咱们用该函数生成12000 个数据,取前2000 个做为测试集,其他为训练集:
from sklearn import datasets X, Y = datasets.make_hastie_10_2(n_samples=12000, random_state=1) train_x, train_y = X[2000:], Y[2000:] test_x, test_y = X[:2000], Y[:2000]
构建 AdaBoost 分类模型,迭代次数为 500:
from sklearn.ensemble import AdaBoostClassifier IterationN = 500 ada = AdaBoostClassifier(n_estimators=IterationN) ada.fit(train_x, train_y)
对测试数据进行预测,并统计错误率:
from sklearn.metrics import zero_one_loss errs = [] for pred_y in ada.staged_predict(test_x): err = zero_one_loss(pred_y, test_y) errs.append(err)
staged_predict
方法用于预测每一轮迭代后输入样本的预测值,因此模型迭代了多少次,该方法就会返回多少次预测结果,其返回的就是分别迭代1,2,3...N 次的预测结果。
zero_one_loss 方法用于计算错误率。
errs
列表中存储了每次迭代的错误率。
用 Matplotlib 画出错误率折线图:
import matplotlib.pyplot as plt plt.plot(range(1, IterationN+1), errs, label='AdaBoost Error Rate', color='orange') plt.legend(loc='upper right', fancybox=True) # 显示图例 plt.show()
经过上图能够看出:
建议:
在实际应用中,能够经过画这种折线图的方式,来判断模型应该迭代多少次。固然也要考虑时间成本,迭代次数越多,时间成本也会越高。
sklearn 官方文档中也有一个这样的例子,你能够参考这里。
须要注意的是,若是数据集不够好的话,错误率在达到必定值后有可能会反弹,即迭代次数若是再增长,错误率可能会增高,这时候就是过拟合现象。
本篇文章主要介绍了如下内容:
(本节完。)
推荐阅读:
欢迎关注做者公众号,获取更多技术干货。