【Kaggle】竞赛入门:Titanic: Machine Learning from Disaster

前言

一直对大名鼎鼎的Kaggle竞赛有所耳闻,加上之前选修了《机器学习》课程并看了一点Ensemble Learning,所以趁着假期比较闲便想去了解一下Kaggle与数据分析。而Titanic大概是Kaggle领域里的Hello World与MNIST,因此打算先从它开始。不过因为这个竞赛我个人觉得是有一定门槛的,尽管机器学习算法都可以使用sklearn实现,数据的处理也可以通过pandas进行,但是数据分析与特征工程的难度还是不小的,Titanic从头到尾比着教程看下来也用了一整天的时间。
由于只是为了去了解基本的竞赛步骤,最后几乎完全是使用了《Kaggle Titanic 生存预测 – 详细流程吐血梳理》这篇博客里的代码,所以有需要的同学可以去看这篇博客。本文只是简单地总结一点个人的心得体会。

Kaggle竞赛

Overview of How Kaggle’s Competitions Work
From:https://www.kaggle.com/c/titanic/overview

  1. Join the Competition
    Read about the challenge description, accept the Competition Rules and gain access to the competition dataset.
  2. Get to Work
    Download the data, build models on it locally or on Kaggle Kernels (our no-setup, customizable Jupyter Notebooks environment with free GPUs) and generate a prediction file.
  3. Make a Submission
    Upload your prediction as a submission on Kaggle and receive an accuracy score.
  4. Check the Leaderboard
    See how your model ranks against other Kagglers on our leaderboard.
  5. Improve Your Score
    Check out the discussion forum to find lots of tutorials and insights from other competitors.

官网上其实说的挺清楚的,一般的步骤首先是选择一个比赛并阅读其Rule,里面可能涉及一些提交次数、组队限制的信息,然后下载数据并通过代码生成预测文件,提交预测文件系统会计算你的得分并且在Leaderboard上公布你的排名,最后我们可以进一步完善代码得到更好的预测刷新得分。不过一般来说,比赛过程中排名的验证只会用一半的测试用例,所以当前的排名其实不是你的最终排名,当比赛结束后会基于另外50%进行计算,得到最终排名。
简单的来说,步骤如下:
加入比赛→下载数据并通过代码获得预测→提交结果→查看排名→继续刷新得分

一般流程

这里基于上面提到的那篇博客,因为我的本次尝试也是基于它做的。

1. 数据总览

下载完数据后我们首先观察数据的基本组成,观察数据的基本结构,从而才能进行下面的步骤。

2. 缺失值处理

由于数据经常有残缺的属性,所以需要对缺失值进行处理。一般是通过pandas的info属性查看缺失值,通过合适的方法进行,比如删掉、均值、众数等等。

3. 分析数据关系

下面便可以开始分析数据之间的关系,能够粗略了解哪些特征会比较大程度的影响预测结果,这个过程还是挺麻烦的,需要大量的可视化操作,有利于数据特征的观察。
这样我们逐个分析与最终predict的属性的关系,在Titanic这个题目里是是否Survived,可以了解特征对于结果的影响。
划分
有的时候我们也经常需要查看一些数据本身的分布对数据进行划分,比如根据年龄将船上的人划分为儿童、少年、成年和老年,有点量化的感觉,这种思想在后面还会用到。
【Kaggle】竞赛入门:Titanic: Machine Learning from Disaster_第1张图片
【Kaggle】竞赛入门:Titanic: Machine Learning from Disaster_第2张图片
进一步剖析数据
对于一些数据分析过程中我们也要进行进一步剖析,比如名字可以转换为名字的长度,然后再与Survived与否寻找关联度。
对于缺失值
在Titanic例子里由于船舱的缺失值确实太多,有效值仅仅有204个,很难分析出不同的船舱和存活的关系,所以在做特征工程的时候,可以直接将该组特征丢弃。
当然,这里我们也可以对其进行一下分析,对于缺失的数据都分为一类。最后也能分析出一定的规律。

对于一些比较显然无关的特征可以选择性不进行分析。

4. 变量转换

这里我理解的可能也不是特别好,只是介绍下自己的心得吧。很多数据并不是数字,可能是字母或者字符串,例如Titanic里的登船地点和乘客姓名。
定性转换
常用的方法有通过Dummy Variables和Factorizing。
前者在我看来就是转换为onehot编码,比如下面这个图:
【Kaggle】竞赛入门:Titanic: Machine Learning from Disaster_第3张图片
主要应对与类别比较少的情况。而后者产生了一种映射,计算字符串与数字本身的映射,主要应对与类别比较多的情况。可以想象,如果对于类别比较多的数据使用onehot编码,那么会得到一个巨大的稀疏矩阵。
定量转换
本文参考的博客中的介绍就很到位了,“Scaling可以将一个很大范围的数值映射到一个很小的范围(通常是-1 - 1,或则是0 - 1),很多情况下我们需要将数值做Scaling使其范围大小一样,否则大范围数值特征将会由更高的权重。比如:Age的范围可能只是0-100,而income的范围可能是0-10000000,在某些对数组大小敏感的模型中会影响其结果。”
还有一个方法是Binning,类似于直方图的bin将数据划分为很多块,类似于上面年龄划分,能够将连续的数据离散化。一般来说,在将数据Bining化后,要么将数据factorize化,要么dummies化。

5. 特征工程

