泰坦尼克号人员预测模型(python/jupyter-notebook/数据挖掘/数据分析)

本文利用Python进行泰坦尼克号人员生还预测,通过数据挖掘技术,探讨乘客等级、性别、年龄等因素对生还率的影响。在Jupyter Notebook中详细展示了数据预处理、模型构建和评估过程。
Python3.8

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

泰坦尼克号人员预测模型

运用python实现泰坦尼克号的人员预测,机器学习,数据挖掘

前言

以泰坦尼克号数据为对象,结合当时背景,理解数据和认识数据,掌握数据的初步探索,具体包括缺失值的处理、数据间的相关性分析等。掌握属性变换、特征生成、特征选择与主成分分析处理方法,生成适合模型算法来预测人员生还情况

实验过程

字段解读

在这里插入图片描述

每个字段的意义如下。

PassengerId :乘客ID

Pclass:乘客等级(1/2/3等舱位)(属性代表船舱等级,1-一等舱,2-二等舱,3-三等舱,从一定程度上反应了这个乘客经济情况和社会地位。)

Name:乘客姓名

Sex:性别

Age:年龄

SibSp:堂兄弟/妹个数

Parch:父母与小孩个数

Ticket:船票信息(字母与数字具体代表什么信息,需要猜测分析判断)

Fare:票价

Cabin:客舱

Embarked:登船港口

Survived:乘客是否获救

使用jupyter-notebook实现的完整过程:

导入所有的第三方库:
import pandas as pd
import numpy as np
import seaborn as sns
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.model_selection import train_test_split
from sklearn.ensemble import VotingClassifier, RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier as KNN
from sklearn import svm
from sklearn import tree
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
from pylab import *
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
数据理解以及数据分析:
#  导入数据
titanic = pd.read_csv(r'D:\Pycharm工程\MYPYTHON2\Titanic\train.csv')
# pd.set_option('display.max_rows', 500)             # 展示区域最多不超过500行
# pd.set_option('display.max_columns', 15)			# 
pd.set_option('display.width', 130)			# 展示前面20行
print(titanic.head(20))

在这里插入图片描述

# 调用isnull()方法来查看train.csv数据集的缺失程度
pd.isnull(titanic).sum()

在这里插入图片描述

# 可以查看每一个数值属性的平均值、方差、最大值、最小值、四分位数等
titanic.describe()

在这里插入图片描述

# (1)Age,对于Age属性我们采用平均值来填补空缺值
# (2)Carbine由于它的空缺值太多,我们这里用一个’NO’来填充Carbine的空缺值
# (3)Embarked 我们采取众数来填充
titanic['Age'] = titanic['Age'].fillna(titanic['Age'].median())
titanic['Cabin'] = titanic['Cabin'].fillna('NO')
titanic['Embarked'] = titanic['Embarked'].fillna('S')
pd.isnull(titanic).sum()

在这里插入图片描述

# 设置画布的大小
fig = plt.figure(figsize=(15,10))
# # 获救人数分布,1为获救
plt.subplot2grid((1, 3), (0, 0))
titanic.Survived.value_counts().plot(kind='bar')    # 柱状图
plt.title("获救情况 (1为获救)")     # 标签
plt.ylabel("人数")     # y轴
plt.xlabel("Survived")      # x轴
# 乘客等级人数分布
plt.subplot2grid((1, 3), (0, 1))
titanic.Pclass.value_counts().plot(kind="bar")
plt.title("乘客等级分布")
plt.ylabel("人数")
plt.xlabel("Pclass")
# 各登船口岸上船人数分布
plt.subplot2grid((1, 3), (0, 2))
titanic.Embarked.value_counts().plot(kind='bar')
plt.title("各登船口岸上船人数")
plt.ylabel("人数")
plt.xlabel("Embarked")

在这里插入图片描述

结果分析:

从分布图可以看出,没有获救的的人数比重大、乘客等级分布里面、三等舱的人数最多、登船口岸上船人数最多的是S口岸

# 乘客等级与获救的关系
Survived_0 = titanic.Pclass[titanic.Survived == 0].value_counts()
Survived_1 = titanic.Pclass[titanic.Survived == 1].value_counts()
df = pd.DataFrame({'获救': Survived_1, '未获救': Survived_0})
df.plot(kind='bar', stacked=True)
plt.title("各乘客等级的获救情况")
plt.xlabel("乘客等级")
plt.ylabel("人数")

在这里插入图片描述

结果分析:

