访谈:探索Kaggle大师的方法论和思维模式

在竞争性机器学习中取得好成绩需要什么?要真正深入探讨这个问题,你需要深入研究那些表现出色的人。

2010年,我参加了一场Kaggle竞赛,预测未来国际象棋比赛的结果。这是一个引人入胜的问题,因为它需要你从历史比赛中建模选手的等级分,并将这些等级分推演到未来进行预测。

我在比赛中表现平平(第17名,约10%),但Diogo Ferreira获得了第4名。Diogo是一个迷人且出色的沟通者,2011年我有幸采访了他关于他参加比赛的经历。本文是那次采访的编辑版本。

采访分为四个部分:

  • 第一部分探讨了Diogo的背景和解决问题的方法论
  • 第二部分关于Kaggle国际象棋等级分竞赛
  • 第三部分深入探讨了Diogo对国际象棋等级分竞赛的解决方案
  • 第四部分为我们留下了一些关于成为有竞争力的机器学习实践者的最终思考(最精彩的部分!)

拿杯饮料,坐下来,尽情享受!

第一部分:背景和方法论

Diogo Ferreira

Diogo Ferreira

Jason:您能自我介绍一下吗?

Diogo:我叫Diogo R. Ferreira,是里斯本理工大学(葡萄牙)信息系统教授,教授数据库系统、企业集成和业务流程管理(BPM)。我也是BPM领域的活跃研究员,尤其专注于流程挖掘,即与从信息系统记录的事件日志中提取流程模型相关的技术。

Jason:您的教育和工作经历中,有哪些经验对您参与国际象棋等级分竞赛并取得成功有所帮助?

我的研究领域流程挖掘与商业智能和数据挖掘领域相关,这让我接触到一系列技术,这些技术通常可以进行调整或作为灵感来源来解决不同的问题。

至于国际象棋等级分竞赛,我长期以来对国际象棋很感兴趣,这让我对这次比赛特别有动力。

Jason:您对流程挖掘的描述让我想起了挖掘网络服务器日志并将结果与网站流程关联起来。

正是如此,我们做的就是这种事情,只不过我们处理的是事件日志(即信息系统记录的事件),这些日志可能来自支持流程的系统(如工作流/BPM系统),也可能来自其他系统(如应用服务器日志)。

Jason:对于我这样不熟悉流程挖掘的人来说,有什么大家可能熟悉的例子或典型案例研究吗?

作为介绍,我或许可以向您推荐最近发布的流程挖掘宣言(PDF)。

至于一些案例研究示例,您可以参考我自己的出版物。在流程挖掘网站上还有更多内容。

Jason:您最近有没有将商业智能(BI)和数据挖掘技术应用于您的工作中,如果有,它们是为了解决什么类型的问题?

序列聚类、期望最大化、序列分析、图分析是我用于或改编用于流程挖掘应用的技巧。

Jason:通常,当您遇到新的数据集(无论是评级数据还是其他数据)时,您从何开始,您的方法论是什么?

首先,我通常会开发一套简单的程序来从数据集中提取特征,以便更好地理解它。数据集通常太大,无法进行手动检查,因此,拥有一些基本工具来开始工作,对于确定下一步的方向非常有用。

然后,在我对数据有了感觉之后,我通常会尝试一些相当简单,甚至可能微不足道的方法,只是为了进行“健全性检查”,即验证结果是否符合我的预期,以增强对数据集的信心。

在我足够自信之后,我开始尝试更精细的方法。这些方法通常是我自己设计的。在后期,我通常会将我的结果与其他人众所周知的方案或技术进行比较。

Jason:我觉得您的方法论描述非常引人入胜,谢谢。您最近使用了哪些工具或技术来从新数据集中提取特征?

为了从新数据集中提取特征,我主要使用特设的自定义代码,并且我发现使用 Python 和相关库(如 numpy、matplotlib、networkx 等)非常高效。

Jason:在这种情况下,您所说的特征是什么意思?(摘要统计?数据中的结构?预测规则?)

精确地说是摘要统计,以及/或寻找数据集中共性和频繁行为的方法。

Jason:如果您可以手动检查数据集,您都使用过哪些示例或工具来完成此操作?

