泰坦尼克号生存预测(多种模型实现)python

本文详细介绍了使用Kaggle泰坦尼克号生存预测数据集进行机器学习模型训练的过程,包括数据预处理、特征工程、模型选择与评估,以及集成学习方法的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

泰坦尼克号生存预测

这是kaggle上面比较入门的一个比赛。今天让我们来看看怎么做吧。kaggle传送门。首先报名,下载数据集。

数据载入及概述

首先导入从Kaggle上面下载的数据集,在导入的过程中就需要先导入一些必备的包了。

import numpy as np
import pandas as pd

# 接着导入我们的训练数据
filename = 'titanic/train.csv'  # 这是我存放的文件路径,这边换成你们自己的
train = pd.read_csv(filename)

然后来看看训练数据集长啥样。(每个列的名字的含义,在kaggle页面有介绍,这边就不说了。)

train.head()

image-20200820170750314

train.info()
image-20200820170950383

通过info()这个函数我们可要知道,哪些特征的数值类型是什么。比如,上面PassengerId,Survived,Pclass,Age等是数值型数据,而Name,Sex,Ticket等是字符型数据。字符型数据肯定到后面是要转换的,可能转换成one-hot类型的。不过数值型数据也可能是需要转换的。后面会细说。

trian.isnull().sum()
image-20200820171408946

通过isnull()可以看出哪些列缺失了数据,缺失了多少行。只有对缺失数据的处理有很多种,比如说填充,或者删去。

数据可视化

年龄与生存

我们都知道,在危难来临之际,一般都会让孩子和老人先脱离危险,所以我们将年龄分成3个段[0,20],[20,60],[60,80]。画出存活的人数和年龄段的图。

import seaborn as sns
examine = train.copy() # 这边将训练数据集备份一份
#将连续变量Age划分为[0,5) [5,15) [15,30) [30,50) [50,80)五个年龄段,并分别用类别变量12345表示
examine['AgeBand'] = pd.cut(examine['Age'],[0,20,60,80],labels = ['1','2','3'])
sns.barplot(x='AgeBand', y='Survived', data=examine)
image-20200820173257324

从上图,可以明显看出小孩的存活率偏高,那为什么老人存活率最低呢,是因为泰坦尼克号与一座冰山相撞,那么有冰山,必然说明那个地方的气候很寒冷,老人的身体不太好,所以存活率这么一解释,是不是也说得通。

性别与生存

前面说的小孩和老人优先,当然了还有一句是女士优先。所以我们来看看性别与存活的关系。

sns.barplot(x="Sex", y="Survived", data=examine)
image-20200820173638288 image-20200820180456938
# 提示:计算男女中死亡人数 1表示生存,0表示死亡
examine.groupby(['Sex','Survived'])['Survived'].count().unstack().plot(kind='bar',stacked='True')
plt.title('survived_count')
plt.ylabel('count')

从上面两个图,明显可以看出两者存活的几率是相差很大的。女性的存活率是明显高于男性。这也符合实际,在泰坦尼克号这部电影中,也是能够看出来。

社会地位与生存

可能有人看到社会地位就有点疑惑了,数据集里面哪有这个特征,其实不然。仓位等级和票价多多少少都能说明的。就好比几十年前,家里有车的人都是大户人家,地主官僚跟普通人的地位还是差别很大的。因此萌发一个想法,看这个特征跟存活率的关系如何。

sns.barplot(x="Pclass", y="Survived", data=examine)
image-20200820180018917

从图中看出来,仓位等级跟生存关系还是很大的,这也比较符合现实。懂得都懂。

泰坦尼克号数据集中不同仓位等级的人年龄分布情况
examine.Age[examine.Pclass == 1].plot(kind='kde')
examine.Age[examine.Pclass == 2].plot(kind='kde')
examine.Age[examine.Pclass == 3].plot(kind='kde')
plt.xlabel("age")
plt.legend((1,2,3),loc="best")
image-20200820180703425

不过这个图好像跟生存关系不大。

数据清洗及特征处理

缺失值的处理
image-20200820171408946

前面分析过,'Cabin'这列缺失了687个数据,总共才891个数据。而且这列确实跟生存与否没什么关系,因此就直接删除掉这列。还有'Name''Ticket '跟生存也没什么关系,一并删除了。

train.drop(['Cabin', 'Name', 'Ticket'], inplace=True, axis=1)
train.head()
image-20200820181911481

然后来看'Age'这列的缺失值,这列缺失了100多条数据,因此我们采用填充的方式,不过填充的方式有很多,这边使用均值填充。

train["Age"] = train["Age"].fillna(train["Age"].mean())
trian.isnull().sum()
image-20200820182510244

现在看到只有'Embarked'这列还剩下2个缺失值,2个缺失值好办,我们直接删掉就好了,对结果没什么影响。

train = train.dropna()

删掉这两条数据之后,总得数据就变成了889条了。缺失值的处理就到这里差不多结束了。

分类变量的处理

首先将二分类变量'Sex'转换成0和1。

train['Sex'] = (train['Sex'] == 'male').astype(np.int64)

然后将三分类变量'Embarked'转换成0、1、2。

