一个实例告诉你:Kaggle 数据竞赛都有哪些套路

前面写了很多篇理论,大家愿意一篇一篇坚持看下来其实挺不容易的,虽然理论很重要,但脱离了实践还是空中楼阁啊,算法科学家也不可能不代码啊,所以呀,今天我们就插播一期实践,和大家聊一聊实际过程当中机器学习算法的应用。

对于我们这些初学者或者说外行来说,因为我们没机会接触到机器学习真正的应用项目,所以一些比赛平台往往是我们不错的选择,比如说这个Kaggle啊,前一段时间被Google收购还挺火的,还有国内的天池啊,DataFountain啊,上面都有不少比赛可以选择,但是入门嘛,我们就从最简单的开始,就是那个被无数文章博客提到过的泰坦尼克幸存者估计,我自己也看过一些,但是觉得很多文章把一开始数据探索部分写得太重了,反而后面特征选择和模型调参讲的很少,我感觉这样有些本末倒置的感觉,数据和特征决定了我们的上限。这里呢,我主要想讲的就是完成一个数据竞赛的整个流程以及其中最常见的一些套路,希望可以帮助大家可以快速入门竞赛,以期取得好成绩或者给自己求职增添砝码。

下面进入正题:

首先我们先观察一下我们的数据,看看哪些可以构建为我们的特征

import pandas as pd
data=pd.read_csv('E:\Blog\Titanic\Train.csv')
data.info()
data.describe()  

所有的数据中一共包括12个变量,其中7个是数值变量,5个是属性变量,接下来我们具体来看一看。

PassengerId:这是乘客的编号,显然对乘客是否幸存完全没有任何作用,仅做区分作用,所以我们就不考虑它了。

Survived:乘客最后的生存情况,这个是我们预测的目标变量。不过从平均数可以看出,最后存活的概率大概是38%。

Pclass:社会经济地位,这个很明显和生存结果相关啊,有钱人住着更加高级船舱可能会享受着更加高级的服务,因此遇险时往往会受到优待。所以这显然是我们要考虑的一个变量。

Name:这个变量看起来好像是没什么用啊,因为毕竟从名字你也不能看出能不能获救,但是仔细观察数据我们可以看到,所有人的名字里都包括了Mr,Mrs和Miss,从中是不是隐约可以看出来一些性别和年龄的信息呢,所以干脆把名字这个变量变成一个状态变量,包含Mr,Mrs和Miss这三种状态,但是放到机器学习里面我们得给它一个编码啊,最直接的想法就是0,1,2,但是这样真的合理吗?因为从距离的角度来说,这样Mr和Mrs的距离要小于Mr和Miss的距离,显然不合适,因为我们把它看成平权的三个状态。

所以,敲黑板,知识点来了,对于这种状态变量我们通常采取的措施是one-hot编码,什么意思呢,有几种状态就用一个几位的编码来表示状态,每种状态对应一个一位是1其余各位是0的编码,这样从向量的角度来讲,就是n维空间的n个基准向量,它们相互明显是平权的,此例中,我们分别用100,010,001来表示Mr,Mrs和Miss。

Sex:性别这个属性肯定是很重要的,毕竟全人类都讲究Lady First,所以遇到危险的时候,绅士们一定会先让女士逃走,因此女性的生存几率应该会大大提高。类似的,性别也是一个平权的状态变量,所以到时候我们同样采取one-hot编码的方式进行处理。

Age:这个变量和性别类似,都是明显会发挥重要作用的,因为无论何时,尊老爱幼总是为人们所推崇,但年龄对是否会获救的影响主要体现在那个人处在哪个年龄段,因此我们选择将它划分成一个状态变量,比如18以下叫child,18以上50以下叫adult,50以上叫elder,然后利用one-hot编码进行处理。不过这里还有一个问题就是年龄的值只有714个,它不全!这么重要的东西怎么能不全呢,所以我们只能想办法补全它。

