集成学习
Ensemble learning 中文名叫做集成学习,它并不是一个单独的机器学习算法,而是将很多的机器学习算法结合在一起,我们把组成集成学习的算法叫做“个体学习器”。在集成学习器当中,个体学习器都相同,那么这些个体学习器可以叫做“基学习器”。
个体学习器组合在一起形成的集成学习,常常能够使得泛化性能提高,这对于“弱学习器”的提高尤为明显。弱学习器指的是比随机猜想要好一些的学习器。
在进行集成学习的时候,我们希望我们的基学习器应该是好而不同,这个思想在后面经常体现。 “好”就是说,你的基学习器不能太差,“不同”就是各个学习器尽量有差异。
集成学习有两个分类,一个是个体学习器存在强依赖关系、必须串行生成的序列化方法,以Boosting为代表。另外一种是个体学习器不存在强依赖关系、可同时生成的并行化方法,以Bagging和随机森林(Random Forest)为代表。
Bagging和随机森林
Bagging使用自助采样的方法(在使用sklearn进行交叉验证一文最后有介绍)来获得个体学习器的训练集,通过把训练好的个体学习器用适当的结合策略结合在一起得到我们的输出结果。
随机森立和Bagging很像,但是它的个体学习器是决策树。它在上面做了一些改进,为了使得个体学习器不同,在决策树算法选择划分属性的时候运用一定的策略进行随机选择,这样就做到了各个学习器不相同。
结合策略和Stacking
将个体学习器结合在一起的时候使用的方法叫做结合策略。
对于连续的值使用平均法,对于分类值使用投票法。
还有一种结合策略是使用另外一个机器学习算法来将个体机器学习器的结果结合在一起,这个方法就是Stacking。
在stacking方法中,我们把个体学习器叫做初级学习器,用于结合的学习器叫做次级学习器或元学习器(meta-learner)。
我们贴一张周志华老师《机器学习》一张图来说一下stacking学习算法。
过程1-3 是训练出来个体学习器,也就是初级学习器
过程5-9是 使用训练出来的个体学习器来得预测的结果,这个预测的结果当做次级学习器的训练集
过程11 是用初级学习器预测的结果训练出次级学习器,得到我们最后训练的模型。
这个算法还可以有别的情况,那就是过程4,我们其实不用从一个空集开始构造次级训练集,我们可以把预测出来的结果当做一个特征,追加到我们的数据集当中。
Stacking的实现
方法一:
最先想到的方法是这样的,用数据集D来训练h1,h2,h3...,然后再用这些训练出来的初级学习器在数据集D上面进行预测得到次级训练集。 这样的想法是不行的,因为这样容易过拟合。用原始数据训练出来的模型再来预测原始数据,模型的预测情况肯定是非常不错的,但是在新数据上表现并不一定好。
方法二:
我们使用k折交叉验证的方法来得到次级训练集。将数据D分为k等份:D1,D2,D3....Dk。
for j = 1,2,...k: ,我们取数据集 D\Dj 作为训练集来训练模型h1,h2,h3...,然后让模型h1,h2,h3...预测Dj的值,并将这个值保存下来,最后所有保存下来值组成了。
def get_stacking(clf, x_train, y_train): result_set = np.zeros(x_train.shape[0]) kf = KFold(n_splits=10) for train_index, test_index in kf.split(x_train): clf.fit(x_train[train_index], y_train[train_index]) result_set[test_index] = clf.predict(x_train[test_index]) return result_set
但是看了别人写的关于stacking的文章以后,发现了一个误区,那就是我们预测了训练集的数据。对于测试集的数据(没有标签的测试数据,而不是将数据集划分出来的训练集和测试集的测试数据)我们也应该处理,否则到了第二层模型训练和预测的时候,训练集和测试数据的特征会不一样。
所以,改进代码如下:
def get_stacking(clf, x_train, y_train, x_test, n_fold=10): result_set = np.zeros(x_train.shape[0]) nfold_y_test = np.zeros((x_test.shape[0], n_fold)) y_set = np.zeros(x_test.shape[0]) kf = KFold(n_splits=n_fold) for i ,(train_index, test_index) in enumerate(kf.split(x_train)): clf.fit(x_train[train_index], y_train[train_index]) result_set[test_index] = clf.predict(x_train[test_index]) nfold_y_test[:, i] = clf.predict(x_test) y_test = nfold_y_test.mean(axis=1) return result_set, y_test
参考
Introduction to Ensembling/Stacking in Python
A Kaggler‘s Guide to Model Stacking in Practice