Kaggle:Getting Started of Titanic

2024-03-04 07:30
文章标签 started kaggle titanic getting

本文主要是介绍Kaggle:Getting Started of Titanic,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、概要

泰坦尼克号幸存预测是Kaggle上参与人数最多的的比赛之一,要求参赛人员预测乘客是否能够幸存,是一个典型的二分类问题。

二、数据简介

官网提供训练数据集train.csv和测试数据集test.csv和一个提交样例数据集,数据中的各个字段如下:

PassengerId: 乘客的ID
Survived:1代表幸存,0代表遇难
Pclass:票类别-社会地位, 1代表Upper,2代表Middle,3代表Lower
Name:姓名
Sex:性别
Age:年龄
SibSp:兄弟姐妹及配偶的个数
Parch:父母或子女的个数
Ticket:船票号
Fare:船票价格
Cabin:舱位
Embarked:登船口岸

三、数据探索

1、加载数据

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
path = '/titanic/data/{}'
train = pd.read_csv(path.format('train.csv'))
test = pd.read_csv(path.format('test.csv'))

2、概览

train.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            714 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)

数据中有大量的数值型数据,这部分可以考虑直接使用;其他非数值型数据要探索一下如何分类;同时里面存在一定量的缺失值,这部分要注意填充或者丢弃。

3、分类样本

train['Survived'].value_counts()0    549
1    342

样本量很小,同时存在不平衡的问题,可能需要考虑调整。

4、特征权重

train_corr = train.drop('PassengerId', axis=1).corr()
train_corr

这里写图片描述
计算数值型字段的协方差,可以看到Pclass与Fare和生存的相关性相对比较明显。

5、特征探索

(1)Pclass

随着船票等级的降低,人数逐渐增加,同时生存率也大大下降,相关性很明显,后续模型需要考虑这个特征。
这里写图片描述

(2)Sex

妇女小孩先走,女性明显有更高的幸存率。

train.groupby('Sex')['Survived'].mean()Sex
female    0.742038
male      0.188908
Name: Survived, dtype: float64
(3)Age

Age字段缺失数量较多,先去除缺失数据,再整体观察
这里写图片描述
根据年龄段的不同,生存出现明显左右高,中间低的现象,对年龄进行分组再对比

age_not_miss['Age'] = pd.cut(age_not_miss['Age'], bins=[0, 18, 30, 45, 100], labels=[1,2,3,4])
age_not_miss.groupby('Age')['Survived'].mean()Age
1    0.503597
2    0.355556
3    0.425743
4    0.368932

未成年人明显具有更高的生存率。

(4)Sibsp + Parch

前面协方差表看到Sibsp和Parch与生存率之间存在一定的关系,但不是特别明显,这里可以考虑将这两个特征组合成一个新特征Family再进行观察

train['F_size'] = train['SibSp'] + train['Parch'] + 1
train.groupby('F_size')['Survived'].mean()F_size
1     0.303538
2     0.552795
3     0.578431
4     0.724138
5     0.200000
6     0.136364
7     0.333333
8     0.000000
11    0.000000
Name: Survived, dtype: float64

可以看到家庭人数在2-4人的情况下,具有较高的生存率,而单独一个与家庭人数大于等于5人的生存率明显降低

(5)Ticket

船票出现重复的数量比较少,这里可以考虑把船票重复与否派生出另一个特征,因为相同的船票代表可能为相互认识的人,从而在逃生的时候更可能出现聚堆的情况。

(6)Fare

从协方差表能看到Fare与生存率有相对明显的关系,因为船票价格众多,先分组
这里写图片描述
可以看出,很明显的递增关系。

(7)Cabin

舱位缺失数量非常多,可能无法提取出足够的信息,可以考虑以舱位缺失与否及舱位前缀作为特征。

(8)Embarked

登船港口有一个缺失值,可以考虑用众数填充或不做处理,C港上船的乘客明显具有更高的生存率,同一个港口上船更可能分布在船中的同一片区域,从而影响生存率。

train.groupby(['Embarked'])['Survived'].mean()Embarked
C    0.553571
Q    0.389610
S    0.336957
Name: Survived, dtype: float64
(9)Name