又敲黑板,知识点又来了,缺失值我们怎么处理呢?最简单的方法,有缺失值的样本我们就扔掉,这种做法比较适合在样本数量很多,缺失值样本舍弃也可以接受的情况下,这样虽然信息用的不充分,但也不会引入额外的误差。然后,假装走心的方法就是用平均值或者中位数来填充缺失值,这通常是最简便的做法,但通常会带来不少的误差。最后,比较负责任的方法就是利用其它的变量去估计缺失变量的值,这样通常会更靠谱一点,当然也不能完全这样说,毕竟只要是估计值就不可避免的带来误差,但心理上总会觉得这样更好……

SibSp:船上兄弟姐妹或者配偶的数量。这个变量对最后的结果到底有什么影响我还真的说不准,但是预测年纪的时候说不定有用。

Parch:船上父母或者孩子的数量。这个变量和上个变量类似,我确实没有想到特别好的应用它的办法,同样的,预测年龄时这个应该挺靠谱的。

Ticket:船票的号码。恕我直言,这个谜一样的数字真的是不知道有什么鬼用,果断放弃了。

Fare:船票价格,这个变量的作用其实类似于社会地位,船票价格越高,享受的服务越高档,所以遇难获救的概率肯定相对较高,所以这是一个必须要考虑进去的变量。

Cabin:船舱号,这个变量或许透露出了一点船舱等级的信息,但是说实话,你的缺失值实在是太多了,我要是把它补全引入的误差感觉比它提供的信息还多,所以忍痛割爱,和你say goodbye!

Embarked:登船地点,按道理来说,这个变量应该是没什么卵用的,但介于它是一个只有三个状态的状态变量,那我们就把它处理一下放进模型,万一有用呢对吧。另外,它有两个缺失值,这里我们就不大动干戈的去预测了,就直接把它定为登船人数最多的S吧。

好的,到这里我们对所有变量应该如何处理大致有谱了,状态变量进行one-hot编码,那数值变量呢,直接用吗?

知识点!对于数值变量,我们通常会先进行归一化处理,这样有利于我们加快收敛速度,将各个维度限制在差不多的区间内,对一些基于距离的分类器有着非常大的好处,但是对于决策树一类的算法其实就没有意义了,不过这边我们就对所有的数值变量都做一个归一化处理吧。

到了这里,想必思路已经很清晰了,下面我们再梳理一下过程:

1 剔除PassengerId,Ticket这两个个变量,我们不用。

2 将Embarked变量补全,然后对Survived,Name,Sex, Embarked进行one-hot编码。

3对Pclass,Fare,Sibsp和Parch进行归一化处理。

3 根据Name,Sex,SibSp,Parch预测age将其补全。

4 对age进行归一化处理。

5 将未编码的Survived提出当做目标变量。

具体的代码实现如下:

import pandas as pd
data=pd.read_csv('E:\Blog\Titanic\Train.csv')
#剔除变量
data.drop(['PassengerId','Ticket'],axis=1,inplace=True)
#补全Embarked变量
data.loc[data.Embarked.isnull(),'Embarked']='S'
#one-hot编码
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import LabelEncoder
#ohe_pclass=OneHotEncoder(sparse=False).fit(data[['Pclass']])
#Pclass_ohe=ohe_pclass.transform(data[['Pclass']])
le_sex=LabelEncoder().fit(data['Sex'])
Sex_label=le_sex.transform(data['Sex'])
ohe_sex=OneHotEncoder(sparse=False).fit(Sex_label.reshape(-1,1))
Sex_ohe=ohe_sex.transform(Sex_label.reshape(-1,1))
le_embarked=LabelEncoder().fit(data['Embarked'])
Embarked_label=le_embarked.transform(data['Embarked'])
ohe_embarked=OneHotEncoder(sparse=False).fit(Embarked_label.reshape(-1,1))
Embarked_ohe=ohe_embarked.transform(Embarked_label.reshape(-1,1))
def replace_name(x):
    if 'Mrs' in x:
       return 'Mrs'
    elif 'Mr' in x:
        return 'Mr'
    else:
        return 'Miss'