从大致的来看,乘客等级为一即头等舱的人获救的人数最多,同样在这个等级里面获救的比例也越大,而再看看等级为三的乘客,没有获救的人数占大比例,其中只有少部分存活下来,可以推测,在当时的社会环境中,社会阶层具有很大的影响对于获救,等级越高的人,会给予一定的社会福利,机会也会比较多,同样也证实了,处于社会底层的人民就是会有不公平的待遇

# 乘客年龄与获救的关系
fig = plt.figure()
fig.set_size_inches(12, 12)
plt.subplot2grid((2, 2), (0, 0))
plt.scatter(titanic.Survived, titanic.Age)
plt.ylabel('年龄')
plt.grid(b=True, which='major', axis='y')
plt.title('乘客年龄与获救的关系(1为获救)')

在这里插入图片描述

结果分析:
从得到的结果来看,年龄对于获救情况没有很大关系,不过还是可以看出,年龄大的人,获救的少,当然也符合事实,年龄大的人一方面回想着把机会留给年轻一代,同时年龄大的人,活动不方便,跟不上撤离的节奏,所以年龄大的人获救的比例少

# 乘客性别与获救情况的关系
Survived_m = titanic.Survived[titanic.Sex == 'male'].value_counts()
Survived_f = titanic.Survived[titanic.Sex == 'female'].value_counts()
df = pd.DataFrame({'男性': Survived_m, '女性': Survived_f})
df.plot(kind='bar', stacked=True)
plt.title("乘客性别与获救情况关系")
plt.xlabel("性别")
plt.ylabel("人数")

在这里插入图片描述

结果分析:
从直观上来看,获救的人数中,女性占有很大的比例,同样在女性这一类别中,女性获救的比例也大于男性获救的比例,当然这也符合当时英国的社会精神’骑士精神’,男生要保护好自己的女人,并且要尊重女生,所以在撤退的时候,会有女士优先,就像电影中所看到的,jack在最后也会把生存的希望留给rose,并嘱咐她好好活下去。这是一种为人称赞的精神!

#乘客上船的口岸与获救情况的关系
Survived_0 = titanic.Embarked[titanic.Survived == 0].value_counts()
Survived_1 = titanic.Embarked[titanic.Survived == 1].value_counts()
df = pd.DataFrame({'获救': Survived_1, '未获救': Survived_0})
df.plot(kind='bar', stacked=True)
plt.title("各登录港口乘客与获救情况")
plt.xlabel("登录港口")
plt.ylabel("人数")

在这里插入图片描述

结果分析:

从实验结果来看,乘客的登录口岸是哪一个对是否获救没有多大影响,大致维持的比例都差不多。

# 堂兄弟/妹,孩子/父母有几人,与获救情况的关系
sibsp_Survived = titanic.SibSp[titanic.Survived == 1].value_counts()
sibsp_Nosurvived = titanic.SibSp[titanic.Survived == 0].value_counts()
df5 = pd.DataFrame({'获救': sibsp_Survived, '未获救': sibsp_Nosurvived})
df5.plot(kind='bar', alpha=0.7)
plt.title('堂兄弟姐妹人数与获救情况的关系')
plt.xlabel("堂兄弟姐妹人数")
plt.ylabel("人数")
plt.show()

# 孩子父母人数与获救情况的关系
parch_Survived = titanic.Parch[titanic.Survived == 1].value_counts()
parch_Nosurvived = titanic.Parch[titanic.Survived == 0].value_counts()
df4 = pd.DataFrame({'Survived': parch_Survived, 'Nosurvived': parch_Nosurvived})
df4.plot(kind='bar', alpha=0.7)
plt.title('孩子父母人数与获救情况的关系')
plt.xlabel("孩子父母人数")
plt.ylabel("人数")
plt.show()

在这里插入图片描述

结果分析:
从结果来看:没有堂兄弟姐妹和孩子父母的人获救的最多,也就是独自一人的获救人数最多。获救人数的多少随着堂兄弟姐妹和孩子父母数量的增多也呈现出递减的趋势,这一现象来看,我们小组的理解就是:可能一个人他没有亲人,也就没有牵挂,所以逃亡的时候可以无所顾忌,同样单独的一个人,行动起来方便,所以获救的机会大一点,不用在撤离的时候顾及自己的亲人,也相对比较果断,只要自己能够活下来就好

# 名字与获救的关系
# 提取名字的长度作为名字的特征属性
def long(s):
    return len(s)
titanic['Name_long'] = titanic['Name'].apply(long)
titanic = titanic.sort_values(by = ['Survived'], ascending = False)
# 红色的点表示获救,蓝色则表示没有获救
plt.scatter(titanic.iloc[:342,2],titanic.iloc[:342,12],c='red')
plt.scatter(titanic.iloc[343:891,2],titanic.iloc[343:891,12],c='blue')