我只使用简单的搜索和查找/查找所有/查找文件/grep 功能,就像大多数文本编辑器中提供的那样。

Jason:在处理数据问题时,您会在哪些类型的任务中准备定制代码和脚本,又会在哪些类型的任务中求助于工具和库?

我经常尽可能多地自己编写代码,即使有类似的代码可用。这是因为逐步开发代码也是了解数据的一种方式。

我求助于工具和库,尤其是在我想将我的结果与其他人或竞争方法的结果进行比较时。

Jason:您提到:“逐步开发代码是了解数据的一种方式”,这非常有趣。如果可能,您能详细说明一下吗?(例如,您指的是具体内容,例如:原型化想法?犯错误?探索死胡同?思考时间?发现边缘案例?)

当我开始处理数据时,我通常会花时间检查每一步中间代码是否按预期工作,在这个过程中,我学到了很多关于数据本身的知识。我通常不会探索死胡同或边缘情况,我只是借此机会在途中停几次(即,如果将编码比作开车,我会说我会偶尔停下来看看风景,而不是直接开到目的地)。

Jason:您对谜题、机器学习、算法、编程、统计学、数学、心理学这些领域有多大兴趣?

我对所有这些领域都有普遍的兴趣,但我通常被手头的特定问题所激励,无论领域如何。我对这些领域中的所有问题都不感兴趣,但我可能对来自不同领域的一些特定问题感兴趣。

Jason:通常,您在处理常见数据任务时会反复使用哪些方法?

我想说,由于我的研究领域(流程挖掘),我会经常回到文本/字符串处理和图分析,而且我发现这些技能在解决不同问题时通常很有用。

Jason:在您的工作中,对于 a) 文本/字符串处理和 b) 图分析,您觉得哪些技术、工具和/或库很有用?

对于文本/字符串处理,我使用 Python 标准模块中提供的简单函数(find、split 等)。

对于图分析,使用 networkx 和 Graphviz 等专业库通常很有用。

Jason:您在不同问题中以什么有创意的方式或最近的例子使用了文本/字符串处理和/或图分析?

最近我一直在分析来自两家不同医院的事件日志,我正是使用了那些工具/技术。

Jason:通常,当您的方法没有得到预期结果时,您如何保持动力?

我可能会觉得这种方法有问题,在这种情况下,我尝试修复它。或者,如果它没有问题,那么我就开始考虑一个完全不同的方法来解决同一个问题。无论哪种方式,这通常能让我保持动力。

Jason:您认为在这样的数据竞赛中,哪些技能能让参与者具有竞争力?

我认为,一个有竞争力的参与者,与其说需要技能,不如说需要坚定的、不可动摇的动力。我见过非常有技能的人甚至不投入努力,而技能较差的人则会尝试各种方法,其中一些最终证明是有效的。所以,这无关乎一个人知道多少,而在于一个人愿意付出多少努力。

Jason:我对您的“动力与技能”哲学很感兴趣,能否进一步探讨一下?您能否谈谈“创造力及/或思想的多样性”和“尝试不同事物的适应性”比“原始技能、智力、经验”更有用(请原谅我简洁的概括)?

一个基本事实是,最终,重要的是事情是否完成。技能意味着做这件事的潜力,但只有动力才能让人开始做这件事。

事情通过结果来评估,这意味着在某些情况下会有不幸的后果,比如有些人投入了大量时间却最终没有得到结果。这就是技能发挥作用的地方:它使人们更有可能从投资中获得一些成果。

但仅仅有技能不足以应对某些挑战的复杂性。即使有技能,手头的任务也可能很困难,这就是动力再次发挥作用的地方。它让人开始,并让人坚持下去。当然,一辆法拉利(更高的技能)会让人更快到达那里,但这并不意味着不能用一辆装备较差的车辆,甚至一辆不能在同一条道路/路径上行驶的车辆到达那里。如果到达那里是唯一重要的事情,那么开哪辆车或走哪条路就无关紧要了。拥有汽油(动力)到达那里比拥有一辆快车(技能)更重要。

Jason:在解决数据问题时,模型调优可能在某个环节发挥作用,如何才能在新模型尝试和对有前景的模型进行调优之间找到一个富有成效的平衡点?

