基于泰坦尼克号 - 机器从灾难中学习

              基于泰坦尼克号 - 机器从灾难中学习

一,选题背景

  这是传说中的泰坦尼克号ML比赛-最好的,并熟悉自己如何Kaggle平台的工作原理。竞争很简单:使用机器学习来创建一个模型,预测哪些乘客在泰坦尼克号沉船事故中幸存下来。泰坦尼克号沉没是历史上最臭名昭著的沉船事件之一。1912年4月15日,在她的处女航中,被广泛认为是"不沉"的"泰坦尼克号"在与冰山相撞后沉没。不幸的是,船上没有足够的救生艇,导致2224名乘客和船员中有1502人死亡。虽然生存中有一些运气因素,但似乎有些人比其他人更有可能生存下来。

 

二,机器学习设计方案

提出问题-->理解数据-->数据清洗-->构建模型-->方案实施

 

三,实现步骤

1.导入数据

数据集来源:https://www.kaggle.com/c/titanic/data

 

1 import pandas as pd
2 import numpy as np
 1 # 读取数据
 2 train = pd.read_csv("D:\\Anaconda\\jupyter_data\\titanic\\train.csv")
 3 test = pd.read_csv("D:\\Anaconda\\jupyter_data\\titanic\\test.csv")
 4 
 5 # train = pd.read_csv("D:/Anaconda/jupyter_data/titanic/train.csv")
 6 # test = pd.read_csv("D:/Anaconda/jupyter_data/titanic/test.csv")
 7 print('train:',train.shape, "test:",test.shape)
 8 
 9 # 合并数据集,方便同时对两个数据进行清洗
10 full = train.append(test, ignore_index = True)
11 print('合并后的数据集:',full.shape)

 

 

 

2.初步查看数据集概要信息

1 # 查看数据
2 full.head()

 

 

 

1 # 获取数据类型描述统计信息
2 full.describe()

 

 

 

1 # 查看每一列数据类型和数据总数
2 full.info()

 

 

 

3.数据清洗

(1)处理缺失数据 

 

1 # age和fare都存在缺失值,且为浮点数类型,可使用平均值进行填充
2 
3 full['Age'] = full['Age'].fillna(full['Age'].mean())
4 full['Fare'] = full['Fare'].fillna(full['Fare'].mean())
1 # 填充客舱号(Cabin)
2 full['Cabin'].head()

 

 

 

1 # Cabin 这一列缺失值较多且无规律,直接填充U(unknow)
2 full['Cabin'] = full['Cabin'].fillna('U')
1 # 出发地点:S=南安普敦  途经地点:C=瑟堡,Q=皇后镇
2 full['Embarked'].head()

 

 

 

 

 

 

 

1 # 统计各个出发地点出现的次数
2 from collections import Counter
3 print(Counter(full['Embarked']))

 

 

 

1 # 由于登船港口(Emabrked)这一列只有两个缺失值,将填充为 最频繁出现的S
2 full['Embarked'] = full['Embarked'].fillna('S')
1 # 再次查看最终缺失值处理情况
2 full.info()

(2)提取特征

1 """
2 将性别的值映射为数值,
3 male --> 1
4 female --> 0
5 """
6 sex_mapDict = {'male':1, 'female':0}
7 # map函数:对于Series 每个数据应用自定义函数计算
8 full['Sex'] = full['Sex'].map(sex_mapDict)
9 full.head()

 

 

1 full['Embarked'].head()

 

 

 

 

 

 

 

1 # 存放提取后的特征
2 embarkedDF = pd.DataFrame()
3 
4 # 使用get_dummies进行one-hot编码,列名前缀为Embarked
5 embarkedDF = pd.get_dummies(full['Embarked'],prefix = 'Embarked')
6 embarkedDF.head()

 

 

 

 

 

 

1 # 添加one-hot编码产生的虚拟变量(dummy variables)到泰坦尼克号数据集full
2 full = pd.concat([full, embarkedDF], axis = 1)
3 
4 # 因已对登船港口(Embarked)进行了one-hot编码产生虚拟变量,故删除 Embarked
5 full.drop('Embarked', axis = 1, inplace = True)
6 full.head()

 

 

 

1 # 存放提取后的特征
2 pclassDf = pd.DataFrame()
3 
4 # 使用get_dummies进行one-hot编码,列名前缀为Pclass
5 pclassDf = pd.get_dummies(full['Pclass'], prefix = 'Pclass')
6 pclassDf.head()

 

 

 

1 full = pd.concat([full, pclassDf], axis = 1)
2 
3 full.drop('Pclass', axis = 1, inplace = True)
4 full.head()

 

 

 

