原理:https://www.jianshu.com/p/c0ba78242466
https://blog.csdn.net/qq_20412595/article/details/82889655
https://blog.csdn.net/shine19930820/article/details/75209021#17-stacking
代码:https://blog.csdn.net/shine19930820/article/details/75209021#17-stacking
1. 模型堆叠stacking
** 标题融合模型的选用条件
- Base Model 之间的相关性要尽可能的小。这就是为什么非 Tree-based Model 往往表现不是最好但还是要将它们包括在 Ensemble 里面的原因。Ensemble 的 Diversity 越大,最终 Model 的 Bias 就越低。
- Base Model 之间的性能表现不能差距太大。 这其实是一个 Trade-off,在实际中很有可能表现相近的 Model 只有寥寥几个而且它们之间相关性还不低。但是实践告诉我们即使在这种情况下 Ensemble 还是能大幅提高成绩。
第一层一般使用比较复杂的模型来学习数据中隐含的更深层的特征,如在第一层使用xgboost/RF/lightGBM/GDBT等集成学习;随着模型堆叠的深入,特征已经能够提供足够的信息给算法降低偏差,所以第二/第三层可以使用相对简单的模型,如KNN、SVM、决策树、逻辑回归等,常用的是lr。
【注意】在模型堆叠中,第二层将第一层得到的新的特征作为训练数据集的输入,不再利用原始的特征,为了避免过拟合。
dataset_blend_train = np.zeros((X.shape[0], len(clfs)))
dataset_blend_test = np.zeros((X_predict.shape[0], len(clfs)))
'''5折stacking'''
n_folds = 5
skf = list(StratifiedKFold(y, n_folds))
for j, clf in enumerate(clfs):
'''依次训练各个单模型'''
# print(j, clf)
dataset_blend_test_j = np.zeros((X_predict.shape[0], len(skf)))
for i, (train, test) in enumerate(skf):
'''使用第i个部分作为预测,剩余的部分来训练模型,获得其预测的输出作为第i部分的新特征。'''
# print("Fold", i)
X_train, y_train, X_test, y_test = X[train], y[train], X[test], y[test]
clf.fit(X_train, y_train)
y_submission = clf.predict_proba(X_test)[:, 1]
dataset_blend_train[test, j] = y_submission
dataset_blend_test_j[:, i] = clf.predict_proba(X_predict)[:, 1]
'''对于测试集,直接用这k个模型的预测值均值作为新的特征。'''
dataset_blend_test[:, j] = dataset_blend_test_j.mean(1)
print("val auc Score: %f" % roc_auc_score(y_predict, dataset_blend_test[:, j]))
clf = GradientBoostingClassifier(learning_rate=0.02, subsample=0.5, max_depth=6, n_estimators=30)
clf.fit(dataset_blend_train, y)
y_submission = clf.predict_proba(dataset_blend_test)[:, 1]
2. 集成学习
通过构建并结合多个学习器来完成学习任务。其中个体学习器可以由决策树,神经网络,贝叶斯分类器,K-近邻等构成。
2.1 Boosting
Boosting族的典型算法有:adaboost、GBDT、xgboost。
Boosting算法的工作机制是首先从训练集用初始权重训练出一个弱学习器1,根据弱学习的学习误差率表现来更新训练样本的权重,使得之前弱学习器1学习误差率高的训练样本点的权重变高,使得这些误差率高的点在后面的弱学习器2中得到更多的重视。然后基于调整权重后的训练集来训练弱学习器2.,如此重复进行,直到弱学习器数达到事先指定的数目T,最终将这T个弱学习器通过集合策略进行整合,得到最终的强学习器。
不过有几个具体的问题Boosting算法没有详细说明。
1)如何计算学习误差率e?
2) 如何得到弱学习器权重系数α?
3)如何更新样本权重D?
4) 使用何种结合策略?
只要是boosting大家族的算法,都要解决这4个问题。
2.1.1 AdaBoost
算法原理:https://www.cnblogs.com/pinard/p/6133937.html?utm_source=tuicool&utm_medium=referral
★ 只适用于二分类问题。
- 加法模型:最终的强分类器是若干个弱分类器加权平均而得到的;
- 基学习器的线性组合(前向分步学习算法):利用前一个弱学习器的结果来更新后一个弱学习器的训练集权重;
- 最小化指数损失函数:
scikit-learn Adaboost类库使用:
https://www.cnblogs.com/pinard/p/6136914.html
2.1.2 GBDT
算法原理:https://www.cnblogs.com/pinard/p/6140514.html
GBDT也是集成学习Boosting家族的成员,但是却和传统的Adaboost有很大的不同。回顾下Adaboost,我们是利用前一轮迭代弱学习器的误差率来更新训练集的权重,这样一轮轮的迭代下去。GBDT也是迭代,使用了前向分布算法,但是弱学习器限定了只能使用CART回归树模型,同时迭代思路和Adaboost也有所不同。
- GBDT的每一次计算都是为了减少上一次的残差;
- 以负梯度下降的方式来拟合损失函数,得到第t棵CART回归树。
GBDT的会累加所有树的结果,而这种累加是无法通过分类完成的,因此GBDT的树都是CART回归树,而不是分类树(尽管GBDT调整后也可以用于分类但不代表GBDT的树为分类树)。
通过损失函数的负梯度来拟合,我们找到了一种通用的拟合损失误差的办法,这样无轮是分类问题还是回归问题,我们通过其损失函数的负梯度的拟合,就可以用GBDT来解决我们的分类回归问题。区别仅仅在于损失函数不同导致的负梯度不同而已。
GBDT的正则化:
- 第一种是和Adaboost类似的正则化项,即步长(learning rate),定义为ν。
对于前面的弱学习器的迭代如果我们加上了正则化项,则有
ν的取值范围为0<ν≤10<ν≤1。对于同样的训练集学习效果,较小的ν意味着我们需要更多的弱学习器的迭代次数。
通常我们用步长和迭代最大次数一起来决定算法的拟合效果。 - 通过子采样比例(subsample)的方式正则化。取值为(0,1]。
注意:这里的子采样和随机森林不一样,随机森林使用的是放回抽样,而这里是不放回抽样。如果取值为1,则全部样本都使用,等于没有使用子采样。如果取值小于1,则只有一部分样本会去做GBDT的决策树拟合。选择小于1的比例可以减少方差,即防止过拟合,但是会增加样本拟合的偏差,因此取值不能太低。推荐在[0.5, 0.8]之间。
使用了子采样的GBDT有时也称作随机梯度提升树(Stochastic Gradient Boosting Tree, SGBT)。由于使用了子采样,程序可以通过采样分发到不同的任务去做boosting的迭代过程,最后形成新树,从而减少弱学习器难以并行学习的弱点。 - 对于弱学习器即CART回归树进行正则化剪枝,同CART决策树。
scikit-learn 梯度提升树(GBDT)调参:
http://www.cnblogs.com/pinard/p/6143927.html
2.1.3 XGBoost
参考链接:
- https://www.jianshu.com/p/7467e616f227
- https://blog.csdn.net/a1b2c3d4123456/article/details/52849091
- https://blog.csdn.net/yingzoe/article/details/86495940
- 画出树结构:https://blog.csdn.net/anshuai_aw1/article/details/82988494
xgboost是在GBDT的基础上对boosting算法进行的改进,内部决策树使用的是回归树.
xgboost运行速度快的原因:gi和hi相互独立,可以并行地求出来。
xgboost的改进点总结
- 传统的GBDT以CART树作为基学习器,XGBoost还支持线性分类器,这个时候XGBoost相当于L1和L2正则化的逻辑斯蒂回归(分类)或者线性回归(回归);
- 目标函数通过二阶泰勒展开式做近似
- 定义了树的复杂度(正则化项),并应用到目标函数中。【xgboost的切分操作和普通的决策树切分过程是不一样的。普通的决策树在切分的时候并不考虑树的复杂度,而依赖后续的剪枝操作来控制。xgboost在切分的时候就已经考虑了树的复杂度,就是那个γ参数。所以,它不需要进行单独的剪枝操作。】
- 分裂结点处通过结构打分和分割损失动态生长
- 分裂结点的候选集合通过一种分布式Quantile Sketch得到
- 可以处理稀疏、缺失数据,自动学习出缺失值的分裂方向
- 借用了RandomForest中的列抽样思想,可以通过特征的列采样防止过拟合,同时减少计算
- gi和hi是不依赖于损失函数的形式的,只要这个损失函数二次可微就可以了。所以xgboost可以支持自定义损失函数,只需满足二次可微即可。
- 决策树的学习最耗时的一个步骤就是对特征的值进行排序,确定最佳分割点。而xgboost实现了特征节点划分的并行(多线程)计算。在训练之前,预先对数据进行了排序,然后保存为block结构,后面的迭代中重复地使用这个结构,实现每个特征的划分增益并行计算,大大减小计算量。
XGBoost参数调优:http://www.cnblogs.com/mfryf/p/6293814.html
XGBoost处理缺失值的方法:
在节点分裂的时候把缺失值同时分到左子树和右子树中分别计算损失函数的值,选择最优的一个属性的值进行分裂。
2.1.4 lightGBM
源码:https://lightgbm.readthedocs.io/en/latest/_modules/lightgbm/sklearn.html
lgb和xgb的比较:https://bacterous.github.io/2018/09/13/LightGBM%E4%BD%BF%E7%94%A8/
2.2 Bagging
Bagging族的典型算法有:Bagging和RF(随机森林)。
Boosting:关注降低偏差,能基于泛化性能弱的学习器构建出很强的集成;个体学习器间存在强依赖关系、必须串行生成的序列化方法。
Bagging:关注降低方差,在不剪枝决策树、神经网络等易受样本扰动的学习期上效用更明显;个体学习器间不存在强依赖关系、可同时生成的并行化方法。
2.2.1 Bagging
采用自助采样法,给定包含m个样本的数据集,县随机取出一个样本放入采样集中,再把该样本放回初始数据集,使得下次采样时该样本仍有可能被选中,这样,经过m次随机采样操作,可以得到含m个样本的采样集。【注意:在一个采样集中,有的样本会多次出现,也有可能有的样本从未出现。】
采样出T个含m个训练样本的采样集,然后基于每个采样集训练出一个基学习器,再将这些基学习器进行结合。
- 有放回的自助采样法
- 结合策略:多数表决(分类)或简单平均(回归)。
- 对于弱学习器没有限制,但是最常用的一般也是决策树和神经网络
2.2.2 随机森林——Bagging的扩展变体
Random Forest(随机森林)是Bagging的扩展变体,它在以 CART决策树 为基学习器构建Bagging集成的基础上,进一步在传统决策树节点选择划分属性的训练过程中引入了随机特征选择(不剪枝)。然后再从这个子集中选择最优的属性用于划分。
这种随机性导致随机森林的偏差会有稍微的增加(相比于单棵不随机树),但是由于随机森林的‘平均’特性,会使得它的方差减小,而且方差的减小补偿了偏差的增大,因此总体而言是更好的模型。
随机森林中基学习器的多样性来自样本扰动(对初始训练集采样) & 属性扰动(随机特征选择),使得集成的泛化性能提升。随着个体学习器数目增加,能获得更低的泛化误差。
RF的重要特性是不用对其进行交叉验证或者使用一个独立的测试集获得无偏估计,它可以在内部进行评估,也就是说在生成的过程中可以对误差进行无偏估计,由于每个基学习器只使用了训练集中约63.2%的样本,剩下约36.8%的样本可用做验证集来对其泛化性能进行“包外估计”。
RF和Bagging对比:
RF的起始性能较差,特别当只有一个基学习器时,随着学习器数目增多,随机森林通常会收敛到更低的泛化误差。 随机森林的训练效率也会高于Bagging,因为在单个决策树的构建中,Bagging使用的是‘确定性’决策树,在选择特征划分结点时,要对所有的特征进行考虑,而随机森林使用的是‘随机性’特征数,只需考虑特征的子集。
随机森林的OOB理解:*
https://blog.csdn.net/nemoyy/article/details/80317936
根据概率论,可知数据集中有大约1/3的数据是没有被选取的(称为Out of bag),所以就是这没被选取的部分作为小树的测试集.
优点:
- 训练可以高度并行化,对于大数据时代的大样本训练速度有优势;
- 由于可以随机选择决策树节点划分特征,这样在样本特征维度很高的时候,仍然能高效的训练模型;
- 在训练后,可以给出各个特征对于输出的重要性;
- 由于采用了随机采样,训练出的模型的方差小,泛化能力强;
- 相对于Boosting系列的Adaboost和GBDT, RF实现比较简单;
- 对部分特征缺失不敏感。
缺点:
- 在某些噪音比较大的样本集上,RF模型容易陷入过拟合;
- 取值划分比较多的特征容易对RF的决策产生更大的影响,从而影响拟合的模型的效果。
scikit-learn随机森林调参:
http://www.cnblogs.com/pinard/p/6160412.html