改进的速度告诉我们何时改变策略。当改进速度开始下降时,就该开始考虑新模型了。

Jason:通常,您是更喜欢花时间调优一个给定的模型来解决数据问题,还是尝试不同的模型?

我个人更喜欢花时间尝试不同的模型,但实际上,当一个模型看起来很有前景时,我经常投入大量时间对其进行调优,这导致我尝试不同模型的时间比我希望的要少。在国际象棋比赛中就是这样,尽管我考虑过尝试其他方法,但最终我大部分时间都花在了调优和改进一个单一模型上。

Jason:您认为模型调优为何不如探索新模型令人满意(例如,增量收益与替代范式)?

因为人们可能会花大量时间进行调整,但最终仍然受限于原始模型的假设。比如说,通过调整获得了20%的改进,而使用新模型可能会获得50%的改进。突破性思维,如果可能的话,通常会带来更高的回报——至少这是我个人的感受。

第二部分:国际象棋等级分竞赛

White vs Black

白方对黑方
照片由Gideon拍摄,保留部分权利

Jason:您提到您长期以来对国际象棋感兴趣,这种兴趣是什么?您有多久了?

在我青少年时期,我曾参加国际象棋比赛,今天我仍然关注国际象棋界的动态,尽管我不再是活跃的棋手。偶尔,我仍然会在线下棋,这是我在青少年时期希望能够实现的事情。

Jason:用您自己的话来说,国际象棋等级分比赛需要解决的问题是什么?

在我看来,国际象棋等级分竞赛的目的是设计一个评级系统,为评级选手之间的比赛结果提供更准确的预测。

Jason:我读到您是从纸笔开始的,您在最初开始比赛时在思考或探索什么?您是如何抵制直接打开电脑编写脚本的冲动的?

当我第一次开始考虑这场比赛时,我正在寻找一个合适的概率模型,我在纸上潦草地写了一些东西,有时相同的公式会一遍又一遍地出现。

同时,我开始编写一些简单的任务,例如读取/解析数据并获取一些汇总统计信息。

过了一段时间,我开始定期在编码和在纸上乱涂乱画之间切换,两个方面的事情都进展得很快。

Jason:从高层次上讲,请总结您在比赛过程中的线性步骤?

我的方法的基础模型开发得相当快,在整个比赛过程中,我基本上使用了相同的模型,只是偶尔有一些变动。

我花时间开发的是一个合适的加权函数,以考虑时间因素(即,最近的比赛比旧的比赛更重要)

我尝试了几个选项,在私有数据集上我观察到了一些改进,尽管公开分数几乎没有提供我是否走在正确轨道上的信心。

Jason:在比赛过程中,您参与了哪些合作,与谁合作?(电子邮件交流、论坛讨论等)

我只是和一位同事进行过几次简短的交流,讨论了比赛以及数据挖掘、过拟合等一般性问题。在这些对话中,我们主要讨论了比赛的设置方式,而不是具体的方法。我还记得有人建议我使用正态分布作为加权函数,但最终我设计了自己的函数。

Jason:我读到您原本预计在比赛上花几天时间,是什么让您投入了这么长时间?

这有两个主要原因:

  1. 每天在公共排行榜上看到其他人的进展,并将其与我自己的进展进行比较,让我对这次比赛感到非常兴奋。
  2. 我自己的交叉验证结果与公共排行榜上的结果之间几乎没有相关性。这让我忙了一段时间,因为我不确定我的方法最终会表现如何。

Jason:用简单的话来说,您解决比赛中提出的问题(最成功)的方法是什么?

我认为这是最简单的方法,即当我将代码简化到真正基本且我认为坚实的基础时。其他想法,例如为了获得一些改进而进行的巧妙修正,结果证明非常耗时,并且带来的额外回报很少。

Jason:在比赛过程中,您进行了哪些数据汇总和数据可视化(如果有的话)?

我使用了 networkx Python 库来研究数据集中玩家之间的连接(游戏)。

除此之外,我还使用了诸如每月比赛数、每玩家每月比赛数等汇总统计数据。

Jason:您在比赛过程中(如果有的话)将哪些经典的国际象棋等级分计算方法应用于数据集?

我一个都没用。我的想法始终是为每个玩家获得一个介于 0.0 和 1.0 之间的归一化等级。