在这里插入图片描述

结果分析:

想着名字的长短或许和贵族有关,随后建立了名字长短、船票的等级、是否获救三者的关系,从实验结果来看,三者看上去可能有一点关系、有可能没有多大关系。

属性值的处理:
# 将“Sex”和“Embarked”属性转化成数字
titanic.loc[titanic['Sex'] == 'male', 'Sex'] = 0
titanic.loc[titanic['Sex'] == 'female', 'Sex'] = 1
titanic.loc[titanic['Embarked'] == 'S', 'Embarked'] = 0
titanic.loc[titanic['Embarked'] == 'C', 'Embarked'] = 1
titanic.loc[titanic['Embarked'] == 'Q', 'Embarked'] = 2


# 年龄分层
titanic['AgeBand'] = pd.qcut(titanic.Age, 4)
titanic[['AgeBand', 'Survived']].groupby('AgeBand').mean()
def age_level(x):
        if x <= 22:
            return 0
        elif x < 28:
            return 1
        elif x < 35:
            return 2
        else:
            return 3

titanic['Age_type'] = titanic['Age'].apply(age_level)
# fare分层
titanic['FareBand'] = pd.qcut(titanic.Fare, 5)
titanic[['FareBand', 'Survived']].groupby('FareBand').mean()
def fare_level(x):
        if x <= 7.854:
            return 0
        elif x < 10.5:
            return 1
        elif x < 21.679:
            return 2
        elif x < 39.688:
            return 3
        else:
            return 4

titanic['Fare_type'] = titanic['Fare'].apply(fare_level)

titanic['FamilySize'] = titanic['SibSp']+titanic['Parch']+1     # 家族规模=堂兄妹+孩子父母+自己
# titanic[['FamilySize', 'Survived']].groupby('FamilySize').mean()
def alone(x):
    return 0 if x > 1 else 1
titanic['IsAlone'] = titanic['FamilySize'].apply(alone)
titanic.head(20)

在这里插入图片描述

# 去除不要的字段,保留便于后续操作的字段,保障呈现的是一个数字特征
titanic_t = titanic.drop(['PassengerId', 'Name', 'Cabin', 'Age', 'SibSp', 'Parch', 'FamilySize', 'AgeBand', 'FareBand', 'Ticket','Name_long'], axis=1)
titanic_t.head(20)

在这里插入图片描述

构建分类模型,评估模型,以及使用模型预测
划分测试集和训练集
# 划分的方法是留出法、比例为7:3
X = titanic_t.iloc[:, 1:]
Y = titanic_t.iloc[:, 0]
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=0)
# print(X_train.shape)
# print(Y_train.shape)
# print(X_test.shape)

构建分类模型、计算得分

# SVM算法(支持向量机)py
# svm算法里面的细节参考:https://blog.csdn.net/TeFuirnever/article/details/99646257
svc = svm.SVC(gamma='auto')
svc.fit(X_train, Y_train)
print(svc.score(X_test, Y_test))

0.7649253731343284

# 决策树
# 决策树的细节:https://www.cnblogs.com/baby-lily/p/10646226.html
dt = DecisionTreeClassifier(criterion='entropy')     # 采用的特征是: 信息熵
dt.fit(X_train, Y_train)
print(dt.score(X_test, Y_test))

0.7947761194029851

# 朴素贝叶斯模型
gaussian = GaussianNB()
gaussian.fit(X_train, Y_train)
print(gaussian.score(X_test, Y_test))

0.7723880597014925

# KNN邻近算法
# n_neighbors:取邻近点的个数k。k取1-9测试
# weight:距离的权重;uniform:一致的权重;distance:距离的倒数作为权重
# p:闵可斯基距离的p值; p=1:即欧式距离;p=2:即曼哈顿距离;p取1-6测试
# 只有当weight=distance的时候,p值才有意义
# for k in range(1,6):
#     for p in range(1,5):
#         mo = KNN(n_neighbors=k,weights="distance",p=p)
#         mo.fit(X_train, Y_train)
#         print(mo.score(X_test, Y_test))

在这里插入图片描述

可以根据得到的实验结果选取最好的参数(每次实验划分的数据集的比例以及选取的随机序列会干扰结果,大家可以选取最好的实验结果)

# KNN算法
# 最终选择的参数n = 5, 距离取3
mo = KNN(n_neighbors=5,weights="distance",p=3)
mo.fit(X_train, Y_train)
print(mo.score(X_test, Y_test))

