Kaggle模型融合

https://mp.weixin.qq.com/s/QVFwMzh2IyKeCjSJ6vjZeA

Kaggle比赛集成指南

集成模型是一种能在各种的机器学习任务上提高准确率的强有力技术。
在第一部分中,我们会讨论从提交文件中建立集成。主要包括:

  • 投票集成
  • 平均
  • 排名平均

第二部分我们会讨论 通过 generalization/blending等方法来创建集成。
我会在后续回答为什么集成能够减少泛化误差。最后我会展示不同的集成方法,包括它们的结果以及代码以供你自己去尝试。
怎样赢得机器学习比赛:你拿别人的结果和你自己的结果与做集成。 —— Vitaly Kuznetsov NIPS2014。

对提交文件进行集成

最简单方便的办法就是对Kaggle提交的csv文件直接进行集成。你只需要模型在测试集上的预测结果,而不需要重新训练一个模型。它简单快速,只需使用已有模型的预测结果,是拼队的理想选择。

投票集成(预测结果为类别时)

我们先看一下简单的投票集成方法。来看看为什么集成模型能够减少错误率,和为什么它能在模型间相关度较低时能取得更好的结果。

纠错码

在航天任务中,所有的信号都被正确的传达是非常重要的。
如果我们有一个二进制字符串形式的信号,如:

1
1110110011101111011111011011

如果信号在传输过程中有一位发生了翻转(第二位),变成了

1
1010110011101111011111011011

那这可能是致命的
在纠错码中有一个编码解决方案.在最简单的情况下,即纠错码是重复码时:以同样大小的数据块多次传递信号,并进行投票

1
2
3
4
5
6
7
8
9
10
11
12
13
Original signal:
1110110011

Encoded:
10,3 101011001111101100111110110011

Decoding:
1010110011
1110110011
1110110011

Majority vote:
1110110011

信号失真很少发生且通常在局部发生,因此,多次投票依然出错的可能性就更小了。
只要信号失真不是完全不可预测的(有50%的几率发生),信号就能被修复。

一个机器学习的例子

假设我们的测试集有10个样本,正确的情况应该都是1:

1
1111111111

我们有3个正确率为70%的二分类器记为A,B,C。你可以将这些分类器视为伪随机数产生器,以70%的概率产生”1”,30%的概率产生”0”。

下面我们会展示这些伪分类器通过投票集成的方法得到78%的正确率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
All three are correct
0.7 * 0.7 * 0.7
= 0.3429

Two are correct
0.7 * 0.7 * 0.3
+ 0.7 * 0.3 * 0.7
+ 0.3 * 0.7 * 0.7
= 0.4409

Two are wrong
0.3 * 0.3 * 0.7
+ 0.3 * 0.7 * 0.3
+ 0.7 * 0.3 * 0.3
= 0.189

All three are wrong
0.3 * 0.3 * 0.3
= 0.027

我们看到有44%的概率投票可以校正大部分错误。大部分投票集成会使最终的准确率变成78%左右(0.3429 + 0.4409 = 0.7838)。

投票个数

跟重复码相似,随着编码重复次数的增加对错误的校正能力也会增加,因此集成通常可以通过提高集成成员的个数来提升准确率.
pic1

同样利用上面数学的数学公式:对5个有70%准确率的伪随机分类器进行投票集成会得到83%的准确率。在大约66%的情况下投票可以校正1或2个错误编码。(0.36015 + 0.3087)

相关性

在我第一次组队参加2014年KDD杯比赛时,Marios Michailidis (KazAnova)提出了一些奇特的东西,他对我们所有的提交文件计算 皮尔逊相关系数,并且挑选出一些性能较好且相关系数较低的模型。

从这些挑选出来的文件中创建平均集成模型,给我们在排行榜上带来了巨大的提升,50名的飞跃。不相关的预测结果的集成明显比相关的集成结果要好,这是为什么?

为了说明这一点,我们再举3个简单的模型。正确的情况仍然是全是1:

1
2
3
1111111100 = 80% accuracy
1111111100 = 80% accuracy
1011111100 = 70% accuracy.

这些模型的预测是高度相关的,当我们进行投票时,可以看到准确率没有提高:

1
1111111100 = 80% accuracy

下面我们比较3个性能相对较差,但是高度不相关的模型:

1
2
3
1111111100 = 80% accuracy
0111011101 = 70% accuracy
1000101111 = 60% accuracy

但我们做集成进行投票得到的结果:

1
1111111101 = 90% accuracy

结果得到了提升:集成低相关性的模型结果似乎会增加纠错能力。

Kaggle案例:森林植被类型预测