Name中包含了对乘客的称呼、性别及可能的社会地位等信息,这里需要先对信息进行抽取,再结合领域知识进行特征构建,这个放到后边再列出来。

四、特征构建

构建特征时,先把训练集和测试集合并到一起

    test['Survived'] = 0train_test = train.append(test)
1、船票等级

船票等级只需要简单的把数据分列即可,构造one-hot向量

train_test = pd.get_dummies(train_test, columns=['Pclass'], prefix='P')
2、名称

对于名称,先用正则表达式提取出其中的称呼

train_test['Name1'] = train_test['Name'].str.extract('.*?,(.*?)\.').str.strip()

对于称呼进行分类,最终构造出了四类特征

train_test['Name1'].replace(['Master'], 'Master' , inplace = True)
train_test['Name1'].replace(['Jonkheer', 'Don', 'Sir', 'the Countess', 'Dona', 'Lady', 'Capt', 'Col', 'Major', 'Dr', 'Rev'], 'Royalty' , inplace = True)
train_test['Name1'].replace(['Mme', 'Ms', 'Mrs', 'Mlle', 'Miss'], 'Mrs' , inplace = True)
train_test['Name1'].replace(['Mr'], 'Mr' , inplace = True)

看看这几类特征与生存率的相关性如何
这里写图片描述
很明显,分组为男士的生存率是最低的,而女士则有占有最高的生存率,Mater组代表了年长同时拥有更高知识水平的人群也获得了极高的存活率,其他剩下的数量较少,但从称号上基本代表了拥有相对高社会身份的人群,如:贵族等。

3、性别

同1,直接分组即可

train_test = pd.get_dummies(train_test, columns=['Sex'], prefix='S')
4、家庭

家庭按照人口数量,分为4个组别

train_test['F_size'] = train_test['SibSp'] + train_test['Parch'] + 1
train_test['F_Single'] = train_test['F_size'].map(lambda s: 1 if s == 1 else 0)
train_test['F_Small'] = train_test['F_size'].map(lambda s: 1 if 2<= s <= 3  else 0)
train_test['F_Med'] = train_test['F_size'].map(lambda s: 1 if s == 4 else 0)
train_test['F_Large'] = train_test['F_size'].map(lambda s: 1 if s >= 5 else 0)
5、船票

按照是否共享船票,提取特征

tpc = train_test['Ticket'].value_counts().reset_index()
tpc.columns = ['Ticket', 'Ticket_sum']
train_test = pd.merge(train_test, tpc, how='left', on='Ticket')
train_test.loc[train_test['Ticket_sum'] == 1, 'T_share'] = 0
train_test.loc[train_test['Ticket_sum'] != 1, 'T_share'] = 1
6、船票价格

船票价格可能和船票等级及登船港口相关,根据这两个特征,找到对应的均值,填充缺失值
这里写图片描述
根据Embarked为S,填充之后分组

train_test['Fare'].fillna(14.644083, inplace=True)
train_test['Fare_bin'] = pd.cut(train_test['Fare'], 3, labels=[1,2,3])
7、船舱

根据是否缺失及船舱首字母构造特征

train_test['Cabin'] = train_test['Cabin'].apply(lambda x: str(x)[0] if pd.notnull(x) else x)
train_test.loc[train_test['Cabin'].isnull(), 'Cabin_nan'] = 1
train_test.loc[train_test['Cabin'].notnull(), 'Cabin_nan'] = 0
train_test = pd.get_dummies(train_test, columns=['Cabin'])
8、港口

直接用众数S填充缺失值,分组

train_test['Embarked'].fillna('S')
train_test = pd.get_dummies(train_test, columns=['Embarked'], prefix='E')
9、年龄

先提取年龄是否缺失特,这很有可能与是否生存有关系

train_test.loc[train_test['Age'].isnull(), 'Age_nan'] = 1
train_test.loc[train_test['Age'].notnull(), 'Age_nan'] = 0

后面考虑建立模型填充缺失的年龄数据,剔除可能与年龄无关或者冗余的字段

