◆ ◆ ◆
介绍
“竞赛中的终极胜利源自于全力以赴的内在满足感。”
这是一次仅由学生参与的编程马拉松比赛(hackathon) -- “终极学生搜索”。一经发布就引起了爆发性的反响,来自世界各地的年轻的机器学习的冠军们竞相在冠军榜上争得一席之地。在竞赛的过程中,有接近1500名注册参与者,并进行了15000份结果的提交!在学生论坛中有超过20000份关于竞赛的信息交流。
老实说,起初我们既惊喜又惊讶于参赛者们的回应,并且觉得需要对学生论坛进行一些掌控。可事实证明我们完全是杞人忧天!代码的质量、解决方案的复杂性和思维过程的精湛性与可行性都让我们大吃一惊。可以很自信地说,机器学习的未来掌握在正确的人的手中。
为增强参赛者的体验,我们邀请了赢得过去两次AV编程马拉松的顶级数据科学家Rohan Rao进行了一场AMA(Ask Me Anything)。Rohan不仅很平易近人而且给了学生们巨大的启发。尽管我们联系他的时间距离这次AMA很短,可他也答应了,而且AMA持续了比约定更长的时间,并且还在结束的时候做了快速问答。
相信我,如果你没有参加这个独一无二的竞赛,你就错失了一个巨大的机会。为了分享知识,排名前五位的参赛者分享了他们的解决办法和代码。读接下来的内容看看你错失了什么,并且在那里可以加强改进。
◆ ◆ ◆
竞赛
这个竞赛在2016年9月24号发布,吸引了来自世界各地的数据科学学生进行了注册。竞赛持续了九天,所有的参赛者都无所顾虑的进行了比赛。我们发布这个竞赛是为了帮助学生们在机器学习编程马拉松里证明他们的气魄。我们被这些对机器学习有着无限热情的年轻人的互动震惊到了。
目睹着竞赛带来的骚动,学生们在开始之后还是持续的参与着。截至竞赛截止时间2016年10月2日23时59分,共有1494名参赛者。
参赛者被要求帮助Gardenia这个国家来理解他的国民的健康习惯。使用的评估度量是RMSE(方均根差)。问题的设定是为了让这些对数据科学热情的年轻人应用机器学习探索、创新。
◆ ◆ ◆
比赛任务
Gardenia是一个坚信需要在科技与自然资源之间寻求和谐的国家。在过去的几年中,他们想出了很多应用先进的科技来更有效地利用自然资源的办法。
这个保护了自然资源和花园的做法让他们引以为傲。接下来Gardenia政府就希望能够应用数据科学产生出一些关于国民健康习惯的见解。
Gardenia的市长想知道在特定的某一天有多少人访问了公园。他们提供一些相关的环境信息,并希望年轻的数据科学家们能帮助他们。
◆ ◆ ◆
获胜者
尽管这个竞赛很激烈、很具有挑战性,可总还是会有一些参赛者的解决方案与大多数人不同,并最终成为冠军。让我们给这些获胜的冠军们送上最诚挚的祝贺,这的确来之不易。
第一名 – Benedek Rozemberczki
https://datahack.analyticsvidhya.com/user/profile/benedekrozemberczki
第二名 – Aakash Kerawat & Akshay Karangale ( Team – AK )
https://datahack.analyticsvidhya.com/user/profile/aakashkerawat
https://datahack.analyticsvidhya.com/user/profile/Akki9011
第三名 – Mikel Bober ( a.k.a. anokas )
https://datahack.analyticsvidhya.com/user/profile/anokas
第四名 – Akhil Gupta
https://datahack.analyticsvidhya.com/user/profile/guptakhil
第五名 – Akash Gupta
https://datahack.analyticsvidhya.com/user/profile/akashgupta222
◆ ◆ ◆
冠军的解决方案
第五名:Akash Gupta (罗奥尔凯埃,印度)
Akash Gupta是印度罗奥尔凯埃IIT大学四年级的学生。他很热爱数据科学,并且参与了几个竞赛来测试他的知识与技能。
下面是他分享的内容:
我起初使用pad方法(直接复制前一行的数值)来处理缺失值,因为一个公园某一天的状况应该和前一天比较相似。更好的办法可能是分别对每一个公园做这个步骤。接下来在特征选择的过程中我发现月份和日期很大程度上影响并决定了脚步数。
我给冬季(11月,12月,1月,2月,3月)做了一个0/1特征。 至于日期我发现了一些规律:平均脚步数随着日期的增加而改变。遇到一些特例,我就把当日的脚步数与和他相邻的两天的脚步数加和进行平均(我把所有的公园和到一起来做的,更好的办法是把每一个公园分开对待)。同时,我把风向整合为四个方向。
建模的时候,我先用了Gradient Bossted Tree的方法,一点点的调试它以得到最好的结果(用2000-2001年做测试集)。接下来我试着用XGBoost并调试。最终,我采取了一个隐藏层的神经网络和一个宽隐藏层。我把三个模型的结果进行了平均得到了最终的结果。
除此之外,在用gradient boosting和xgboosting模型是,我分别对每一个公园进行了回归,因为我相信每一个公园的特征和与其它变量的关系都不相同。而在神经网络模型中,我把公园的ID作为一个变量放进了模型(即该模型是对所有公园的)因为需要一个大一些的训练集。
代码链接(https://github.com/analyticsvidhya/The_Ultimate_Student_Hunt/tree/master/Rank%204)
第四名: Akhil Gupta(鲁尔基,印度)
Akhil Gupta是IIT Roorkee大四的学生,对于深度数据科学研究很感兴趣,他希望能在年轻人中普及数据科学。而他也和我们分享了他的方法:
我的方法挺简单直接的。我着重把精力都花在数据预处理上了,具体的模型实现上反而没花那么多时间。这是个平衡数据集,有连续变量也有类别变量。
一开始我一直在处理缺失值,因为有些变量40%的数据都缺失了。通过观察我发现一个公园的特征都和那一天同一地点的其他公园相关。所以我的第一个解法只用了日期,月份和公园ID。这个答案当时在排行榜上得分是146。后来我继续处理缺失值,增加了一些特征,单凭这些分数就提高到到了113。
我清理了一些数据上的噪音,并把所有的变量都按比例转变到0到10之间,因为不同特征原本的值域差别挺大的。
将类别变量分区也很重要,因为当你用Boxplot观察它们的中位数时,你就能发现不同公园、月份和日期之间都有很大的相似度。我没有在模型上花太多时间,只试了Gradient Boosting Regressor,我觉得如果在调参之后用XGB可以让分数再提高一些。
交叉验证也是关键。我用了2000-2001的数据验证我的模型。
相信我,这个数据集很有意思,让我忙了四五天呢。我还算放松,但是LB排行榜的压力给了我很多努力的动力。
代码连接(https://github.com/analyticsvidhya/The_Ultimate_Student_Hunt/tree/master/Rank%204)
第三名:Mikel Bober(伦敦,英国)
Mikel Bober,也就是anokas,是一位年轻的机器学习冠军,年纪轻轻的他却已名声在外了,他是Kaggle天才,就连专业人士也都称赞不绝。这次比赛他全程都活跃在论坛里,给所有参赛者分享他的知识和看法:
我在任何比赛里做的第一件事就是先提交一个基础模型来验证数据集,并且用它的得分作为后续复杂模型的参照。我最先试的是XGBoost,我知道这里不能用随机分离,因为我们预测的是一个时间序列。
我把训练集按照时间分为训练和验证集,用训练集里最后三年的数据作为验证集。最初的模型验证的时候RMSE是190,在排行榜上得分是220。这之后我做了些简单地的特征工程。一开始最明显的失误就是没有把日期变量考虑进来,因为它不是数值变量所以我最开始就把它排除了。我把特征按公园划分了,这样XGBoost可以更好地对每个公园建模。之后我又在XGBoost里加了一个衡量特征重要性的函数。我看了一下各个特征的重要性得分,没想到风向竟然是最重要的。
做了最初的特征工程之后我就想花时间想一些新的,很重要的特征。我发现像强行盯着各种图这样并不能有新的发现,相反,如果我退一步重新审视问题,从更简单的角度出发,往往能发现别人想不到的。你得问问自己“有哪些事情会影响人们去公园?”
我的结论是,如果一周内连续下了很久的雨很能影响人们去公园。所以我创建了“lead”和“lag”变量,把过去两天和未来两天的特征也作为当下时间的特征。这么做很成功,我的得分一下子就提高到109了。
而为了把天气用进模型,我写了一个爬虫爬天气网站的数据,爬到了印度主要城市从90年代以来的天气数据。然而这些数据似乎全都没用,我进入了一个死胡同。但即使很有可能失败,也不能害怕去尝试。那些最终获胜的人也是尝试过更多失败特征的人,但他们不会因为失败就止步不前。
在任何比赛里我的最后一步都是做一个集成模型。这次的集成模型很简单,我在Keras里用了一批神经网络。我把每一层的权重都存了起来,在神经网络走完的时候取这些权重中损失值(loss)低于某一标准的值,用这些权重的平均值作为最终神经网络的权重。最终,我用了两个模型的均值作为最后的提交。
完整的方法在这里(https://medium.com/implodinggradients/how-i-got-3rd-place-in-the-ultimate-student-hunt-3ecf827375a6#.op2t2q7kk)
代码连接(https://github.com/analyticsvidhya/The_Ultimate_Student_Hunt/tree/master/Rank%203)
第二名:Aakash Kerawat(鲁尔基,印度)和Akshay Karangle (鲁尔基,印度)
Aakash Kerawat和Akshay Karangle都是印度IIT Roorkee大四的学生。Aakash已经参加过很多次机器学习的竞赛了。这一次他们是组队一起参加的。
看看他们都说了些什么:
我们从研究数据和可视化目标变量与日期的关系开始,并且发现这两个变量有明显的关系。所以我们又从日期变量中创建了新的变量,像是星期,一年中的第几天,一个月中的第几天,月份和年份。用这些新特征和原始特征我们试着用了几个不同的模型,从线性模型到XGBoost,而XGBoost的表现最好,在公开的排行榜上得分是133.xx。
之后我们把连续型的天气变量拆分,创建像“平均风速”,“风向”等变量。直觉告诉我们还要把月份聚合成季度,因为不同季节公园的人流量会不同。作图的结果也表明不同季节公园的平均人流量明显不同。我们还根据提供的最大值和最小值,创建了对于气压、风速等变量的范围特征。这些新特征将预测结果提高到123.xx。继续调参之后分数又提高到118.xx。到这儿之后我们就找不到继续提高的办法了。我们还试过另一组特征,用了按照“公园ID及风向区间”,“公园ID及最小湿润指数”等分组的平均人流量,但这个模型过度拟合了。
为了得到更好的结果我们对数据做了更深入的研究,对日期和几乎其他所有变量做了图。从这些图里我们似乎感觉到有些噪音在里面。去除噪音的方法是用了这些变量的移动平均线(moving average/rolling means),参数是3.7和30天。这一步让我们的结果有了一大步提高,从118到了107.xx。不止于此,我们又想到了另一个特征,天气变量两天里的的“变化百分比”。因为我们想把这种两天内的天气变化加入到模型里。这使得我们的分数又进一步提高到了100.xx。然后我们调试了moving average的不同参数,测试它们在验证集上的表现,同时得避免过度拟合。最终的模型有大概43个变量,在公开的和私人的排行榜上分别有96.xx和86.xx的得分。
这次比赛让我们学到,正确的特征工程是提高比分的关键之一。
代码连接(https://github.com/analyticsvidhya/The_Ultimate_Student_Hunt/tree/master/Rank%202)
第一名:Benedek Rozemberczki (爱丁堡,英国)
Benedek Rozemberczki 在爱丁堡大学的数据科学研究组实习。而他在这个领域的专业知识和能力也让他成为了这次比赛的第一名。
来看看他说了什么:
让我早早领先的因素是对比赛的动力。每当其他组得分接近我的时候,我也总能够想到新的特征工程方法。
很关键的一点是如果面板数据(panel data)的时间序列除了季节性之外还相对平稳,xgboost能很好地处理数据的季节性。还有一点就是,如果能够聚集不同单位内的数据(across observational unit aggregates),就没有必要解决缺失值的问题了。用面板数据就能很好地做特征工程。
碰壁的时候坐在电脑旁漫无目地地敲代码并不能解决问题。我们得想办法获得新的灵感,哪怕是用白板组织思路都是有用的。
理解缺失值总会有帮助的,这次比赛也是。
自动化数据处理的过程:自己写一些hot-one encoders和归一化函数。我渐渐的在各种数据科学的项目里用了自己写的函数,我觉得有一套在各种地方都能用的函数是很重要的。
原文发布时间为:2016-10-27
本文来自云栖社区合作伙伴“大数据文摘”,了解相关信息可以关注“BigDataDigest”微信公众号