泰坦尼克数据科学解决方法
有几个优秀的notebook来研究数据科学竞赛参赛作品。然而,许多人会跳过一些关于如何开发解决方案的解释,因为这些notebook是由专家为专家开发的。本笔记本的目标是遵循分步工作流程,解释我们在解决方案开发过程中做出的每个决策的每个步骤和基本原理。
工作流步骤
- 1.问题的定义
- 2.获得训练和测试数据
- 3.整理、准备和清洗数据
- 4.分析、识别模式并探索数据
- 5.建模、预测和解决问题。
- 6.可视化、报告和呈现问题解决步骤和最终解决方案
- 7.提供或提交结果。
工作流指示每个阶段如何跟随另一个阶段的一般顺序。但是,也有例外的用例。
- 我们可能会将多个工作流程阶段结合起来。我们可以通过可视化数据进行分析。
- 在指定的阶段之前执行。我们可能会在整理数据之前和之后分析数据。
- 在我们的工作流程中多次执行一个阶段。可视化阶段可多次使用。
问题定义
像Kaggle这样的竞争网站定义要解决的问题或要问的问题,同时提供用于训练数据科学模型的数据集,并根据测试数据集测试模型结果。泰坦尼克号生存竞赛的问题或问题定义在Kaggle中进行了描述。
从列出在泰坦尼克号灾难中幸存下来或没有幸存下来的乘客的训练样本中,我们的模型是否可以根据不包含生存信息的给定测试数据集来确定测试数据集中的这些乘客是否幸存下来。
我们可能还想对问题的领域有一些早期的了解。这在这里的Kaggle竞争描述页面上进行了描述。以下是需要注意的亮点。
- 1912 年 4 月 15 日,泰坦尼克号在处女航中与冰山相撞后沉没,2224 名乘客和船员中有 1502 人死亡,存活率为32%。
- 沉船导致这种生命损失的原因之一是没有足够的救生艇供乘客和船员使用。
- 虽然在沉没中幸存下来有一些运气因素,但有些人群比其他人更有可能生存下来,例如妇女,儿童和上层阶级。
workflow 的目标
数据科学解决方案工作流解决了七个主要目标。
- 分类。我们可能希望对样本进行分类或分类。我们可能还希望了解不同类与我们的解决方案目标的含义或相关性。
- 相关性。人们可以根据训练数据集中的可用特征来解决问题。数据集中的哪些功能对我们的解决方案目标有重大贡献?从统计学上讲,功能和解决方案目标之间是否存在相关性?随着功能值的变化,解决方案状态是否也会改变,反之亦然?这既可以针对给定数据集中的数值特征和分类特征进行测试。我们可能还希望确定后续目标和工作流阶段的生存以外的特征之间的相关性。关联某些要素可能有助于创建、完成或更正要素。
- 转换。 对于建模阶段,需要准备数据。根据模型算法的选择,可能需要将所有特征转换为数值。例如,将文本分类值转换为数值。
- 填充。数据准备可能还需要我们估计要素中的任何缺失值。当没有缺失值时,模型算法可能效果最佳。
- 纠正。我们还可能分析给定的训练数据集中的错误或可能不确定的特征值,并尝试更正这些值或排除包含错误的样本。执行此操作的一种方法是检测我们的样本或特征中的任何异常值。如果某个特征没有对分析有贡献,或者可能显着扭曲结果,我们也可能会完全丢弃该特征。
- 创建。我们是否可以基于现有特征或一组特征创建新特征,以便新特征遵循相关性,转换,完整性目标。
- 制图。如何根据数据的性质和解决方案目标选择正确的可视化图和图表。
导包
import pandas as pd
import numpy as np
import random as rnd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC,LinearSVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import SGDClassifier
from sklearn.tree import DecisionTreeClassifier
获取数据
train_df=pd.read_csv('titanic_train.csv')
test_df=pd.read_csv('test.csv')
combine=[train_df,test_df]
分析数据
#获取特征名
print(train_df.columns.values)
['PassengerId' 'Survived' 'Pclass' 'Name' 'Sex' 'Age' 'SibSp' 'Parch'
'Ticket' 'Fare' 'Cabin' 'Embarked']
- 类别型特征:survived,sex,embarked
- 序号:pclass
- 连续型数值型特征:age,fare
- 离散型数值型特征:sibsp,parch
train_df.head()
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
混合型数据:字母、数字混合,数据中的ticket和cabin
train_df.info()
print('-'*50)
test_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 891 non-null int64
1 Survived 891 non-null int64
2 Pclass 891 non-null int64
3 Name 891 non-null object
4 Sex 891 non-null object
5 Age 714 non-null float64
6 SibSp 891 non-null int64
7 Parch 891 non-null int64
8 Ticket 891 non-null object
9 Fare 891 non-null float64
10 Cabin 204 non-null object
11 Embarked 889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
--------------------------------------------------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 418 entries, 0 to 417
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 418 non-null int64
1 Pclass 418 non-null int64
2 Name 418 non-null object
3 Sex 418 non-null object
4 Age 332 non-null float64
5 SibSp 418 non-null int64
6 Parch 418 non-null int64
7 Ticket 418 non-null object
8 Fare 417 non-null float64
9 Cabin 91 non-null object
10 Embarked 418 non-null object
dtypes: float64(2), int64(4), object(5)
memory usage: 36.0+ KB
- 对于train来说,cabin、age、embarked存在null
- test数据集:cabin和age不完整
train_df.describe()
PassengerId | Survived | Pclass | Age | SibSp | Parch | Fare | |
---|---|---|---|---|---|---|---|
count | 891.000000 | 891.000000 | 891.000000 | 714.000000 | 891.000000 | 891.000000 | 891.000000 |
mean | 446.000000 | 0.383838 | 2.308642 | 29.699118 | 0.523008 | 0.381594 | 32.204208 |
std | 257.353842 | 0.486592 | 0.836071 | 14.526497 | 1.102743 | 0.806057 | 49.693429 |
min | 1.000000 | 0.000000 | 1.000000 | 0.420000 | 0.000000 | 0.000000 | 0.000000 |
25% | 223.500000 | 0.000000 | 2.000000 | 20.125000 | 0.000000 | 0.000000 | 7.910400 |
50% | 446.000000 | 0.000000 | 3.000000 | 28.000000 | 0.000000 | 0.000000 | 14.454200 |
75% | 668.500000 | 1.000000 | 3.000000 | 38.000000 | 1.000000 | 0.000000 | 31.000000 |
max | 891.000000 | 1.000000 | 3.000000 | 80.000000 | 8.000000 | 6.000000 | 512.329200 |
- 存活率是38%
- 总乘客数是891
- 高于75%的乘客没有带孩子或者父母
- 25%的人有兄弟或者姐妹在一起
- 很少有老年人乘坐
分类特征的分布情况:
- 名称在整个数据集中是唯一的
- 性别变量为两个值,男性占了65%
- cabin在样本之间具有多个二重。或者,几名乘客共用一间客舱
- embarked有三个值,大部分乘客由S登船
- ticket有高的重复值比率
#获得字符串的信息
train_df.describe(include=['O'])
Name | Sex | Ticket | Cabin | Embarked | |
---|---|---|---|---|---|
count | 891 | 891 | 891 | 204 | 889 |
unique | 891 | 2 | 681 | 147 | 3 |
top | Braund, Mr. Owen Harris | male | 347082 | B96 B98 | S |
freq | 1 | 577 | 7 | 4 | 644 |
基于数据分析的假设
相关性
我们想知道每个特征与生存的相关性如何。我们希望在项目的早期就做到这一点,并将这些快速相关性与项目后期的建模相关性相匹配。
填充
- 填充从age特征,因为它一定与存活有关
- 可能会填充embarked特征,因为它可能会与存活或者其他重要的特征有关
更正
- ticket可能会从我们的分析中移除,因为包含高的重复率(22%),可能survival和ticket没有关联
- cabin特征可能会被移除,由于它高度不相关并且含有很多空值在train和test数据集
- passengerld会从training数据集移除,因为它不会对survival产生影响
- name特征是完全不标准的,对survival没有直接贡献,也被移除
创造特征
- 可能创造一个family特征,依据parch和sibsp特征,这个特征包含船上的所有的家庭成员
- 处理name特征提取title作为新的特征
- 创造新的特征作为age 区间,这将连续的数值型特征转为有序的类别特征
- 创造新的fale 范围特征帮助分析
分类
我们还可以根据前面提到的问题描述来增加我们的假设。
- 女人更可能存活
- 儿童更可能存活
- pcalss=1的人更可能存活
Analyze by pivoting features
为了证实我们的一些观察和假设,我们可以通过相互旋转特征来快速分析我们的特征相关性。在此阶段,我们只能对没有任何空值的特征执行此操作。仅对categorical(Sex),ordinal ( Pclass )或discrete( SibSp , Parch )类型的特征这样做也是有意义的。
- Pcalss。我们观察到Pclass=1和Survived(分类)之间存在显着相关性(>0.5)。我们决定将此功能包含在我们的模型中。
- Sex。我们证实了问题定义过程中的观察结果,即性别=女性的存活率为74%(分类)。
- SibSp and Parch.这些特征对于某些值的相关性为零。最好从这些单独的特征派生一个特征或一组特征(创建 #1)。
train_df[['Pclass', 'Survived']].groupby(['Pclass'], as_index=False).mean().sort_values(by='Survived', ascending=False)
Pclass | Survived | |
---|---|---|
0 | 1 | 0.629630 |
1 | 2 | 0.472826 |
2 | 3 | 0.242363 |
train_df[['Sex','Survived']].groupby(['Sex'],as_index=False).\
mean().sort_values(by='Survived',ascending=False)
Sex | Survived | |
---|---|---|
0 | female | 0.742038 |
1 | male | 0.188908 |
train_df[['SibSp','Survived']].groupby(['SibSp'],as_index=False).\
mean().sort_values(by='Survived',ascending=False)
SibSp | Survived | |
---|---|---|
1 | 1 | 0.535885 |
2 | 2 | 0.464286 |
0 | 0 | 0.345395 |
3 | 3 | 0.250000 |
4 | 4 | 0.166667 |
5 | 5 | 0.000000 |
6 | 8 | 0.000000 |
train_df[["Parch", "Survived"]].groupby(['Parch'], as_index=False).mean().sort_values(by='Survived', ascending=False)
Parch | Survived | |
---|---|---|
3 | 3 | 0.600000 |
1 | 1 | 0.550847 |
2 | 2 | 0.500000 |
0 | 0 | 0.343658 |
5 | 5 | 0.200000 |
4 | 4 | 0.000000 |
6 | 6 | 0.00 |