miss_age = train_test.drop(['PassengerId', 'Name', 'Ticket', 'Fare', 'Survived'], axis=1)
miss_age_train = miss_age[miss_age['Age'].notnull()]
miss_age_test = miss_age[miss_age['Age'].isnull()]
miss_age_train_x = miss_age_train.drop(['Age'], axis=1)
miss_age_train_y = miss_age_train['Age']
miss_age_test_x = miss_age_test.drop(['Age'], axis=1)

特征都是one-hot向量,先标准化处理一下

from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(miss_age_train_x)
miss_age_train_x_ss = ss.transform(miss_age_train_x)
miss_age_test_x_ss = ss.transform(miss_age_test_x)

用贝叶斯模型进行进行预测

from sklearn import linear_model
model = linear_model.BayesianRidge()
model.fit(miss_age_train_x_ss, miss_age_train_y)
train_test.loc[train_test['Age'].isnull(), 'Age'] = model.predict(miss_age_test_x_ss)

最后按年龄段进行分组

train_test['Age'] = pd.cut(train_test['Age'], bins=[0, 18, 30, 45, 100], labels=[1, 2, 3, 4])
train_test = pd.get_dummies(train_test, columns=['Age'], prefix='A')
10、去除冗余特征
feature_columns = ['PassengerId', 'Name', 'Ticket', 'Fare', 'SibSp', 'Parch']
train_test = train_test.drop(feature_columns, axis=1)

最终提取出来的特征如下所示:
这里写图片描述

11、特征评价

画出特征的协方差图
这里写图片描述
从相关图上看,我们选取的大部分特征彼此之间都没有太大的相关性,这对于建立模型来说是一个好消息,我们希望每一个特征彼此之间无关,能够提供不同的层面的信息,从而更加充分的表达出数据的整体信息。

五、模型构建

1、数据标准化

和上文提到的预测年龄一样,先分割数据集和标准化数据

train_data = train_test[:891]
test_data = train_test[891:]
train_data_x = train_data.drop(['Survived'], axis=1)
train_data_y = train_data['Survived']
test_data_x = test_data.drop(['Survived'], axis=1)
ss1 = StandardScaler()
ss1.fit(train_data_x)
train_data_x_ss = ss1.transform(train_data_x)
test_data_x_ss = ss1.transform(test_data_x)
2、普通模型

模型调参

from sklearn.model_selection import GridSearchCV
params = {name: value}
cv = GridSearchCV(estimator=cls), param_grid=params, scoring='roc_auc', cv=5)
cv.fit(train_data_x_ss, train_data_y)
cv.best_params_
(1)RandomForestClassifier
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_estimators=220, min_samples_leaf=3, max_depth=5, min_samples_split=9)
rf.score(train_data_x_ss, train_data_y)
(2)LogisticRegression
lr = LogisticRegression(class_weight='balanced', C=0.01, max_iter=100)
lr.fit(train_data_x_ss, train_data_y)
lr.score(train_data_x_ss, train_data_y)
(3)SVC
from sklearn import svm
svc = svm.SVC(C=10, max_iter=350, probability=True)
svc.fit(train_data_x_ss, train_data_y)
svc.score(train_data_x_ss, train_data_y)
(4)GradientBoostingClassifier
from sklearn.ensemble import GradientBoostingClassifier
gbdt = GradientBoostingClassifier(learning_rate=0.5, n_estimators=120)
gbdt.fit(train_data_x_ss, train_data_y)
gbdt.score(train_data_x_ss, train_data_y)
(5)XGBClassifier
import xgboost as xgb
xg = xgb.XGBClassifier(learning_rate=0.8, n_estimators=100)
xg.fit(train_data_x_ss, train_data_y)
xg.score(train_data_x_ss, train_data_y)
(6)ExtraTreesClassifier
from sklearn.ensemble import ExtraTreesClassifier
et = ExtraTreesClassifier(n_estimators=200)
et.fit(train_data_x_ss, train_data_y)
et.score(train_data_x_ss, train_data_y)

3、融合模型

