0%

机器学习案例-泰坦尼克号获救预测

4.实例-Kaggle-泰坦尼克船员获救分析

1. 主要使用的库函数:

  • Numpy - python科学计算库

  • pandas - python数据分析处理库

  • Scikit-learn - python机器学习库

2. 数据介绍:

image-20230910164325668

  • PassengerId 整型变量,标识乘客的ID,递增变量,对预测无帮助
  • Survived 整型变量,标识该乘客是否幸存。0表示遇难,1表示幸存。将其转换为factor变量比较方便处理
  • Pclass 整型变量,标识乘客的社会-经济状态,1代表Upper,2代表Middle,3代表Lower
  • Name 字符型变量,除包含姓和名以外,还包含Mr.
  • Mrs. Dr.这样的具有西方文化特点的信息
  • Sex 字符型变量,标识乘客性别,适合转换为factor类型变量
  • Age 整型变量,标识乘客年龄,有缺失值
  • SibSp 整型变量,代表兄弟姐妹及配偶的个数。其中Sib代表Sibling也即兄弟姐妹,Sp代表Spouse也即配偶
  • Parch 整型变量,代表父母或子女的个数。其中Par代表Parent也即父母,Ch代表Child也即子女
  • Ticket 字符型变量,代表乘客的船票号 Fare 数值型,代表乘客的船票价
  • Cabin 字符型,代表乘客所在的舱位,有缺失值
  • Embarked 字符型,代表乘客登船口岸,适合转换为factor型变量

3.导入数据

1
2
3
4
import pandas
titanic_data = pandas.read_csv('D:\机器学习\Kaggle_Titanic\mytrain.csv')
titanic_data.head(3)
# titanic_data.describe()

image-20230910170525751

4. 数据描述性统计

image-20230910170234015

  • count:总共多少条数据
  • mean: 平均值
  • std::方差
  • min:最小值
  • 25%:数据集四分之一处的数据
  • 50%:数据集二分之一处的数据
  • 75%:数据集四分之三处的数据
  • max:最大值

5. 对于缺失值的处理

​ 对数据进行分析的时候要注意其中是否有缺失值。一些机器学习算法能够处理缺失值,比如神经网络,一些则不能。
对于缺失值,一般有以下几种处理方法:

  • 如果数据集很多,但有很少的缺失值,可以删掉带缺失值的行;
  • 如果该属性相对学习来说不是很重要,可以对缺失值赋均值或者众数。
  • 对于标称属性,可以赋一个代表缺失的值,比如‘U0’。因为缺失本身也可能代表着一些隐含信息。比如船舱号Cabin这一属性,缺失可能代表并没有船舱。

观察图可知,字段Age和Embarked有缺失值

1
2
3
4
5
# 缺失值处理
# 将Age列缺失的值用中位数进行填充
titanic_data["Age"].fillna(titanic_data["Age"].median())
# 将Embarked列用出现最多的S进行填充
titanic_data["Embarked"] = titanic_data["Embarked"].fillna("S")

image-20230910171438056

6. 非数字型数据转换为数字表示类型

1
2
3
4
5
6
7
8
9
10
11
12
# 对于非数字型信息进行数字化
# 寻找出性别这列的种类 ['male', 'female']
titanic_data["Sex"].unique()

# 通过定位找到male和female用数字0/1代表赋值
titanic_data.loc[titanic_data["Sex"] == "male","Sex"] = 0
titanic_data.loc[titanic_data["Sex"] == "female","Sex"] = 1

# 登船地点S C Q 用 0/1/2进行表示
titanic_data.loc[titanic_data["Embarked"] == "S","Embarkded"] = 0
titanic_data.loc[titanic_data["Embarked"] == "C","Embarkded"] = 1
titanic_data.loc[titanic_data["Embarked"] == "Q","Embarkded"] = 2

7. 处理结果

image-20230910184428905