Jason:您发布了您方法的详细描述和源代码——为什么您在描述上投入了如此大的精力,并免费发布了代码?

嗯,我习惯于撰写科学论文,以这种形式呈现描述对我来说很有意义。至于源代码,我认为几乎没有人会费心去实现这种方法,即使他们真的这样做了,也许他们也不会足够细心,以确保所有内容都按照最初的意图实现;这可能会导致我的方法报告的结果比我用自己的代码获得的结果更差。所以,为什么不直接发布源代码作为参考实现呢,就是这样。

Jason:回顾过去,您认为在这场比赛中,计算时间或计算机硬件对您或您的方法构成了限制吗?

当然是。我记得我的笔记本电脑曾经连续运行了几天。有一次我甚至尝试使用我们大学的服务器,结果却发现我的笔记本电脑运行得更快。参数调优通常需要数小时,甚至数天才能完成。我通常每隔一小时就会检查一下进展情况,甚至在半夜也会,我希望自己能有更多的机器来并行运行。

这种情况没有变得绝对关键的唯一原因是,我们每天只能提交两次,我觉得这是一个相当不错的规则。我记得我将我的实际提交次数除以同一时期我被允许提交的总次数,我得到一个接近50%的数字。所以总的来说,我认为我很好地利用了手头可用的提交次数。

Jason:请讨论一下您在公共排行榜上工作以及在您的私有数据集中观察到的差异。

如果我没记错的话,我将公共数据集的1到100个月划分为一个交叉验证数据集:1到95个月(训练)+ 96到100个月(测试)。(我还使用了1到90个月+91到95个月,以及其他划分方式)

发生的情况是,交叉验证数据集上更好的结果往往意味着在公共排行榜上更差的结果。也许之前的提交因为过拟合或只是运气而更好。无论如何,这并没有帮助我建立对所尝试事物的信心。交叉验证结果表明它肯定会更好,但公共排行榜却恰恰相反。在某个时候,我(以及其他许多参与者)开始觉得公共数据集和排行榜之间存在很大的差异。最终,我认为这仅仅是因为排行榜分数是根据相对少量的数据(20%)计算的。

Jason:您在私人结果中与公共排行榜相比,探索了哪些统计数据(例如,您是否探索了两者之间的相关性)?

我没有探索两者之间的任何相关性,因为看起来它们之间没有相关性。

至于统计数据,我记得比赛使用月度汇总RMSE作为误差衡量标准。我记得尝试使用其他衡量标准,例如每局的绝对偏差,每局的RMSE等。因此我做了一些参数调整,试图最小化这些其他误差衡量标准。然而,最终看来使用月度汇总RMSE效果更好。

Jason:根据您在数据中的观察,有哪些“巧妙修正”成功了,或者您后来又移除了?

举个例子:在某些比赛中,白方或黑方获胜的预测接近 1.0(例如 0.98 的概率)。所以我做的是设置一个阈值(例如 0.98),高于该阈值的结果将转换为 1.0。这有助于稍微降低整体预测误差,问题是阈值的选择非常敏感,所以我最终放弃了使用这种技巧。

Jason:您能回忆起从总结统计数据和数据探索中发现的任何有趣的观察吗?

我记得有一点是,最近几个月的比赛比以前几个月多得多。我想这也解释了为什么需要如此快速下降的时间函数。比赛太少很难得出结论,所以旧的比赛不太有用。然而,即使是最新的比赛也不多(总数),所以旧的比赛仍然对预测目的有用。我认为,这是为什么选择一个时间加权函数如此困难的另一个原因。

Jason:在您的整个参与过程中,您为什么一直专注于归一化评级?

因为我主要处理概率,直观上我也想将玩家的等级表达为一种概率度量(下文会有更多说明)。

Jason:您有没有记录或日志来记录您的想法或尝试?

我将每次提交的代码都保存到一个单独的文件中。然而,我有一个单独的程序用于参数调优,我并没有保存它的每个版本。在如此多的提交(最终超过100次)中,有时我不确定我之前是否已经尝试过某件事。

第三部分:关于您的具体解决方案的问题

graphs

我使用的时序加权函数的图表,Diogo的报告中对此进行了解释。