(1)VotingClassifier
from sklearn.ensemble import VotingClassifier
rf = RandomForestClassifier(n_estimators=220, min_samples_leaf=3, max_depth=5, oob_score=True)
lr = LogisticRegression(class_weight='balanced', C=0.01, max_iter=100)
svc = svm.SVC(C=10, max_iter=350, probability=True)
gbdt = GradientBoostingClassifier(learning_rate=0.5, n_estimators=120)
xg = xgb.XGBClassifier(learning_rate=0.8, n_estimators=100)
et = ExtraTreesClassifier(n_estimators=200)vot = VotingClassifier(estimators=[('rf', rf), ('lr', lr), ('svc', svc), ('gbdt', gbdt), ('xg', xg), ('et', et)], voting='hard')
vot.fit(train_data_x_ss, train_data_y)
vot.score(train_data_x_ss, train_data_y)
(2)Stacking

两层模型,先处理数据

from sklearn.cross_validation import StratifiedKFold
clfs = [rf, lr, svc, gbdt, xg, et]
X = np.array(train_data_x_ss)
Y = np.array(train_data_y)
X_test = np.array(train_data_x_ss)
Y_test = np.array(train_data_y)

blend作为第二层模型输入

train_blend = np.zeros((X.shape[0], len(clfs)))
test_blend = np.zeros((X_test.shape[0], len(clfs)))

K-flod

skf = list(StratifiedKFold(Y, 5))

依次训练单个模型,再使用模型的预测值构建第二层模型的输入

for i, clf in enumerate(clfs):test_blend_i = np.zeros((test_blend.shape[0], len(skf)))for j, (train, test) in enumerate(skf):clf.fit(X[train], Y[train])# 每一个模型的预测值,填充到blend的对应位置,k-flod的测试刚好覆盖# 全部的训练集,填充blend对应的一列train_blend[test, i] = clf.predict_proba(X[test])[:, 1]test_blend_i[:, j] = clf.predict_proba(X_test)[:, 1]# test_blend相比而言会多出k-1份数据,直接取均值即可test_blend[:, i] = test_blend_i.mean(1)

第二层模型直接使用逻辑回归

clf2 = LogisticRegression(C=10, max_iter=100)
clf2.fit(train_blend, Y)
clf2.score(test_blend, Y_test)

上述模型中,得分最高的是随机森林,达到了0.80382,位于前11%

六、调优

观察姓名字段,在同一艘船上,姓相同的乘客很有可能是同一家人,从而在逃生的时候分布在同一片区域,这里可以考虑增加特征。
提取乘客的姓名,对于只出现1次的姓,不进行考虑,直接命名为small,而其他则进行分组

train_test['Name2_'] = train_test['Name'].apply(lambda x: x.split('.')[1].strip())
names = train_test['Name2_'].value_counts().reset_index()
names.columns = ['Name2_', 'Name2_sum']
train_test = pd.merge(train_test, names, how='left', on='Name2_')
train_test.loc[train_test['Name2_sum'] <= 1, 'Name2'] = 'small'
train_test.loc[train_test['Name2_sum'] > 1, 'Name2'] = train_test['Name2_']
train_test = pd.get_dummies(train_test, columns=['Name2'], prefix='N')

再次进行模型训练,最终得分0.81339,达到前5%

七、结果

最终得分最高的模型为随机森林,得分为0.81339,排名551/11347,位于Top 5%
这里写图片描述

八、后续

Titanic是一个入门级的项目,关键点在于对这种比赛套路的认识,从数据分析到特征提取,最后建模调参等。
实际中,特征决定了模型的上限的,而好的模型和参数能够无限逼近这个上限,这也是kaggle社区一致的认识。
上述项目如果想再提升,那么就是对特征的再次发掘,或者用大量的存在一定差异的模型进行模型融合,或许能够得到意想不到的结果。
具体代码可以在我github上找到: https://github.com/lpty/kaggle
在写作过程中,参考了以下文章,在此致谢:
https://github.com/apachecn/kaggle/tree/dev/competitions/getting-started/titanic
http://www.jasongj.com/ml/classification/

这篇关于Kaggle:Getting Started of Titanic的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/772451

相关文章