data['Name']=data['Name'].map(lambda x:replace_name(x))
le_name=LabelEncoder().fit(data['Name'])
Name_label=le_name.transform(data['Name'])
ohe_name=OneHotEncoder(sparse=False).fit(Name_label.reshape(-1,1))
Name_ohe=ohe_name.transform(Name_label.reshape(-1,1))
data['Sex_0']=Sex_ohe[:,0]
data['Sex_1']=Sex_ohe[:,1]
data['Embarked_0']=Embarked_ohe[:,0]
data['Embarked_1']=Embarked_ohe[:,1]
data['Embarked_2']=Embarked_ohe[:,2]
data['Name_0']=Name_ohe[:,0]
data['Name_1']=Name_ohe[:,1]
data['Name_2']=Name_ohe[:,2]
#归一化处理
from sklearn.preprocessing import StandardScaler
Pclass_scale=StandardScaler().fit(data['Pclass'])
data['Pclass_scaled']=StandardScaler().fit_transform(data['Pclass'].reshape(-1,1),Pclass_scale)
Fare_scale=StandardScaler().fit(data['Fare'])
data['Fare_scaled']=StandardScaler().fit_transform(data['Fare'].reshape(-1,1),Fare_scale)
SibSp_scale=StandardScaler().fit(data['SibSp'])
data['SibSp_scaled']=StandardScaler().fit_transform(data['SibSp'].reshape(-1,1),SibSp_scale)
Parch_scale=StandardScaler().fit(data['Parch'])
data['Parch_scaled']=StandardScaler().fit_transform(data['Parch'].reshape(-1,1),Parch_scale)
#预测年纪并补全
from sklearn.ensemble import RandomForestRegressor
def set_missing_age(data):
    train=data[['Age','SibSp_scaled','Parch_scaled','Name_0','Name_1','Name_2','Sex_0','Sex_1']]
    known_age=train[train.Age.notnull()].as_matrix()
    unknown_age=train[train.Age.isnull()].as_matrix()
    y=known_age[:,0]
    x=known_age[:,1:]
    rf=RandomForestRegressor(random_state=0,n_estimators=200,n_jobs=-1)
    rf.fit(x,y)
    print rf.score(x,y)
    predictage=rf.predict(unknown_age[:,1:])
    data.loc[data.Age.isnull(),'Age']=predictage
    return data,rf
data,rf=set_missing_age(data)
Age_scale=StandardScaler().fit(data['Age'])
data['Age_scaled']=StandardScaler().fit_transform(data['Age'].reshape(-1,1),Age_scale)
train_x=data[['Sex_0','Sex_1','Embarked_0','Embarked_1','Embarked_2','Name_0','Name_1','Name_2','Pclass_scaled','Age_scaled','Fare_scaled']].as_matrix()
train_y=data['Survived'].as_matrix()  

完成了我们的数据预处理和特征工程之后,就开始选择合适的机器学习模型来进行学习就ok了。

这很显然是个分类问题,那么我们现在可以的选择有逻辑回归(一个名字叫回归却干着分类器的活的家伙),决策树以及决策树提升的一些算法(包括什么GDBT,AdaBoost,RandomForest等等),还有SVC,甚至聚类算法我们都可以试试……不过呢,花板子我们就不玩了,这里我们就选择逻辑回归,支持向量分类器,随机森林分类器和梯度提升分类器来做一下,看看它们在训练集上的表现如何:

#模型构造
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
x_tr,x_te,y_tr,y_te=train_test_split(train_x,train_y,test_size=0.3,random_state=0)
lr=LogisticRegression(C=1.0,tol=1e-6)
lr.fit(x_tr,y_tr)
print lr.score(x_te,y_te)
from sklearn.svm import SVC
svc=SVC(C=2, kernel='rbf', decision_function_shape='ovo')
svc.fit(x_tr,y_tr)
print svc.score(x_te,y_te)
from sklearn.ensemble import RandomForestClassifier
randomf=RandomForestClassifier(n_estimators=500,max_depth=5,random_state=0)
randomf.fit(x_tr,y_tr)
print randomf.score(x_te,y_te)
from sklearn.ensemble import GradientBoostingClassifier
gdbt=GradientBoostingClassifier(n_estimators=600,max_depth=5,random_state=0)
gdbt.fit(x_tr,y_tr)
print gdbt.score(x_te,y_te)  

输出的结果为

0.783582089552

0.832089552239

0.824626865672

0.813432835821

我们可以看出SVC的效果最好,当然这有一定的随机性在里面,那我们就改变一下划分训练集和测试集的种子,看看结果是否会发生变化,将Random_state的值改为1,输出为

0.768656716418

0.787313432836

0.779850746269

0.768656716418

整体的正确率都发生了下降,但SVC的效果依然是做好的,所以我们不妨用SVC做一个结果先提交了看看正确率如何。那要想用这个模型进行预测,那我们要对测试集的数据做和训练集数据同样的事儿,包括补全无效值,预测年龄,one-hot编码以及归一化等等,只有这样我们的训练模型才能最大限度的发挥它的作用。完成预测之后,我们要将对应的ID和预测结果写入一个csv文件提交,实现的代码如下:

#预测数据
data_test=pd.read_csv('test.csv')
data_test.drop(['Ticket'],axis=1,inplace=True)
data_test.loc[data_test.Embarked.isnull(),'Embarked']='S'
Sex_label_test=le_sex.transform(data_test['Sex'])
Sex_ohe_test=ohe_sex.transform(Sex_label_test.reshape(-1,1))
Embarked_label_test=le_embarked.transform(data_test['Embarked'])
Embarked_ohe_test=ohe_embarked.transform(Embarked_label_test.reshape(-1,1))
data_test['Name']=data_test['Name'].map(lambda x:replace_name(x))
Name_label_test=le_name.transform(data_test['Name'])
Name_ohe_test=ohe_name.transform(Name_label_test.reshape(-1,1))
data_test['Sex_0']=Sex_ohe_test[:,0]
data_test['Sex_1']=Sex_ohe_test[:,1]
data_test['Embarked_0']=Embarked_ohe_test[:,0]
data_test['Embarked_1']=Embarked_ohe_test[:,1]
data_test['Embarked_2']=Embarked_ohe_test[:,2]
data_test['Name_0']=Name_ohe_test[:,0]
data_test['Name_1']=Name_ohe_test[:,1]
data_test['Name_2']=Name_ohe_test[:,2]
data_test['Pclass_scaled']=StandardScaler().fit_transform(data_test['Pclass'].reshape(-1,1),Pclass_scale)
data_test.loc[data_test.Fare.isnull(),'Fare']=0
data_test['Fare_scaled']=StandardScaler().fit_transform(data_test['Fare'].reshape(-1,1),Fare_scale)
data_test['SibSp_scaled']=StandardScaler().fit_transform(data_test['SibSp'].reshape(-1,1),SibSp_scale)
data_test['Parch_scaled']=StandardScaler().fit_transform(data_test['Parch'].reshape(-1,1),Parch_scale)
train_test=data_test[['Age','SibSp_scaled','Parch_scaled','Name_0','Name_1','Name_2','Sex_0','Sex_1']]
unknown_age_test=train_test[train_test.Age.isnull()].as_matrix()
x_test=unknown_age_test[:,1:]
predictage=rf.predict(x_test)
data_test.loc[data_test.Age.isnull(),'Age']=predictage
data_test['Age_scaled']=StandardScaler().fit_transform(data_test['Age'].reshape(-1,1),Age_scale)
test_x=data_test[['Sex_0','Sex_1','Embarked_0','Embarked_1','Embarked_2','Name_0','Name_1','Name_2','Pclass_scaled','Age_scaled','Fare_scaled']].as_matrix()
predictions=model.predict(test_x).astype(np.int32)
result=pd.DataFrame({'PassengerId':data_test['PassengerId'].as_matrix(),'Survived':predictions})
result.to_csv('svc.csv',index=False)  