当评价指标需要有力的预测时,比如多分类问题的准确率,少数服从多数投票法具有重要意义。

森林植被类型预测 比赛使用 UCI Forest CoverType 数据集。这个数据集有54个属性,6种分类类型。

我们建立一个有500棵树的随机森林模型作为 起始模型,然后我们再建立更多的模型,并挑选出最好的一个。在这个问题中,我们选择的一个ExtraTreesClassifier 模型表现得最好。

加权

接下来,我们讨论加权投票。为什么要加权?通常我们希望模型越好,其权重就越高。所以,在这里,我们将表现最好的模型的投票看作3票,其它的4个模型只看作1票。

原因是:当表现较差的模型需要否决表现最好的模型时,唯一的办法是它们集体同意另一种选择。我们期望这样的集成能够对表现最好的模型进行一些修正,带来一些小的提高。

表一是5个模型训练出来的结果,包括结果得分以及加权的得分。

pic2

Kaggle案例:CIFAR-10 图像检测

CIFAR-10是另一个用准确率衡量的多分类kaggle比赛。

这个比赛中,我们队的队长Phil Culliton,从dr. Graham那复制了一个好的模型,并第一个发现最好的参数设置。

然后他对大约30个提交文件使用了投票集成的方法(所有的准确率得分在90%以上)。在集成模型中最好的单模型的得分为 0.93170.

对30个模型的投票集成得分为0.94120.大约降低了0.01错误率的,使得其识别结果超过人类 estimated human classification accuracy.

代码

我们有一个简单的投票脚本 在 MLWave Github repo中找到. 它在kaggle的提交目录中运行,并负责创建一个新的提交文件。更新:Armando Segnini 已经加上了加权部分的代码。


Ensembling.训练10个神经网络并平均它们的预测结果,这是一个相当简单的技术,却有相当大的性能改进。

这里可能会有疑惑:为什么平均会有如此大的帮助?这有一个对于平均有效的简单的原因。假设我们有2个错误率70%的分类器,当2者结果一样时,那就是这个结果;当2者发生分歧时,那么如果其中一个分类器总是正确的,那么平均预测结果就会设置更多的权重在那个经常正确的答案上。

这个作用会特别强,whenever the network is confident when it’s right and unconfident when it’s wrong.——Ilya Sutskever在深度学习的简单概述中说道。


平均

平均可以很好的解决一系列问题(二分类与回归问题)与指标(AUC,误差平方或对数损失)。

与其说平均,不如说采用了多个个体模型预测值的平均。一个在Kaggle中经常听到的词是“bagging submissions”。

平均预测常常会降低过拟合。在类与类间,你想要理想的平滑的将其分离,而单一模型的预测在边界间可能会有一些粗糙。
pic3
上面这幅图片来自这个kaggle比赛:不要过拟合!图中黑线比绿线有更好的分割,绿色线已经从数据点中学习了一些噪声。但不用担心,平均多个不同的绿线应该使我们更接近黑线。

记住,我们的目标不仅是去记住这些训练数据(这里有比在随机森林里更加有效的方法来存储数据),而且还要去对我们没有看到的数据进行良好的泛化。

Kaggle案例: Bag of Words Meets Bags of Popcorn

这是一个电影情感分析竞赛,在以前的文章中,我们使用 在线感知机脚本 得到了0.952的AUC.

这个感知机是一个线性分类器,在数据线性可分的情况下一定能找到一个分隔。这是一个受人喜欢的性质,但是你要意识到一旦达到这种分隔,分类器就会停止学习。它不一定会是新数据的最好的分隔。

那当我们随机初始化5个感知机的权重,并通过平均来组合预测会发生什么?结果是我们在测试集上的结果得到了提升,但这是为什么呢?

pic4
以上结果还能说明,集成能(暂时)使您不必了解特定机器学习算法的更精细的细节与内部工作原理。如果集成起作用,那很好,如果没起作用,那并无大碍。
就算你平均10个相同的线性回归的结果也没事。Bagging一个糟糕的交叉验证与过拟合的提交有可能会增加多样性从而给你带来一点提高。

排名平均

当平均多个来自不同模型的输出时,会出现一些问题。并不是所有的预测器的结果是完美 校准的, 它们可能会产生过高或过低的预测概率,或者预测在一定的范围里非常混乱。

在极端情况下,你可能会有一个这样一个提交:

1
2
3
4
5
Id,Prediction
1,0.35000056
2,0.35000002
3,0.35000098
4,0.35000111

当评估指标是ranking或者像AUC一样的阈值时,这些预测结果可能会在排行榜上表现的较好。但是当与类似下面这个模型进行平均时:

1
2
3
4
5
Id,Prediction
1,0.57
2,0.04
3,0.96
4,0.99

集成不会改变什么。

我们的解决方案是:首先将预测结果进行一个排名,然后去平均这个排名。

1
2
3
4
5
Id,Rank,Prediction
1,1,0.35000056
2,0,0.35000002
3,2,0.35000098
4,3,0.35000111

在标准化平均排名在0到1之间后,你肯定会得到一个均匀分布预测。排名平均结果:

1
2
3
4
5
Id,Prediction
1,0.33
2,0.0
3,0.66
4,1.0

历史排名

排名需要一个测试集,所以当你要预测一个新样本时,你该怎么办?你可以与老的测试集一起,重新计算排名,但这会增加你的解决方案的复杂性。

一个解决方案是使用历史排名。存储旧的测试集预测及其排名,现在当你预测一个新的测试样例如“0.35000110”,你去找到最接近的历史预测并取其历史排名(在这里最接近的历史预测是“0.35000111”其历史排名为“3”)。

Kaggle使用案例:获得有价值的顾客挑战赛

排名平均在基于排名和基于阈值的指标(如AUC)和搜索引擎质量指标(如k平均精度)上表现良好。

这个 挑战赛的目标 是对一个购物者成为一个重复顾客的概率进行排名。

我们队首先将多个Vowpal Wabbit中的模型与一个R语言的GLMNet模型进行取平均,然后我们使用排名平均来提高完全相同的集成的情况。
pic5
我已经在 Avito挑战赛中写过排名平均给了我们大幅的提升 。

finnally, when weighted rank averaging the bagged perceptrons from the previous chapter (1x) with the new bag-of-words tutorial (3x) on fastML.com we improve that model’s performance from 0.96328 AUC to 0.96461 AUC.

Stacked Generalization & Blending

对预测文件进行平均既简单又好用,但这并不是顶级kaggle选手使用的唯一方法。stacking与blending也能让你颇受收益。做好心理准备,接来下将要给你介绍屠龙技。

Netflix

Netdlix公司曾组织并普及了第一次数据科学比赛,在电影推荐挑战赛中,参赛者们将集成发展成为了一门艺术,可能是太极端了以至于Netfilx公司决定不将获胜方案应用到产品中。 因为这实施起来太复杂了。

不过,这个比赛涌现了很多论文与新颖的方法:

  • Feature-Weighted Linear Stacking
  • Combining Predictions for Accurate Recommender Systems
  • The BigChaos Solution to the Netflix Prize

这些论文都比较有趣且可以阅读的,当你想要提高你在Kaggle比赛中的成绩时,可以点进去阅读一下。

这是我工作这么多年以来,最令人印象深刻的集成和看到的最好的成果,它融合了上百个预测模型来得到最终结果。我们在线下使用了一些新方法重新评估了一番,但是我们测试认为该模型对准确率提升效果似乎并不值得将它引入到生产环境——-Netflix 的工程师说。

Stacked generalization

Wolpert在1992的论文中对stacked generalization进行了介绍,比Breiman的论文 “Bagging Predictors“早了2年。Wolpert的另一成名的机器学习理论是:“没有免费午餐定理”

stacked generalization背后的基本思想是使用大量基分类器,然后使用另一种分类器来融合它们的预测,旨在降低泛化误差。

下面来说下2折stacking:

  • 将训练集分成2部分: train_a 与 train_b
  • 用train_b来拟合同类型的学习器对train_a进行预测
  • 最后用整个训练集拟合模型,并对测试集进行预测
  • 基于初级学习器的概率输出,来训练次级学习器

一个stacker模型通过使用第一阶段的预测作为特征,比相互独立的训练模型能够得到更多的信息。

我们通常希望在第0层泛化器是全类型的,而不仅仅是彼此的简单变化(比如我们想要 surface-fitters, Turing-machine builders, statistical extrapolators等等.)这样,所有可能学习到训练集规律的方法都会被使用到, 这就是所谓的初级学习器应该“跨越空间”意思的一部分.

[…]stacked generalization是将非线性泛化器组合从而形成新的泛化器的手段,是为了尝试最好的集成每个初级泛化器。每个学习器信息越多(在其他学习器上没有重复),stacked generalization的结果就越好

Blending

Blending 一词是Netflix的获胜者们引入的。它与stacked generalization非常像,但更简单并且信息泄露风险更小。一些研究者们交换着使用“stacked ensembling”与“blending”这2个词。

通过Blinding,不需要对训练集创建折外预测(out-of-fold predictions ),你只需创建一个小的留出集,比如10%的训练集做为留出。stacker模型只在留出集里面进行训练。