Jason:您的方法只有100多行 Python 代码(不含注释),我觉得这很了不起。您能用通俗的语言描述一下您的算法吗?

基本上,我将每个玩家 X 的实力估计为对抗一个通用参考玩家 Z 的预期得分。(这个参考玩家 Z 是一个抽象实体,它不存在,它的实力无需计算,它的目的只是将所有玩家的实力转化为可比较的条件。)

如果我们有每个玩家 X 对阵参考玩家 Z 的结果,我们就会有玩家 X 的评分,仅此而已。但是我们没有 X 对阵 Z 的结果,我们有的是 X 对阵一组对手的结果,而这些对手的实力也是未知的。

在我的方法中,我设计了一种基于对手实力计算X实力的方法。我们根据X的对手的对手的实力,以及X的对手的对手的对手的实力等等来计算X的对手的实力;它成为一个迭代算法,其中每个玩家的实力必须同时计算,并经过几次迭代,直到最终收敛。

在此基础上,我添加了一个时间加权函数,使旧游戏对结果的影响较小。

Jason:您的方法侧重于加权函数,您是从哪里开始的,它是如何随着时间变化的?

我从指数函数开始,然后是正态函数,然后是线性函数等等,直到我最终确定了报告中和图中(上方)所示的简单函数。

Jason:您的方法使用了布拉德利-特里模型,这个模型是什么,您是如何使用它的?

布拉德利-特里模型可能是“成对比较”(即根据玩家/团队之间的比赛估算实力)领域最古老的模型之一了。

它非常简单:给定两个玩家X和Y的实力,一个简单的公式提供了一个介于0和1之间的数字,可以将其视为X战胜Y的“概率”。参见我报告中的公式(1)。

在我的方法中,我直接使用了布拉德利-特里公式,其中我将每个玩家的实力视为战胜虚构参考玩家Z的概率,如上所述。

Jason:您在做出预测之前是如何探索玩家初始评级的收敛性的?

收敛很慢,这是我的方法中主要的计算问题。我想进行参数调优,但每次尝试不同的参数值时,我都必须等待很长时间,才能让整个过程(评分)再次收敛。无论如何,由于缺乏更快的方法,我尝试着接受它。

Jason:鉴于玩家的预测评级是基于其估计评级,您是否花费更多时间探索您的模型对评级估计还是评级预测的影响?

我花费了所有时间试图设计一种方法来估计玩家评级,以便在预测比赛结果时实现最低误差。我没有研究玩家评级不确定性的任何方面。然而,我倾向于认为TrueSkill之所以有效,是因为它包含了玩家评级的不确定性。

Jason:您尝试过哪些没有成功的想法或策略?

将布拉德利-特里模型扩展到平局不起作用。尽管我阅读了大量相关资料(其他作者的作品)并实现了它,尽管国际象棋结果充满了平局,但使用包含平局可能性的布拉德利-特里模型对我不起作用。我认为这是因为,总而言之,我们拥有的训练数据对于这个目的来说相对稀少。

Jason:在准备您的私有交叉验证训练/测试数据集时,您担心哪些问题?

我尝试了几个交叉验证数据集,因为我不确定哪一个最接近实际测试数据,我担心我的参数调优只会过度拟合到某个交叉验证数据集,而在实际测试数据中表现不佳。

我记得有一次,我通过对6个交叉验证数据集的结果取平均值来进行参数调优!

Jason:您在模型准备过程中是否过滤或排除了任何数据?如果没有,您是否考虑过排除较旧的数据?

我尝试抛弃一半的历史数据(最旧的一半),但对未来比赛的预测并没有变得更好。

Jason:我读到您使用了爬山法局部搜索来调整模型参数,您是手动选择初始值的吗?

是的,但我通常是根据之前的结果选择这些值。

Jason:您是否考虑过其他模型调优方法(全局搜索算法、非线性相互依赖假设、分层搜索)?

没有,我没有时间去阅读和实现其他优化算法,我只是想达到一个(局部)最大值,即使这需要使用最粗糙的方法。

Jason:我觉得很神奇的是,您又重新推导出了新的模型参数,使得最终排名分数超过了第一名。您为什么这样做(如果模型无法做得更好怎么办),您是否考虑过进一步探索这个问题(改变交叉验证套件的假设,进一步反向工程模型的改进)?