将结果提交到Kaggle的网站之后,我们发现我们的准确率是79.904%,居然已经进了20%了,还是蛮顺利的嘛,那么如何继续提升我们的成绩呢?最有效的方法莫过于构建新的特征,寻找更有效的特征永远是提升正确率的王道。当然了,也有一些简单的办法有可能能帮助我们提高成绩,那就是三个臭皮匠顶个诸葛亮。我们选择几个相关性不是很大的分类器,用它们预测的结果进行投票,往往一定程度上也能提高我们的成绩,比如下面这种做法:

from sklearn.ensemble import VotingClassifier
model=VotingClassifier(estimators=[('lr',lr),('svc',svc),('rf',randomf),('GDBT',gdbt)],voting='hard',weights=[0.5,1.5,0.6,0.6])
model.fit(x_tr,y_tr)
print model.score(x_te,y_te)  

输出为:

0.860830527497

测试集上的表现可真棒啊!!!这一下很大的鼓舞了我的信心,所以赶紧用这个模型做个结果提交一下看看。

结果,正确率变成了78.649%,正确率下降了,整段垮掉!!!前面说的那么有模有样,结果被无情的现实狠甩一记耳光啊……

不过最重要的还是这个思路,比如你可以和你的小伙伴各做一个模型,你们构建模型的思路肯定不一样啊,那么模型的相关性比较低,这样组合起来提升效果应该比较明显,我就强行这样圆一下吧。

其实我相信到这里大家也看出来了,做的这个模型我们还是把绝大数的时间花在了模型的构造上了,真正模型训练啥的并没有占据我们太多的时间。所以还是那句话,数据和特征决定了机器学习的上限,而模型和方法只能是逼近这个上限,好好做特征吧。

====================================分割线================================

本文作者:AI研习社

本文转自雷锋网禁止二次转载,原文链接

时间: 2024-12-01 14:01:06

一个实例告诉你:Kaggle 数据竞赛都有哪些套路的相关文章

tcp流控的一个实例:无法发送数据!

模拟测试程序,从客户端向服务器发数据,人工控制服务器收数据.当客户端发了一部分数据后,无法再发送,此时服务器开始每次收取1K.按照常理推断,服务器收取1K后,客户端应该能够继续发送数据,但实测观察发现,客户端还是无法发送数据,直到服务器收取了一定数据量后,客户端才能够继续发送. tcp抓包如下: 11:42:40.217984 IP localhost.6379 > localhost.28944: . ack 65665 win 0 <nop,nop,timestamp 1816613366

从 Kaggle 困局,看国内数据竞赛平台如何突围

国内数据竞赛市场,能做好的话,预测一两年就会有繁荣景象. --DataFountain COO 陈娟 要说本月开发者圈子的头等大事,毫无疑问是 Kaggle 被谷歌云收购.作为全世界首屈一指的数据科学.机器学习开发者社区和竞赛平台,Kaggle 不仅开拓了一个全新市场(虽然该市场的当前商业价值有限),还为国内近几年冒出的数据竞赛平台树立了学习.模仿的榜样. 李飞飞宣布谷歌云收购 Kaggle 目前看来,这场收购可谓是皆大欢喜. Kaggle 得到了谷歌云的计算资源.数据资源和业界关系支持,也对投

加入 Kaggle 大数据竞赛,总共分几步?

日前,谷歌在 Google Cloud Next 云计算大会上宣布收购知名大数据竞赛平台 Kaggle.消息一出,震动了数据科学.AI.机器学习三界(详见雷锋网文章:谷歌收购 Kaggle 为什么会震动三界?).相信经过这条新闻的曝光,未来会出现更多的开发者和从业人员加入 Kaggle 一展身手.为此,雷锋网编译了一篇国外大牛的博文,其中总结了入门 Kaggle 竞赛的四个简单步骤,希望对相关人员有所帮助. 原文作者 Jason Brownlee,机器学习专家,开发者,作家,企业家,曾在美国国防