0.7686567164179104

在这里需要提一下软投票以及硬投票

在这里插入图片描述

# 模型的融合:采用投票法对模型进行融合,投票
rfc = svm.SVC(gamma='auto',probability=True)
GB = GaussianNB()
dtc = tree.DecisionTreeClassifier()
mo = KNN(n_neighbors=5,weights="distance",p=3)
clf_vc = VotingClassifier(estimators=[('svm', rfc), ('GNB', GB), ('dtc', dtc),('knn',mo)],voting='soft')
clf_vc.fit(X_train, Y_train)
print(clf_vc.score(X_test, Y_test))

0.8134328358208955

预测分析
titanic_test = pd.read_csv(r'D:\Pycharm工程\MYPYTHON2\Titanic\test.csv')
pd.set_option('display.width', 130)
 # 空缺值的填补
 titanic_test['Age'] = titanic_test['Age'].fillna(titanic_test['Age'].median())
titanic_test['Fare'] = titanic_test['Fare'].fillna(titanic_test['Fare'].median())           # 多了一个费用的填
titanic_test['Cabin'] = titanic_test['Cabin'].fillna('NO')
titanic_test['Embarked'] = titanic_test['Embarked'].fillna('S')
pd.isnull(titanic_test).sum()
# 将“Sex”和“Embarked”属性转化成数字
titanic_test.loc[titanic_test['Sex'] == 'male', 'Sex'] = 0
titanic_test.loc[titanic_test['Sex'] == 'female', 'Sex'] = 1
titanic_test.loc[titanic_test['Embarked'] == 'S', 'Embarked'] = 0
titanic_test.loc[titanic_test['Embarked'] == 'C', 'Embarked'] = 1
titanic_test.loc[titanic_test['Embarked'] == 'Q', 'Embarked'] = 2
# 年龄分层
titanic_test['AgeBand'] = pd.qcut(titanic_test.Age, 4)
titanic_test[['AgeBand']].groupby('AgeBand').mean()
def age_level(x):
        if x <= 22:
            return 0
        elif x < 28:
            return 1
        elif x < 35:
            return 2
        else:
            return 3

titanic_test['Age_type'] = titanic_test['Age'].apply(age_level)


# fare分层
titanic_test['FareBand'] = pd.qcut(titanic_test.Fare, 5)
titanic_test[['FareBand']].groupby('FareBand').mean()
def fare_level(x):
        if x <= 7.854:
            return 0
        elif x < 10.5:
            return 1
        elif x < 21.679:
            return 2
        elif x < 39.688:
            return 3
        else:
            return 4

titanic_test['Fare_type'] = titanic_test['Fare'].apply(fare_level)

titanic_test['FamilySize'] = titanic_test['SibSp']+titanic_test['Parch']+1     # 家族规模=堂兄妹+孩子父母+自己
# titanic_test[['FamilySize', 'Survived']].groupby('FamilySize').mean()
def alone(x):
    return 0 if x > 1 else 1
titanic_test['IsAlone'] = titanic_test['FamilySize'].apply(alone)
titanic_test.head(10)
# 去除不要的字段,保留便于后续操作的字段,保障呈现的是一个数字特征
titanic_test_t = titanic_test.drop(['PassengerId', 'Name', 'Cabin', 'Age', 'SibSp', 'Parch', 'FamilySize', 'AgeBand', 'FareBand', 'Ticket'], axis=1)
titanic_test_t.head(20)

在这里插入图片描述

# SVM算法预测
result1 = svc.predict(titanic_test_t.iloc[:,0:7])
print(result1)

在这里插入图片描述

# 决策树预测
result2 = dt.predict(titanic_test_t.iloc[:,0:7])
print(result2)

在这里插入图片描述

# 朴素贝叶斯
result3 = gaussian.predict(titanic_test_t.iloc[:,0:7])
print(result3)

在这里插入图片描述

# KNN 预测
result4 = mo.predict(titanic_test_t.iloc[:,0:7])
print(result4)

在这里插入图片描述

# 融合的模型预测结果
result5 =clf_vc.predict(titanic_test_t.iloc[:,0:7])
print(result5)

在这里插入图片描述

总结

实验的内容过程大致就是上面的描述,大家可以根据上面的描述到jupyter-notebook一步一步演示,应该没有多大问题,需要注意的是,注意文件存放的位置,要让程序运行的时候可以读取到文件,还有就是在jupyter-notebook里面有时候会自动展示结果,有时候又没有,大家做的时候可以多调试。

有些细节的做的不好的地方,大家可以在讨论区指出来哦!

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值