zabbix出现active check configuration update from [127.0.0.1:10051] started to fail (cannot connect to

出现active check configuration update from [127.0.0.1:10051] started to fail (cannot connect to [[127.0.0.1]:10051]: [111] Connection refused),直接编辑zabbix_agentd.conf(vi /usr/local/zabbix/etc/zabbix_agen

Kaggle比赛:成人人口收入分类

拿到数据首先查看数据信息和描述   import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # 加载数据(保留原路径,但在实际应用中建议使用相对路径或环境变量) data = pd.read_csv(r"C:\Users\11794\Desktop\收入分类\training.csv", e

【Kaggle量化比赛】Top讨论

问: 惊人的单模型得分,请问您使用了多少个特征来获得如此高的得分?我也在使用LGB模型。 答 235个特征(180个基本特征+滚动特征) 问: 您是在使用Polars进行特征工程还是仅依赖于Pandas+Numba/多进程?即使进行了Numba优化,我也发现当滚动特征过多时,推理速度会非常慢。在Colab T4上使用在线流式评估,完成一个qp需要超过7秒。 答 使用Numba和多进程

【Hadoop】Flume NG Getting Started(Flume NG 新手入门指南)翻译

新手入门 Flume NG是什么? 有什么改变? 获得Flume NG 从源码构建 配置 flume-ng全局选项flume-ng agent选项flume-ng avro-client 选项 提供反馈 Flume NG是什么? Flume NG的目标是比Flume OG在简单性,大小和容易部署上有显著性地提高。为了实现这个目标,Flume NG将不会兼容Flume OG.我们目

Kaggle-Camera_Model_Identification 比赛记录总结[19/582(Top 4%)]

这篇博客记录自己在这次kaggle比赛中做的工作。成绩:19/582(Top 4%) Kaggle比赛地址 我的代码github地址 这次比赛是给出10个相机拍摄的照片,然后给出测试图片,区分是哪个相机拍摄的。训练集中每类照片数量相同,每类都是由同一个手机拍摄的照片。测试集中,每类的照片都是来自另外一个手机,一半的图片可能被用了八种可能的操作。 总结: 1. 更多的数据。

Python学习从0开始——Kaggle时间序列002

Python学习从0开始——Kaggle时间序列002 一、作为特征的时间序列1.串行依赖周期 2.滞后序列和滞后图滞后图选择滞后 3.示例 二、混合模型1.介绍2.组件和残差3.残差混合预测4.设计混合模型5.使用 三、使用机器学习进行预测1.定义预测任务2.为预测准备数据3.多步骤预测策略3.1 Multioutput模型3.2 直接策略3.3 递归策略3.4 DirRec策略 4.使用

动手学深度学习4.10 实战Kaggle比赛:预测房价-笔记练习(PyTorch)

以下内容为结合李沐老师的课程和教材补充的学习笔记,以及对课后练习的一些思考,自留回顾,也供同学之人交流参考。 本节课程地址:实战 Kaggle 比赛:预测房价_哔哩哔哩_bilibili 本节教材地址:4.10. 实战Kaggle比赛:预测房价 — 动手学深度学习 2.0.0 documentation (d2l.ai) 本节开源代码:...>d2l-zh>pytorch>chapter_m

titanic乘客简单的数据分析(matplotlib和seaborn 的使用)

数据来源: kaggle的Titanic 生存模型:titanic_train.csv。 引入的库: import numpy as npimport pandas as pdimport sysreload(sys)sys.setdefaultencoding('gbk')import matplotlib.pyplot as pltimport seaborn as sns

Huggingface Transformers库学习笔记(一):入门(Get started)

前言 Huggingface的Transformers库是一个很棒的项目,该库提供了用于自然语言理解(NLU)任务(如分析文本的情感)和自然语言生成(NLG)任务(如用新文本完成提示或用另一种语言翻译)的预先训练的模型。其收录了在100多种语言上超过32种预训练模型。这些先进的模型通过这个库可以非常轻松的调取。同时,也可以通过Pytorch和TensorFlow 2.0进行编写修改等。 本系列学

动手学深度学习——Kaggle小白入门

1. kaggle注册 注册网址:https://www.kaggle.com 注册账号不需要代理,但手机号验证需要代理。如果要使用GPU或TPU,则需要进行手机号验证。 手机号验证位置:右上角头像的settings界面。 手机号验证时会有几个问题: 无验证码,提示:Captcha must be filled out. 原因:人机验证组件在国内被拦截,所以看不到验证按钮,需要