Blending的优势:

  • 比stacking更加简单
  • 能够防止信息泄露:generalizers和stackers使用不同的数据
  • 你不需要跟你的队友设定一个相同的随机种子来进行相同的分折 谁都可以将模型放入“blender”中,由blender来决定是否保留这个模型。

缺点:

  • 只使用了整体中数据一部分
  • 最终的模型有可能对留出集过拟合
  • stacking使用交叉验证比使用单一留出集更加稳健 (在更多的折上进行计算)。

至于性能,两种技术的得到的结果差不多,取决于你的个人喜好以及你更倾向于哪种技能。就我自己而言,我更喜欢stacking。

如果你不能做选择的话,你可以同时选择这2种,使用stacked泛化器创建stacked集成和折外预测。然后使用留出集在第三层进一步结合这些stacked模型。

Stacking 分类和回归

Stacking可以允许你使用分类器来完成回归问题,反之亦然。比如说,在一个二分类问题中,有人可能会尝试使用线性分位回归 来完成分类任务。一个好的stacker应该可以从预测中提取出你想要的信息,尽管回归通常并不是一个好的分类器。

而使用一个分类器做回归就有点棘手。你先离散化:将y均匀地分为几个的类别。那么一个要求你预测工资的回归问题就可以转换为这样的一个多分类的问题:

  • 所有低于20k的为类别1
  • 所有20k到40k之间的为类别2
  • 所有大于40k的为类别3

使用分类器预测出来的概率可以帮助回归函数取得更好的预测效果。

模型选择

你还可以通过组合多个集成模型来继续优化你评分。

  • 这有一个特别的方法:使用平均,投票,或秩平均等方法来手动选择表现好的集成模型。
  • 贪婪前向模型选择 (Caruana et al.)。先使用一个或几个好的模型作为基集成模型。然后不断地增加使得评分提升最大的模型。当然你也可以在期间允许把模型放回去,这样的话一个模型可能会被选择很多次。
  • 使用遗传算法来做选择,用交叉验证得分作为适应度评分函数。可以看 inversion‘s solution 的解决方案:‘Strategy for top 25 position‘.
  • 受Caruana的启发,我使用一个完全随机的方法:通过随机选择集成(无放回),创建一个100或其他个数的集成。然后选择其中评分最高的模型。

自动化操作

当我在 Otto product classification比赛中,使用了stacking策略,我很快的得到了前十的成绩。我通过不断的添加越来越多的基分类器,和bagging多个stack集成我的分数得到不断的提高。

当我达到了7个基模型,用了6个stacker,一阵恐惧和忧郁的感觉向我袭来。我是否能够把所有这些都重现?这些复杂而又笨重的模型让我偏离了快速而又简单的机器学习的初衷。

我在后续的比赛中,都将时间花在了建造一个自动化stacking的方法。我们去训练那些具有纯随机参数的纯随机算法的基模型。我们写了一个与Scikit-learn的Api协同工作的封装器去负责训练分类模型VW, Sofia-ML, RGF, MLP and XGBoost。

使用自动化stacking可以让你轻松的打败那些对该问题设计特定算法的领域专家,各个模型的训练都是可以分布式和并行化的。

你也可以在这里看到自动化融合的代码:MLWave Github repo: “Hodor-autoML“.

在Otto product 分类比赛中,第1名和第2名融合了超过1000个不同的模型 可以在这里看到更多: first place 和 second place。

我们为什么要使用如此复杂的集成方法?

使用stacking,组合1000多个模型,计算几十个小时这也太疯狂了吧。这..确实是的。但是,这些怪物般的集成方法同样有着它的用处:

  • 它可以使你赢得kaggle比赛
  • 它可以帮你打败当前学术界性能最好的算法
  • You can then compare your new-and-improved benchmark with the performance of a simpler, more production-friendly model
  • 总有一天,虽然现在的计算机和云端还是很弱。你将做好准备
  • 我们有可能将集成的知识迁移到到简单的分类器上(Hinton’s Dark Knowledge, Caruana’sModel Compression)
  • 不是所有基模型都要按时完成的。因为在集成方法中,即使损失一两个模型也是可以接受的。
  • 自动化的大型集成策略可以通过添加正则项有效的对抗过拟合,而且并不需要太多的调参和特征选择。所以从原则上讲,stacking非常适合于那些“懒人”
  • 这是目前提升机器学习效果最好的方法,或者说是最效率的方法human ensemble learning
  • 每1%精度的提升,或许就可以使得你的投资减少大量的损失。更严肃的说:在医疗行业中,每1%的提升,你就能多拯救几个生命。
-------------本文结束感谢您的阅读-------------