大数据竞赛平台——Kaggle入门篇

这篇文章适合那些刚接触Kaggle.想尽快熟悉Kaggle并且独立完成一个竞赛项目的网友,对于已经在Kaggle上参赛过的网友来说,大可不必耗费时间阅读本文.本文分为两部分介绍Kaggle,第一部分简单介绍Kaggle,第二部分将展示解决一个竞赛项目的全过程.如有错误,请指正! 1.Kaggle简介 Kaggle是一个数据分析的竞赛平台,网址:https://www.kaggle.com/ 企业或者研究者可以将数据.问题描述.期望的指标发布到Kaggle上,以竞赛的形式向广大的数据科学家征集解决

这些典型实例告诉你:什么是数据可视化

大数据时代,数据是非常重要的,怎样把它的重要之处就展示出来是我们需要掌握的,这就是大讲台老师本文要讲的重点数据可视化. 通过观察数字和统计数据的转换以获得清晰的结论并不是一件容易的事.必须用一个合乎逻辑的.易于理解的方式来呈现数据. 一.谈谈数据可视化 人类的大脑对视觉信息的处理优于对文本的处理--因此使用图表.图形和设计元素,数据可视化可以帮你更容易的解释趋势和统计数据. 但是,并非所有的数据可视化是平等的. 那么,如何将数据组织起来,使其既有吸引力又易于理解 通过下面的16个有趣的例子获得启

图片-MFC 编程。接收到的数据为什么都是一个字符一个字符的,这么多的字符串结束符,新手求教

问题描述 MFC 编程.接收到的数据为什么都是一个字符一个字符的,这么多的字符串结束符,新手求教 收到的数据个数是对的,但就是实际数据和字符结束符一样一半.怎么会这样啊 解决方案 给出完整代码 ..... 解决方案二: 楼主看下MFC编码,我也遇到过转换宽字符后就没问题了

问题标签用户 .NET 怎么写一个事物使更新集合数据到SQL数据库时有一个报错所有数据都不更新

问题描述 需要.NET写一个事物在更新集合数据(即多条数据)到SQL数据库时其中有一个报错则所有数据都不更新.方法如下,事物代码我应该怎么写publicvoidUpdateCollection(RequirementsPlanningCollectiondatas){foreach(varRequirementsPlanningindatas){Update(RequirementsPlanning);}} 解决方案 解决方案二:Update直接接收datas,在里面处理事务解决方案三:物件更新

.net-.NET 怎么写一个事物使更新集合数据到SQL数据库时有一个报错所有数据都不更新

问题描述 .NET 怎么写一个事物使更新集合数据到SQL数据库时有一个报错所有数据都不更新 需要.NET 写一个事物在更新集合数据(即多条数据)到SQL数据库时其中有一个报错则所有数据都不更新. 方法如下,事物代码我应该怎么写 public void UpdateCollection(RequirementsPlanningCollection datas) { foreach (var RequirementsPlanning in datas) { Update(RequirementsPl

独家 | PHM数据竞赛首个中国夺冠团队经验分享(常用模型&amp;赛题详解&amp;PPT&amp;视频)

昆仑数据首席数据科学家田春华博士演讲视频: 团队成员代表刘家扬演讲视频: 以下内容经数据派THU整理而成: 后台回复关键词"1114",下载两位演讲嘉宾完整版PPT. 昆仑数据首席数据科学家田春华   一.工业大数据背景知识和赛题背景 田春华:竞赛是促进大家研究和交流的一种机制,而各个赛事侧重点不同.在KDD-CUP竞赛中,题目相对通用,对于参赛人员的门槛较低,因此会有大量的队伍参加,最后的前几名基本上是小数点后两位或三位的比拼.而PHM侧重于工业行业,一般会描述一个相对具体的问题,参