我这样做是因为我坚信,如果我的模型如此接近第一名,那么它肯定可以通过不同的参数选择超越第一名。但请注意,这个“好于第一名”的结果是过拟合到实际测试数据的。我相信其他参与者一旦拿到完整的测试数据,也能提高他们的分数。

另一方面,在比赛后的一封电子邮件中,杰夫·索纳斯(Jeff Sonas)写信给我,说最终得分的计算方式实际上存在问题。由于测试数据的准备和按玩家-月份聚合的方式,一些比赛在公共和私人测试数据之间共享。这可能影响了最终结果(例如,有利于一些过拟合公共测试数据的参与者)。

在同一封电子邮件中,杰夫写道,当他从测试数据中删除共享比赛时,我的方法排名第一。

第四部分:结局

Jason:您参加国际象棋评级比赛对您解决问题的整体方法论有何改变(如果有的话)?

总的来说,我觉得参加这次比赛让我对分析数据和从中得出结论变得更加谨慎。

能够预测未来的结果或许是发现一个人对数据了解多少的最佳方式。将模型拟合到数据并得出结论相当容易;但获得足够的知识来做出准确预测则要困难得多。

对数据中的不确定性程度(与一致性程度相比)形成一种感觉并不容易,这可能需要大量的时间和艰苦的工作。

最终,当一个人意识到存在多少不确定性时,他也能对任何预测固有的不确定性形成一个概念。超过某个点,一个非常准确的预测只能是纯粹运气的产物。

所以,看到别人的预测结果更好,不一定意味着他们的方法更好(即使这是一个很好的指标)。在不确定性中,他们只是碰巧更接近事实。

在这场比赛中,从公共排行榜到最终排名的位置变化,正说明了不确定性在这次比赛中发挥了多大的作用。当我第一次开始怀疑这一点时(甚至在比赛结束之前),我感到很震惊,这就是为什么我对数据做出明确的陈述变得更加谨慎。

Jason:对于刚开始参加数据竞赛的人,你有什么建议?

我认为一个人不应该轻易放弃自己的动力,直到他/她对比赛的真正利害关系以及数据的情况有了清晰的认识。

刚开始参加这类比赛时,可能会很快看到一系列结果,最好不要去想这些结果,直到自己的想法成熟。只有当我们认真尝试过之后,才应该开始关注别人的做法。

Jason:如果拥有几乎无限的资源(时间、金钱、博士团队),你理想化的数据竞赛通用策略或方法是什么?(你将如何充分利用资源?)

在我看来,并行计算只有在处理器之间的消息传递所需的计算能力远低于每个节点的实际计算能力时才值得。

所以,如果有几个人(或机器)一起解决同一个问题,但需要一直保持同步,那并没有什么帮助。

我发现真正有用的是思想交流。所以当不同的人独自解决同一个问题,并在认真思考一段时间后,他们会面交流想法,这通常会给讨论带来新的启发,并成为突破的源泉。

因此,作为团队合作的策略,我会让每个人独立工作,一旦他们准备好或需要,他们就应该会面交流经验和结果。这些会议可以重复进行几轮,我希望看到结果从一轮到下一轮有显著的改进。

Jason:你还有什么想说的吗?

这次比赛非常有趣,虽然它的实际意义仅限于国际象棋等级分,但我感觉我的努力得到了很好的利用。

鉴于这类比赛可以产生巨大的兴趣,我一定会花时间仔细检查这类比赛的设置方式,以确保每个人投入的所有努力都能为社区带来最大的益处。

进一步阅读

采访:探索 Kaggle 大师的方法论和思维模式的 2 条回复

  1. Hui 2014 年 10 月 17 日上午 4:25 #

    精彩的帖子,我现在还没读完,但只想说,真实的人,真实的比赛,真实的问题,这正是我在阅读了那么多机器学习理论博客/书籍之后所需要的。谢谢。

发表评论

Machine Learning Mastery 是 Guiding Tech Media 的一部分,Guiding Tech Media 是一家领先的数字媒体出版商,专注于帮助人们了解技术。访问我们的公司网站以了解更多关于我们的使命和团队的信息。