labels = train['Embarked'].unique().tolist()
train['Embarked'] = train['Embarked'].apply(lambda x : labels.index(x))

当然,将分类变量转换成数值型的方式又很多,我只是写了其中的一种。

将数据中的训练变量和标签分开
X = train.iloc[:, train.columns != 'Survived']
y = train.iloc[:, train.columns == 'Survived']
X.shape, y.shape
# 输出
# (889, 8), (889, 1)

接下来,要将训练集拆分为训练集和验证集。并且训练集和验证集的比列为3:1。

from sklearn.model_selection import train_test_split
Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.25)
Xtrain.shape, Xtest.shape
# 输出
# (666, 8), (223, 8)

还有最后一步,我们要重新设置下索引。至于为什么需要,看下面这张图就可以了。

image-20200820210343454
for i in [Xtrain, Xtest, Ytrain, Ytest]:
    i.reset_index(drop=True, inplace=True)

到这里,数据的清洗,特征处理的工作基本完成了。接下来就是建模了。

数据建模及模型评估

先导入一些后面会用到的库

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
import matplotlib.pyplot as plt
决策树
clf = DecisionTreeClassifier(random_state=0)
clf.fit(Xtrain, Ytrain)
# 查看验证集score值
print("Testing set score: {:.2f}".format(clf.score(Xtest, Ytest)))
# Testing set score: 0.74

使用10折交叉验证来评估,并且取平均。

score = cross_val_score(clf,X,y,cv=10).mean()
# 0.757

接下来优化下这个模型

tr = []
te = []
for i in range(1, 11):
    clf = DecisionTreeClassifier(random_state=0,max_depth=i,criterion="entropy")
    clf = clf.fit(Xtrain, Ytrain)
    score_tr = clf.score(Xtrain,Ytrain)
    score_te = cross_val_score(clf,X,y,cv=10).mean()
    tr.append(score_tr)
    te.append(score_te)
print(max(te))
plt.plot(range(1,11),tr,color="red",label="train")
plt.plot(range(1,11),te,color="blue",label="test")
plt.xticks(range(1,11))
plt.legend()
image-20200820211514091

可以看出,最大深度为3的时候,得分最高为0.8166624106230849

逻辑回归
# 默认参数逻辑回归模型
lr = LogisticRegression()
lr.fit(Xtrain, Ytrain)
print("Testing set score: {:.2f}".format(lr.score(Xtest, Ytest)))
# Testing set score: 0.80

使用10折交叉验证来评估,并且取平均。

score = cross_val_score(lr,X,y,cv=10).mean()
# 0.795
随机森林
test = []
for i in range(1, 11):
    rfc = RandomForestClassifier(n_estimators=100, max_depth=i, random_state=20)
    score = cross_val_score(rfc, X, y, cv=10)
    test.append(score.mean())
plt.plot(range(1, 11), test)
image-20200820214323400

可以,发现当最大深度为6的时候,模型的得分最高。接近0.83,我们可以使用网格搜索来获取最优的参数,但是网格搜索比较耗时,这边就不写出来了。

Bagging
from sklearn.ensemble import BaggingClassifier
test = []

for i in range(10, 50, 5):
    clf = BaggingClassifier(n_estimators=i)
    score = cross_val_score(clf, X, y, cv=10)
    test.append(score.mean())
    
plt.plot(range(10, 50, 5), test)
plt.ylabel('score')
plt.xlabel('n_estimators')
image-20200820215404157

从上图看出,最高应该在0.82左右。

LGBClassifier
from lightgbm import LGBMClassifier
test = []
for i in range(10, 100, 5):
    lgb = LGBMClassifier(max_depth=2, n_estimators=i)
    score = cross_val_score(lgb, X, y, cv=10)
    test.append(score.mean())
    
plt.plot(range(10, 100, 5), test)
plt.ylabel('score')
plt.xlabel('n_estimators')
image-20200820220218847

从图中可以看出,最高得分接近0.84。

集成几个模型

最后将几个模型集成一下

clf = [None]*5
clf[0] = DecisionTreeClassifier(random_state=0,max_depth=3,criterion="entropy")
clf[1] = LogisticRegression()
clf[2] = RandomForestClassifier(n_estimators=100, max_depth=6, random_state=20)
clf[3] = BaggingClassifier(n_estimators=20)
clf[4] = LGBMClassifier(max_depth=2, n_estimators=40)

predictFrame = pd.DataFrame()
for model in clf:
    model.fit(Xtrain, Ytrain)
    predictFrame[str(model)[:14]] = model.predict(Xtest)

te = []
for i in range(1, 10):
    clf_ = RandomForestClassifier(n_estimators=100, max_depth=i, random_state=0)
    score = cross_val_score(clf_, predictFrame, Ytest, cv=10, scoring='precision')
    te.append(score.mean())
    
plt.plot(range(1,10), te)
image-20200821002438273

从上图看出,集成后的得分超过了0.91比单个模型的正确率提升了很多。但还是挺菜的。

最后简单总结下,自己能力有限,一些参数也是简单的定了下来,当然我相信你们分数都会比我高。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值