1 full['Name'].head()

 

 

 

 1 # 从姓名中获取头衔
 2 # split()通过制定分隔符对字符串进行切片
 3 def getTitle(name):
 4     str1 = name.split(',')[1]
 5     str2 = str1.split('.')[0]
 6     # strip()移除字符串头尾制定的字符(默认为空格)
 7     str3 = str2.strip()
 8     return str3
 9 
10 titleDf = pd.DataFrame()
11 
12 # map函数:对于Series每个数据应用自定义函数计数
13 titleDf['Title'] = full['Name'].map(getTitle)
14 titleDf.head()

 

 

 

 1 # 从姓名中头衔字符串与自定义头衔类别的映射
 2 title_mapDict = {
 3     'Capt':'Officer',
 4     'Col':'Officer',
 5     'Major':'Officer',
 6     'Jonkheer':'Royalty',
 7     'Don':'Royalty',
 8     'Sir':'Royalty',
 9     'Dr':'Officer',
10     'Rev':'Officer',
11     'the Countess':'Royalty',
12     'Dona':'Royalty',
13     'Mme':'Mrs',
14     'Mlle':'Miss',
15     'Mr':'Mr',
16     'Mrs':'Mrs',
17     'Miss':'Miss',
18     'Master':'Master',
19     'Lady':'Royalty'
20 }
21 # print(title_mapDict)
22 titleDf['Title'] = titleDf['Title'].map(title_mapDict)
23 # 使用get——dummies进行one-hot编码
24 titleDf = pd.get_dummies(titleDf['Title'])
25 titleDf.head()

 

 

 

1 # 添加one-hot编码产生的虚拟变量到泰坦尼克号数据集full
2 full = pd.concat([full, titleDf], axis = 1)
3 
4 # 删除姓名(Name)这一列
5 full.drop('Name', axis = 1, inplace = True)
6 full.head()

 

 

 

1 full['Cabin'].head()

 

 

 

 1 # 存放客舱号信息
 2 cabinDf = pd.DataFrame()
 3 
 4 # 客舱号的类别值是首字母, eg:C85
 5 
 6 #定义匿名函数 lambda,用于查找首字母
 7 full['Cabin'] = full['Cabin'].map(lambda c:c[0])
 8 
 9 # 使用get_dummies 进行one-hot 编码, 列名前缀为Cabin
10 cabinDf = pd.get_dummies(full['Cabin'], prefix = 'Cabin')
11 cabinDf.head()

 

 

 

1 # 添加one-hot编码产生的虚拟变量到泰坦尼克号数据集full
2 full = pd.concat([full, cabinDf], axis = 1)
3 # 删除客舱号等级(Pclass)这一列
4 full.drop('Cabin', axis = 1, inplace = True)
5 full.head()

 

 

 

 

 

 

 

 1 # 存放家庭信息
 2 familyDf = pd.DataFrame()
 3 # 家庭人数 = 同代直系亲属数(SibSp)+ 不同代直系亲属数(Parch)+ 乘客自己
 4 familyDf['Familysize'] = full['SibSp'] + full['Parch'] + 1
 5 """
 6 家庭类别:
 7 小家庭Family_Single:家庭人数=1
 8 中等家庭Family_Small:2<=家庭人数<=4
 9 大家庭Family_Large:家庭人数>=5
10 """
11 # if条件为真是返回if前面内容, 否则返回0
12 familyDf['Family_Single'] = familyDf['Familysize'].map(lambda s : 1 if s == 1 else 0)
13 familyDf['Family_Small'] = familyDf['Familysize'].map(lambda s : 1 if 2 <= s <=4 else 0)
14 familyDf['Family_Large'] = familyDf['Familysize'].map(lambda s : 1 if s >= 5 else 0)
15 familyDf.head()

 

 

 

1 # 添加one-hot编码产生的虚拟变量到泰坦尼克号数据集full
2 full = pd.concat([full, familyDf], axis = 1)
3 full.head()

 

 

 

 

 

 

 1 # 存放年龄信息
 2 ageDf = pd.DataFrame()
 3 """
 4 年龄类别:
 5 儿童Child:0<年龄<=6
 6 青少年Teenager:6<年龄<18
 7 青年Youth:18<=年龄<=40
 8 中年Middle_age:40<年龄<=60
 9 老年Older:60<年龄
10 """
11 ageDf['Child'] = full['Age'].map(lambda a : 1 if 0 < a <= 6 else 0)
12 ageDf['Teenager'] = full['Age'].map(lambda a : 1 if 6 < a < 18 else 0)
13 ageDf['Youth'] = full['Age'].map(lambda a : 1 if 18 <= a <= 40 else 0)
14 ageDf['Middle_age'] = full['Age'].map(lambda a : 1 if 40 < a <= 60 else 0)
15 ageDf['Older'] = full['Age'].map(lambda a : 1 if a > 60 else 0)
16 ageDf.head()

 

 

 

 

 

 