8.特征分析

  • Pclass(船舱等级)

    船舱等级, 一等舱是整个船最昂贵奢华的地方, 有钱人才能享受, 想必一等舱的有钱人比三等舱的穷人更容易幸存, 到底是不是呢?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    # 二、特征分析
    # 1.Pclass(船舱等级)与幸存相关性
    import numpy as np
    import matplotlib.pyplot as plt

    # 解决matplotlib中文乱码
    from matplotlib import font_manager
    fontnamelist = font_manager.get_font_names()
    plt.rcParams['font.sans-serif']=['kaiti']
    plt.rcParams["axes.unicode_minus"]=False #解决图像中的"-"负号的乱码问题

    #生成Survived为0时, 每个Pclass的总计数
    Pclass_Survived_0 = titanic_data.Pclass[titanic_data['Survived'] == 0].value_counts()

    #生成Survived为1时, 每个Pclass的总计数
    Pclass_Survived_1 = titanic_data.Pclass[titanic_data['Survived'] == 1].value_counts()
    Pclass_Survived = pandas.DataFrame({ 0: Pclass_Survived_0, 1: Pclass_Survived_1})

    #生成Pclass_Survived的列联表(生成关联列表与上述操作作用一致)
    #Pclass_Survived = pd.crosstab(df_train['Pclass'], df_train['Survived'])

    # 绘制堆叠柱形图
    Pclass_Survived.plot(kind='bar',stacked=True,figsize=(10,6))

    plt.xticks(rotation=360)

    # 添加标注
    plt.xlabel('船舱等级')
    plt.ylabel('人数')

    plt.legend(loc='upper left')
    plt.title('船舱等级与幸存情况')

    # 三个船舱的死亡数
    Pclass_Survived_0.sort_values()
    # print(Pclass_Survived_0.sort_values())
    # 1 80
    # 2 97
    # 3 372
    # 三个船舱的幸存数
    Pclass_Survived_1.sort_values()
    # print(Pclass_Survived_1.sort_values())
    # 2 87
    # 3 119
    # 1 136

    Pclass_all = Pclass_Survived_0+Pclass_Survived_1

    # 计算每个船舱的生存率
    Pclass_Survived_rate = round(Pclass_Survived_1/Pclass_all,2)
    print(Pclass_Survived_rate)

    image-20230910191606907

分析:可以看到一等舱人员的幸存机会远大于三等舱, 果然和船舱等级相关。

  • Sex 性别

    女士优先, 但在这种紧急关头, 会让女士优先上救生艇吗?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # 2.Sex
    #生成性别与生存列联表
    Sex_Survived = pandas.crosstab(titanic_data['Sex'], titanic_data['Survived'])

    # 查看列联表
    Sex_Survived

    # 绘制簇状柱形图
    Sex_Survived.plot(kind='bar',figsize=(10,6))

    # 添加数值标签
    for x,y in enumerate(Sex_Survived[0]):
    plt.text(x-0.12, y+10, '%s' %y,ha='center',va='bottom')
    for x,y in enumerate(Sex_Survived[1]):
    plt.text(x+0.12, y+10, '%s' %y,ha='center',va='bottom')

    # 调整x轴刻度
    plt.xticks(rotation=360)

    image-20230910192447218

分析:结果可以看出, 女性中的幸存率远高于男性(也就是说女性优先上救生艇)

9.构建模型及评估

用sklearn库实现机器学习算法 考虑用到的算法有: 逻辑回归, 决策树

  • 逻辑回归
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 三、建立模型
# 七个特征值
predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]


from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