特征工程大概是Kaggle比赛的核心,对最后的效果影响巨大,这里推荐一篇博客:《使用sklearn做单机特征工程》,里面介绍的挺清晰的。
要注意一点,做特征工程的时候别忘了同时也要对测试数据进行处理。对数据进行特征工程,也就是从各项参数中提取出对输出结果有或大或小的影响的特征,将这些特征作为训练模型的依据。一般来说都会从含缺失值的特征开始。
特征工程要基于数据分析的结果,以及上面介绍的变量转换方法与缺失值处理方法。
例如,姓名可以提取其称谓并且合并,从而形成新的特征,这里显然是基于上面对姓名内容与分布分析的结果。然后还可以为所以条目基于姓名增加姓名长度这一个属性,也就是做特征的扩展。
有的特征需要做一些填充,比如票价就少了一个值,然后再通过binning划分等级。
特征如果与结果有一定相关性则不需要丢弃,如果是数值型的则需要做一定的处理,例如dummy、factorize。
有的特征完全可以进行合并,比如Titanic题目中亲友的数量,这里不过多介绍。
Age这个特征需要比较多的考虑,因为其缺失值比较多,而且有众数或平均数也不怎么合适。既可以根据称谓信息来填充,也可以综合几项如Sex、Title、Pclass等其他没有缺失值的项,使用机器学习算法来预测Age,甚至同时进行也可以,相当于集成学习嵌套了集成学习,这种设计可能也是Kaggle比赛的一个区分度吧。
Ticket通过观察有字母和数字之分,意味着不同的位置,对Survived产生一定的影响,所以我们将Ticket中的字母分开,为数字的部分则分为一类。
像Cabin这样缺失值比较多可以直接扔掉,因为本身也很难去分析与预测。
总结一下,上面的过程涉及到了特征扩展特征删除缺失项预测特征变量转换
当然,这样的特征工程显然太过于独立,所以我们还要研究特征间的相关性,可以挑选一些主要的特征,生成特征之间的关联图,查看特征与特征之间的相关性。相关性较强的在一些情况中完全可以进行合并从而实现降维。
上面的步骤主要是对于特征本身进行处理,在宏观层面进行优化,对于抛开特征本身,我们也要做一些与之没有直接关系的基本处理,或者说“善后工作”。比如数值正则化、训练数据与测试数据再次分开。

6. 模型融合及预测

完成了上面的特征工程便可以进行模型的组装了,也就是集成学习部分。一般的步骤如下:
选出较为重要的特征
这个过程利用不同的模型来对特征进行筛选,对特征的重要性进行排序。
构建训练集和测试集
在进行特征工程的过程中,产生了大量的特征,而特征与特征之间会存在一定的相关性。太多的特征一方面会影响模型训练的速度,另一方面也可能会使得模型过拟合。所以在特征太多的情况下,我们可以利用不同的模型对特征进行筛选,选取出我们想要的前n个特征。这样的结果同样可以进行可视化。
模型融合
参考博文中提到常见的模型融合方法有:Bagging(Random Forest使用了该思想)、Boosting(AdaBoost,Gradient Boost)、Stacking、Blending。
这个划分与西瓜书中稍有不同,如果我的理解没错的话,西瓜书的思路是将集成学习划分为串行式的Boosting和并行式的Bagging与Random Forest,然后对于基学习器结合时有平均法、投票法和学习法(Stacking),这个思路我觉得可能更好理解一些。
这里面Stacking用的应该比较多,比如对于这个问题,参考博客中使用的便是Stacking。它的结构Level 1使用了:RandomForest、AdaBoost、ExtraTrees、GBDT、DecisionTree、KNN、SVM ,一共7个模型,Level 2通过XGBoost第一层预测的结果作为特征对最终的结果进行预测。
验证:学习曲线
在测试集上表现不好可能是因为训练集的欠拟合,也可能是因为过拟合而失去泛化能力。所以我们要通过学习曲线来观察模型当前处于什么状态。这个过程对于Stacking框架中第一层的各个基学习器我们都应该对其学习曲线进行观察,从而去更好地调节超参数,进而得到更好的最终结果。
预测并生成提交文件
通过上面的模型便可以得到最终结果,提交到Kaggle平台即可。整个过程对代码能力的考验也是巨大的。别看是Kaggle里入门级的Titanic,它最终完成代码量还是不小的。

7. 进一步优化

有了baseline便要进行不断的优化,比如在一定程度上修改结构,或者进行合理的调参,这可能也是比赛过程中最耗时的阶段,只有合理的优化的才能取得较高的分数。

Titanic结果

根据上面提到的那篇博客的代码,最终得分和排名如下:
【Kaggle】竞赛入门:Titanic: Machine Learning from Disaster_第4张图片
这里也有个比较有趣的现象,很多人达到了1.0的准确率,我开始还是很奇怪的,不敢想象有效果这么完美的模型。后来发现因为Titanic的信息本身就是公开的,所以能够采取一些作弊的方法映射过去。不过这也就失去了比赛本身的意义了,只是得到了一个比较好看的分数。
另外Kaggle比赛中从论坛中学习也是很重要的,里面会分享很多好的方法甚至比较新奇的思路,比如我看到有人说从姓氏入手,如果一个家庭男人活下来了那么妻子和孩子活下来的可能性也很高,不过这只针题目中对这些数据了,泛化能力自然不会很高。

结语

虽然完全是照搬别人的代码,但本次尝试还是挺有艰难的,花了比想象中长很多的时间。不过收获也不少,比如Kaggle比赛的基本规则与步骤、特征工程、集成学习、sklearn和Pandas的使用甚至是jupyter notebook的使用。有时间还会再学习下别的题目,这种刷榜的比赛个人觉得还是挺有趣的。

你可能感兴趣的:(机器学习竞赛)