1 # 添加one-hot编码产生的虚拟变量到泰坦尼克号数据集full
2 full = pd.concat([full, ageDf], axis = 1)
3 # 删除Age这一列
4 full.drop('Age', axis = 1, inplace = True)
5 full.head()

 

 

 

1 # 查看现已有的特征
2 full.shape

(3)特征选择

1 # 相关矩阵
2 corrDf = full.corr()
3 corrDf

 

 

 

1 # 查看各个特征与生成情况(Survived)的相关系数,ascending = False表示按降序排列
2 
3 corrDf['Survived'].sort_values(ascending = False)

 

 

 

 

 

 

 

 1 # 特征选择
 2 full_X = pd.concat([
 3     titleDf,  # 头衔
 4     pclassDf,
 5     full['Fare'],
 6     full['Sex'],
 7     cabinDf,
 8     embarkedDF
 9 ], axis = 1)
10 full_X.head()

 

 

 

 

 

 

4构建模型

(1)建立训练集和测试集

 1 # 原始数据共有891行
 2 sourceRow = 891
 3 """
 4 原始数据集sourceRow是从Kaggle下载的训练集,可知共有891条数据从特征集
 5 full_X中提取原始数据前891行数据时需减去1,因为行号是从0开始
 6 """
 7 # 原始数据集:特征
 8 source_X = full_X.loc[0:sourceRow-1,:]
 9 # 原始数据集:标签
10 source_y = full.loc[0:sourceRow-1,'Survived']
11 # 预测数据集:特征
12 pred_X = full_X.loc[sourceRow:,:]
13 # 查看原始数据集有多少行
14 print('原始数据集:', source_X.shape[0])
15 # 查看预测数据集有多少行
16 print('预测数据集:',pred_X.shape[0])

 

 

 

 

 

 

 1 # from sklearn.cross_validation import train_test_split
 2 from sklearn.model_selection import train_test_split
 3 
 4 # 建立模型所需的训练数据集合测试集
 5 train_X,test_X,train_y,test_y = train_test_split(source_X,source_y,train_size=0.8)
 6 # 输出数据集大小
 7 print('原始数据集特征:',source_X.shape,
 8      '训练数据集特征:',train_X.shape,
 9      '测试数据集特征:',test_X.shape,)
10 print('原始数据集标签:',source_y.shape,
11      '训练数据集标签:',train_y.shape,
12      '测试数据集标签:',test_y.shape,)

 

 

 

 

 

 

 

1 # 查看原始数据集标签
2 source_y.head()

 

 

 

(2)选择机器学习算法

1 # 第一步:导入算法
2 from sklearn.linear_model import LogisticRegression
3 # 第二步:创建模型:逻辑回归
4 model = LogisticRegression()
1 # 第三步:训练模型
2 model.fit(train_X, train_y)

 

 

 

 

1 # 第四步评估模型
2 # 分类问题 score 得到的是模型正确率
3 model.score(test_X, test_y)

 

 

 

 

 

 

5实施方案

 1 # 使用机器学习模型,对预测数据集中的生存情况进行预测
 2 pred_y = model.predict(pred_X)
 3 
 4 # 生成的预测值是浮点数,但是Kaggle要求提交的结果是整数型
 5 # 使用astype对数据类型进行转换
 6 pred_y = pred_y.astype(int)
 7 # 乘客id
 8 passenger_id = full.loc[sourceRow:,'PassengerId']
 9 # 数据框:乘客id, 预测生存情况
10 predDf = pd.DataFrame({'PassengerId':passenger_id, 'Survived':pred_y})
11 predDf.shape
12 predDf.head()

 

 

 

# 保存结果
predDf.to_csv('./titanic_pred.csv', index=False)

 

 

 四,总结

1,通过对泰坦尼克号 - 机器从灾难中学习过程实现,得到了0.81的精度,

2,完成设计过程中,机器学习过程时间过于长需要一直跑测试集,需要改进的地方是如果还将性别变量转换为数字
x[性别][labelencoder_x.fit_转换(x[[性']),问题可能会得到解决。

 

posted @ 2021-06-23 23:59  Z-Mitexi  阅读(602)  评论(0编辑  收藏  举报