X=titanic_data[["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]]
y=titanic_data['Survived']
#随机划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
#逻辑回归模型初始化
lg = LogisticRegression()
#训练逻辑回归模型
lg.fit(X_train, y_train)
#用测试数据检验模型好坏
a= lg.score(X_test, y_test)
#print(a)

image-20230910193031170

  • 决策树

    1
    2
    3
    4
    5
    from sklearn.tree import DecisionTreeClassifier
    #树的最大深度为15, 内部节点再划分所需最小样本数为2, 叶节点最小样本数1, 最大叶子节点数10, 每次分类的最大特征数6
    dt = DecisionTreeClassifier(max_depth=15, min_samples_split=2, min_samples_leaf=1, max_leaf_nodes=10, max_features=6)
    dt.fit(X_train, y_train)
    dt.score(X_test, y_test)

    image-20230910194455835

10.代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
"""
@FileName: Kaggle_Titanic.py
@DateTime: 2023/9/17 15:58
@SoftWare: PyCharm
"""


import pandas

#一、数据处理
# 1.导入数据
titanic_data = pandas.read_csv('mytrain.csv')
# print(titanic_data.head(3))
# print(titanic_data.describe())



# 缺失值处理
# 将Age列缺失的值用中位数进行填充
titanic_data["Age"] = titanic_data["Age"].fillna(titanic_data["Age"].median())
# 将Embarked列用出现最多的S进行填充
titanic_data["Embarked"] = titanic_data["Embarked"].fillna("S")
# 用NO来填充Cabin的缺失值
titanic_data['Cabin'] = titanic_data['Cabin'].fillna('NO')


# 对于非数字型信息进行数字化
# 寻找出性别这列的种类 ['male', 'female']
titanic_data["Sex"].unique()

# 通过定位找到male和female用数字0/1代表赋值
titanic_data.loc[titanic_data["Sex"] == "male","Sex"] = 0
titanic_data.loc[titanic_data["Sex"] == "female","Sex"] = 1

# 登船地点S C Q 用 0/1/2进行表示
titanic_data.loc[titanic_data["Embarked"] == "S","Embarked"] = 0
titanic_data.loc[titanic_data["Embarked"] == "C","Embarked"] = 1
titanic_data.loc[titanic_data["Embarked"] == "Q","Embarked"] = 2



# 二、特征分析
# 1.Pclass(船舱等级)与幸存相关性
import numpy as np
import matplotlib.pyplot as plt

# 解决matplotlib中文乱码
from matplotlib import font_manager
fontnamelist = font_manager.get_font_names()
plt.rcParams['font.sans-serif']=['kaiti']
plt.rcParams["axes.unicode_minus"]=False #解决图像中的"-"负号的乱码问题

#生成Survived为0时, 每个Pclass的总计数
Pclass_Survived_0 = titanic_data.Pclass[titanic_data['Survived'] == 0].value_counts()

#生成Survived为1时, 每个Pclass的总计数
Pclass_Survived_1 = titanic_data.Pclass[titanic_data['Survived'] == 1].value_counts()
Pclass_Survived = pandas.DataFrame({ 0: Pclass_Survived_0, 1: Pclass_Survived_1})

#生成Pclass_Survived的列联表(生成关联列表与上述操作作用一致)
#Pclass_Survived = pd.crosstab(df_train['Pclass'], df_train['Survived'])

# 绘制堆叠柱形图
# Pclass_Survived.plot(kind='bar',stacked=True,figsize=(10,6))
#
# plt.xticks(rotation=360)

# 添加标注
plt.xlabel('船舱等级')
plt.ylabel('人数')

plt.legend(loc='upper left')
plt.title('船舱等级与幸存情况')

# 三个船舱的死亡数
Pclass_Survived_0.sort_values()
# print(Pclass_Survived_0.sort_values())
# 1 80
# 2 97
# 3 372
# 三个船舱的幸存数
Pclass_Survived_1.sort_values()
# print(Pclass_Survived_1.sort_values())
# 2 87
# 3 119
# 1 136

Pclass_all = Pclass_Survived_0+Pclass_Survived_1

# 计算每个船舱的生存率
Pclass_Survived_rate = round(Pclass_Survived_1/Pclass_all,2)
# 1 0.63
# 2 0.47
# 3 0.24


# 2.Sex
#生成性别与生存列联表
Sex_Survived = pandas.crosstab(titanic_data['Sex'], titanic_data['Survived'])

# 查看列联表
Sex_Survived

# 绘制簇状柱形图
Sex_Survived.plot(kind='bar',figsize=(10,6))

# 添加数值标签
for x,y in enumerate(Sex_Survived[0]):
plt.text(x-0.12, y+10, '%s' %y,ha='center',va='bottom')
for x,y in enumerate(Sex_Survived[1]):
plt.text(x+0.12, y+10, '%s' %y,ha='center',va='bottom')

# 调整x轴刻度
plt.xticks(rotation=360)

# 不同性别对应死亡数
Sex_Survived_0 = Sex_Survived[0]

# 不同性别对应生存数
Sex_Survived_1 = Sex_Survived[1]

# 不同性别生存率计算
Sex_all = Sex_Survived.sum(axis=1)
Sex_Survived_rate = round(Sex_Survived_1/Sex_all,2)
# print(Sex_Survived_rate)



# 三、建立模型
# 七个特征值
predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]


from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

X=titanic_data[["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]]
y=titanic_data['Survived']
#随机划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
#逻辑回归模型初始化
lg = LogisticRegression()
#训练逻辑回归模型
lg.fit(X_train, y_train)
#用测试数据检验模型好坏
a= lg.score(X_test, y_test)
# print(a)

# 2.决策树
from sklearn.tree import DecisionTreeClassifier
#树的最大深度为15, 内部节点再划分所需最小样本数为2, 叶节点最小样本数1, 最大叶子节点数10, 每次分类的最大特征数6
dt = DecisionTreeClassifier(max_depth=15, min_samples_split=2, min_samples_leaf=1, max_leaf_nodes=10, max_features=6)
dt.fit(X_train, y_train)
b = dt.score(X_test, y_test)
# print(b)