首页 > 其他分享 >机器学习——泰坦尼克号幸存者预测及分析

机器学习——泰坦尼克号幸存者预测及分析

时间:2023-06-10 14:44:16浏览次数:44  
标签:Fare 泰坦尼克号 机器 幸存者 Embarked Age train Survived test

1. 项目背景

泰坦尼克号: 是当时世界上体积最庞大、内部设施最豪华的客运轮船, 于1909年3月31日动工建造, 1912年4月2日完工试航. 于1912年4月10日, 在南安普敦港的海洋码头, 启程驶往纽约, 开始了它的第一次, 也是最后一次的航行. 泰坦尼克号将乘客分为三个等级: 三等舱位于船身较下层也最便宜; 二等舱具备与当时其他一般船只的头等舱同样的等级, 许多二等舱的乘客原先在其他船只上预定的头等舱, 却因为泰坦尼克号的航行, 将煤炭能源转移给泰坦尼克号; 一等舱是整艘船最为昂贵奢华的部分.

船上时间为1912年4月14日23时40分左右, 泰坦尼克号与一座冰山相撞, 造成水密舱进水, 次日凌晨2时20分左右沉没. 2224名船员和乘客中1502人遇难, 造成如此巨大的伤亡原因之一是船上没有足够的救生艇供乘客和船员使用. 在这次灾难中能否幸存下来难免会有些运气成分, 但是有些人比其他人更可能生存下来, 比如妇女, 儿童和上层阶级.

2.提出问题

什么样的人在泰坦尼克号中更容易存活?

3.收集数据

3.1采集数据

从Kaggle泰坦尼克号项目页面下载数据:https://www.kaggle.com/c/titanic

本项目提供了两份数据: train.csv文件作为训练集构建与生存相关的模型; 另一份test.csv文件则用作测试集, 用我们构建出来的模型预测生存情况.

2.1 读取数据:

import pandas as pd
df_train, df_test= pd.read_csv('train.csv'), pd.read_csv('test.csv')

从训练集开始介绍:

2.2 查看前五行数据

#查看前5行数据
df_train.head()

#查看后5行数据
df_titanic.tail()

通过以上数据以及题目资料, 可以了解到训练集总共有891行, 以下字段:

.PassengerId -- Id, 具有唯一标识的作用, 即一个人员对应一个Id.

 Survived -- 是否幸存, 1表示是 0则表示否

 Pclass -- 船舱等级, 1: 一等舱, 2: 二等舱, 3: 三等舱

 Name -- 姓名, 通常西方人的姓名结构为教名+自取名+姓, 但在很多场合中间的"自取名"会省略不写, 而且很多人更喜欢用教名的昵称取代正式教名. 有时也会将姓氏写在逗号前. 比如Dooley, Mr. Patrick, 即Dooley表示姓氏, Patrick表示名, 那Mr.呢? Mr.表示头衔, 有身份地位的象征.

 Sex -- 性别, female女性, male男性

 Age -- 年龄

 SibSp -- 同船配偶以及兄弟姐妹的人数

 Parch -- 同船父母或者子女的人数

 Ticket -- 船票

 Fare -- 票价

 Cabin -- 舱位

 Embarked -- 登船港口

2.3 查看数据表整体信息

#查看数据信息, 其中包含数据维度, 数据类型, 所占空间等信息
df_train.info()
<class 'pandas.core.frame.DataFrame'>   
RangeIndex: 891 entries, 0 to 890       
Data columns (total 12 columns):        
PassengerId    891 non-null int64       
Survived       891 non-null int64       
Pclass         891 non-null int64       
Name           891 non-null object      
Sex            891 non-null object      
Age            714 non-null float64    
SibSp          891 non-null int64       
Parch          891 non-null int64       
Ticket         891 non-null object      
Fare           891 non-null float64     
Cabin          204 non-null object    
Embarked       889 non-null object     
dtypes: float64(2), int64(5), object(5) 
memory usage: 83.6+ KB

数据维度: 891行X12列

缺失字段: Age, Cabin, Embarked

数据类型: 2个64位浮点型, 5个64位整型, 5个python对象.

2.4 描述性统计

df_train.describe()

除了python对象以外的数据类型, 均参与了计算: 

38.4%的人幸存, 死亡率很高;

年龄现有数据714, 缺失占比714/891=20%;

同船兄弟姐妹与配偶人数最大为8, 同船父母或者子女的人数最大则为6, 且两者最小值均为0, 看来有大家庭, 小家庭(独自一人)之分;

票价最小为0, 最大为512.3, 均值为32.20, 中位数为14.45, 正偏, 贫富差距不小.

那么与python对象对应的该怎么查看呢?

#同样是使用describe()方法
df_train[['Name','Sex','Ticket','Cabin','Embarked']].describe()

显示结果与上述有点区别, 依次来看:

姓名共有891种, 总数也891个, 姓名是唯一的;

性别中男性最多, 达到577人次;

船票中681种, 总数891, 部分人共用一张票;

舱位总数204, 缺失占比(891-204)/891= 77%;

登船港口总数889, 缺失2个, 共有3种类型, 其中S最多, 达到644人次, 

现在已经对每个特征的大致信息有所了解, 那么下一步则是在特征分析中探索着找出与幸存相关的特征.

3. 特征分析

在以上特征中, 哪些是和幸存相关的呢?让我们通过数据分析来知晓。

 

1. PassengerId

Id仅仅是用来标识乘客的唯一性, 必然是与幸存无关.

2. Pclass

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

复制代码
import numpy as np
import matplotlib.pyplot as plt
#生成Pclass_Survived的列联表
Pclass_Survived = pd.crosstab(df_train['Pclass'], df_train['Survived'])
#绘制堆积柱形图
Pclass_Survived.plot(kind = 'bar', stacked = True)
Survived_len = len(Pclass_Survived.count())
Pclass_index = np.arange(len(Pclass_Survived.index))
Sum1 = 0
for i in range(Survived_len):
    SurvivedName = Pclass_Survived.columns[i]
    PclassCount = Pclass_Survived[SurvivedName]
    Sum1, Sum2= Sum1 + PclassCount, Sum1
    Zsum = Sum2 + (Sum1 - Sum2)/2
    for x, y, z in zip(Pclass_index, PclassCount, Zsum):
        #添加数据标签
        plt.text(x,z, '%.0f'%y, ha = 'center',va='center' )
#修改x轴标签
plt.xticks(Pclass_Survived.index-1, Pclass_Survived.index, rotation=360)
plt.title('Survived status by pclass')
复制代码

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

其中的列联表就等同于以下操作:

#生成Survived为0时, 每个Pclass的总计数
Pclass_Survived_0 = df_train.Pclass[df_train['Survived'] == 0].value_counts()
#生成Survived为1时, 每个Pclass的总计数
Pclass_Survived_1 = df_train.Pclass[df_train['Survived'] == 1].value_counts()
#将两个状况合并为一个DateFrame 
Pclass_Survived = pd.DataFrame({ 0: Pclass_Survived_0, 1: Pclass_Survived_1})

3. Name

姓名, 总数891个且有891种不同的结果, 把名字直接拿来讨论, 没多大意义. 但是在他们国家的那个年代,姓名中有头衔存在, 头衔又是身份地位的象征, 想必身份地位越高, 应当更容易幸存.为了验证这个猜想是否正确,我们 先提取出Name中的头衔特征:

#提取出头衔
df_train['Appellation'] = df_train.Name.apply(lambda x: re.search('\w+\.', x).group()).str.replace('.', '')
#查看有多种不同的结果
df_train.Appellation.unique()
array(['Mr', 'Mrs', 'Miss', 'Master', 'Don', 'Rev', 'Dr', 'Mme', 'Ms',
       'Major', 'Lady', 'Sir', 'Mlle', 'Col', 'Capt', 'Countess',
       'Jonkheer'], dtype=object)

头衔名称的解读: Mr 既可用于已婚男性, 也可用于未婚男性,  Mrs 已婚女性, Miss 通常用来称呼未婚女性, 但有时也用于称呼自己不了解的年龄较大的妇女, Master  男童或男婴,  Don 大学教师,  Rev 牧师,  Dr 医生或者博士, Mme 女士, Ms 既可用于已婚女性也可用于未婚女性, Major 陆军少校,  Lady 公候伯爵的女儿,  Sir 常用来称呼上级长官, Mlle 小姐, Col 上校(常用于陆空军), Capt 船长, Countess 指伯爵夫人, Jonkheer 乡绅.

头衔太多了, 决定将其归类, 那么如何归类呢? 先查看下其与性别对应的人数:

Appellation_Sex = pd.crosstab(df_train.Appellation, df_train.Sex)
Appellation_Sex.T

决定将将少数部分归为'Rare', 将'Mlle', 'Ms'用'Miss'代替, 将'Mme'用'Mrs'代替.

df_train['Appellation'] = df_train['Appellation'].replace(['Capt','Col','Countess','Don','Dr','Jonkheer','Lady','Major','Rev','Sir'], 'Rare')
df_train['Appellation'] = df_train['Appellation'].replace(['Mlle','Ms'], 'Miss')
df_train['Appellation'] = df_train['Appellation'].replace('Mme', 'Mrs')
df_train.Appellation.unique()
array(['Mr', 'Mrs', 'Miss', 'Master', 'Rare'], dtype=object)

头衔和幸存相关吗?让我们来一起验证。

#绘制柱形图
Appellation_Survived = pd.crosstab(df_train['Appellation'], df_train['Survived'])
Appellation_Survived.plot(kind = 'bar')
plt.xticks(np.arange(len(Appellation_Survived.index)), Appellation_Survived.index, rotation = 360) plt.title('Survived status by Appellation')

头衔中Master, Miss, Mrs的幸存机会均大于Mr 和 Rare.

4. Sex

性别, 女士优先, 但在这种紧急关头, 会让女士优先上救生艇吗?让我们一起通过数据来分析。

复制代码
#生成列联表
Sex_Survived = pd.crosstab(df_train['Sex'], df_train['Survived'])
Survived_len = len(Sex_Survived.count())
Sex_index = np.arange(len(Sex_Survived.index))
single_width = 0.35
for i in range(Survived_len):
    SurvivedName = Sex_Survived.columns[i]
    SexCount = Sex_Survived[SurvivedName]
    SexLocation = Sex_index * 1.05 + (i - 1/2)*single_width
   #绘制柱形图
    plt.bar(SexLocation, SexCount, width = single_width)
    for x, y in zip(SexLocation, SexCount):
        #添加数据标签
        plt.text(x, y, '%.0f'%y, ha='center', va='bottom')
index = Sex_index * 1.05 
plt.xticks(index, Sex_Survived.index, rotation=360)
plt.title('Survived status by sex')    
复制代码

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

5. Age

由于Age特征存在缺失值, 处理完缺失值, 再对其进行分析.

6. SibSp

从之前的描述性统计了解到, 兄弟姐妹与配偶的人数最多为8, 最少为0, 哪个更容易生存呢?

#生成列联表
SibSp_Survived = pd.crosstab(df_train['SibSp'], df_train['Survived'])
SibSp_Survived.plot(kind = 'bar')
plt.title('Survived status by SibSp')

可以看到, 大部分的SibSp为0, 且幸存率不大, 当SibSp数量为1,2时幸存率又有所增加, 再往上又降低.

7. Parch

通过上面的描述性统计了解到, 同样也可以分为大家庭(最多为6), 小家庭(最小为0), 他们的幸存率如何呢?

Parch_Survived = pd.crosstab(df_train['Parch'], df_train['Survived'])
Parch_Survived.plot(kind = 'bar')
plt.title('Survived status by Parch')

 同样可以看到, 大部分Parch为0, 幸存率不大, 当为1,2,3时, 有所增加, 再往上又有所减小.

8. Ticket

总人数891, 船票有681种, 说明部分人共用一张票, 什么人能共用一张票呢? 想必应该认识, 就需要对他们进行归类, 共用票的分为一类, 独自使用的分为一类:

复制代码
#计算每张船票使用的人数
Ticket_Count = df_train.groupby('Ticket', as_index = False)['PassengerId'].count()
#获取使用人数为1的船票
Ticket_Count_0 = Ticket_Count[Ticket_Count.PassengerId == 1]['Ticket']
#当船票在已经筛选出使用人数为1的船票中时, 将0赋值给GroupTicket, 否则将1赋值给GroupTicket
df_train['GroupTicket'] = np.where(df_train.Ticket.isin(Ticket_Count_0), 0, 1)
#绘制柱形图
GroupTicket_Survived = pd.crosstab(df_train['GroupTicket'], df_train['Survived'])
GroupTicket_Survived.plot(kind = 'bar')
plt.title('Survived status by GroupTicket')
复制代码

 很明显, 船上有同伴比孤身一人幸存的机会大.

9. Fare

票价, 最小为0, 最大为512.3292, 生存率到底和票价有没有关系呢?对Fare进行分组对比:

复制代码
#对Fare进行分组: 2**10>891分成10组, 组距为(最大值512.3292-最小值0)/10取值60
bins = [0, 60, 120, 180, 240, 300, 360, 420, 480, 540, 600]
df_train['GroupFare'] = pd.cut(df_train.Fare, bins, right = False)
GroupFare_Survived = pd.crosstab(df_train['GroupFare'], df_train['Survived'])
#GroupFare_Survived.plot(kind = 'bar')
#plt.title('Survived status by GroupFare')
GroupFare_Survived.iloc[2:].plot(kind = 'bar')
plt.title('Survived status by GroupFare(Fare>=120)')
复制代码

可以看到随着票价的增长, 幸存机会也会变大.

10. Cabin

由于含有大量缺失值, 处理完缺失值再对其进行分析.

11.Embarked

同样也含有缺失值, 处理完缺失值在对其进行分析.

 

以上便是对特征中无缺失部分进行分析, 下一步则会在特征工程中对缺失部分进行处理

4. 特征工程

4.1 缺失值处理

缺失值主要是由人为原因和机械原因造成的数据缺失, 在pandas中用NaN或者NaT表示, 它的处理方式有多种:

1. 用某些集中趋势度量(平均数, 众数)进行对缺失值进行填充.

2. 用统计模型来预测缺失值, 比如回归模型, 决策树, 随机森林

3. 删除缺失值

4. 保留缺失值

究竟采用处理方式呢, 应当结合具体的场景进行选择.

在缺失值处理之前, 应当将数据拷贝一份, 以保证原始数据的完整性

train = df_train.copy()

4.1.1 Embarked缺失值处理

通过以上, 我们已经知道Embarked字段中缺失2个, 且数据中S最多, 达到644个, 占比644/891=72%, 那么我们就采用众数进行填充.

train['Embarked'] = train['Embarked'].fillna(train['Embarked'].mode()[0])

4.1.2 Cabin缺失值处理

Cabin缺失687个, 占比687/891=77%, 缺失数据太多, 是否删除呢? 舱位缺失可能代表这些人没有舱位, 不妨用'NO'来填充.

train['Cabin'] = train['Cabin'].fillna('NO')

4.1.3 Age缺失值处理

Age缺失177个, 占比177/891=20%, 缺失数据也不少, 而且Age在本次分析中也尤其重要(孩子和老人属于弱势群体, 应当更容易获救), 不能删除也不能保留, 那么到底采用哪种方式呢? 由于是第一次项目, 就采用简单点的, 采用与头衔相对应的年龄中位数进行填补.

复制代码
#求出每个头衔对应的年龄中位数
Age_Appellation_median = train.groupby('Appellation')['Age'].median()
#在当前表设置Appellation为索引 
train.set_index('Appellation', inplace = True)
#在当前表填充缺失值
train.Age.fillna(Age_Appellation_median, inplace = True)
#重置索引
train.reset_index(inplace = True)
复制代码

此时, 就完成了对Age字段中缺失值的填充.

检查一下, 检查是否存在缺失值, 有多种方法, 这里采用第三种: 顺带看下均值, 中位数

#第一种: 返回0即表示没有缺失值
train.Age.isnull().sum()
#第二种: 返回False即表示没有缺失值
train.Age.isnull().any()
#第三种: 描述性统计
train.Age.describe()
count    891.000000
mean      29.392447
std       13.268389
min        0.420000
25%       21.000000
50%       30.000000
75%       35.000000
max       80.000000
Name: Age, dtype: float64

完成了缺失值的处理, 接下来对缺失特征进行分析

4.2 缺失特征分析

4.2.1 Embarked

#绘制柱形图
Embarked_Survived = pd.crosstab(train['Embarked'], train['Survived'])
Embarked_Survived.plot(kind = 'bar')
plt.title('Survived status by Embarked') 

C港生存机会明显高于Q港, S港, C港的有钱人多吗?这里不再深究, 现能确定的是它与生存相关.

4.2.2 Cabin

#将没有舱位的归为0, 有舱位归为1.
train['GroupCabin'] = np.where(train.Cabin == 'NO', 0, 1)
#绘制柱形图
GroupCabin_Survived = pd.crosstab(train['GroupCabin'], train['Survived'])
GroupCabin_Survived.plot(kind = 'bar')
plt.title('Survived status by GroupCabin')

有舱位的比没有舱位的幸存机会大.

4.2.3 Age

#对Age进行分组: 2**10>891分成10组, 组距为(最大值80-最小值0)/10 =8取9
bins = [0, 9, 18, 27, 36, 45, 54, 63, 72, 81, 90]
train['GroupAge'] = pd.cut(train.Age, bins)
GroupAge_Survived = pd.crosstab(train['GroupAge'], train['Survived'])
GroupAge_Survived.plot(kind = 'bar')
plt.title('Survived status by GroupAge')

正如料想的那样: 小孩幸存机会更大.

到现在我们已经完成所有特征的分析, 接下来看一下能否在这些特征的基础上提取一些新的特征.

4.3 新特征的提取

通过以上的分析, 我们已经了解到生存率相关的特征:

Pclass, Appellation(Name中提取), Sex, GroupAge(对Age分组), SibSp, Parch, GroupTicket(对Ticket分组), GroupFare(对Fare分组), GroupCabin(对Cabin分组), Embarked.

1. Pclass中没有更多信息可供提取, 且为定量变量, 这里不作处理. 

2. Appellation是定性变量, 将其转化为定量变量: 

train['Appellation'] = train.Appellation.map({'Mr': 0, 'Mrs': 1, 'Miss': 2, 'Master': 3, 'Rare': 4})
train.Appellation.unique()

3. Sex是定性变量, 将其转化为定量变量, 即用0表示female, 1表示male

train['Sex'] = train['Sex'].map({'female': 0, 'male': 1})

4. 按照GroupAge特征的范围将Age分为10组.

复制代码
train.loc[train['Age'] < 9, 'Age'] = 0
train.loc[(train['Age'] >= 9) & (train['Age'] < 18), 'Age'] = 1
train.loc[(train['Age'] >= 18) & (train['Age'] < 27), 'Age'] = 2
train.loc[(train['Age'] >= 27) & (train['Age'] < 36), 'Age'] = 3
train.loc[(train['Age'] >= 36) & (train['Age'] < 45), 'Age'] = 4
train.loc[(train['Age'] >= 45) & (train['Age'] < 54), 'Age'] = 5
train.loc[(train['Age'] >= 54) & (train['Age'] < 63), 'Age'] = 6
train.loc[(train['Age'] >= 63) & (train['Age'] < 72), 'Age'] = 7
train.loc[(train['Age'] >= 72) & (train['Age'] < 81), 'Age'] = 8
train.loc[(train['Age'] >= 81) & (train['Age'] < 90), 'Age'] = 9
train.Age.unique()
复制代码
array([2., 4., 3., 6., 0., 1., 7., 5., 8.])

 5. 将SibSp和Parch这两个特征组合成FamilySize特征

#当SibSp和Parch都为0时, 则孤身一人.
train['FamilySize'] = train['SibSp'] + train['Parch'] + 1
train.FamilySize.unique()
array([ 2,  1,  5,  3,  7,  6,  4,  8, 11], dtype=int64)

 6. GroupTicket是定量变量, 不作处理

 7. 按照GroupFare特征的范围将Fare分成10组:

复制代码
train.loc[train['Fare'] < 60, 'Fare'] = 0
train.loc[(train['Fare'] >= 60) & (train['Fare'] < 120), 'Fare'] = 1
train.loc[(train['Fare'] >= 120) & (train['Fare'] < 180), 'Fare'] = 2
train.loc[(train['Fare'] >= 180) & (train['Fare'] < 240), 'Fare'] = 3
train.loc[(train['Fare'] >= 240) & (train['Fare'] < 300), 'Fare'] = 4
train.loc[(train['Fare'] >= 300) & (train['Fare'] < 360), 'Fare'] = 5
train.loc[(train['Fare'] >= 360) & (train['Fare'] < 420), 'Fare'] = 6
train.loc[(train['Fare'] >= 420) & (train['Fare'] < 480), 'Fare'] = 7
train.loc[(train['Fare'] >= 480) & (train['Fare'] < 540), 'Fare'] = 8
train.loc[(train['Fare'] >= 540) & (train['Fare'] < 600), 'Fare'] = 9
train.Fare.unique()
复制代码
array([0., 1., 4., 2., 8., 3.])

 8. GroupCabin是定量变量, 不作处理

 9. Embarked是定类变量, 转化为定量变量.

train['Embarked'] = train.Embarked.map({'S': 0, 'C': 1, 'Q': 2})

 现有特征:

 PassengerId, Survived, Pclass, Name, Appellation, Sex, Age, GroupAge, SibSp, Parch, FamilySize, Ticket, GroupTicket, Fare, GroupFare, Cabin, GroupCabin, Embarked.

 删除重复多余的以及与Survived不相关的:

train.drop(['PassengerId', 'Name', 'GroupAge', 'SibSp', 'Parch', 'Ticket', 'GroupFare', 'Cabin'], axis = 1, inplace =True)

 删除后, 现有特征:

 Survived, Pclass, Appellation, Sex, Age, FamilySize, GroupTicket, Fare, GroupCabin, Embarked.

 

 到这里, 数据就处理完了, 下一步就是建立模型

5. 构建模型

5.1,逻辑回归模型

  逻辑回归也是只选择了几个比较全的特征,准确率还好,达到了: 81.56424581005587%。代码如下:

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 import pandas as pd import numpy as np import matplotlib.pyplot as plt import warnings import seaborn as sns from sklearn.linear_model import LinearRegression, LogisticRegression from sklearn.model_selection import KFold, train_test_split from sklearn.ensemble import RandomForestClassifier   warnings.filterwarnings('ignore')     def load_dataset(trainfile, testfile):     train = pd.read_csv(trainfile)     test = pd.read_csv(testfile)     train['Age'] = train['Age'].fillna(train['Age'].median())     test['Age'] = test['Age'].fillna(test['Age'].median())     # replace all the occurences of male with the number 0     train.loc[train['Sex'] == 'male''Sex'] = 0     train.loc[train['Sex'] == 'female''Sex'] = 1     test.loc[test['Sex'] == 'male''Sex'] = 0     test.loc[test['Sex'] == 'female''Sex'] = 1     # .fillna() 为数据填充函数  用括号里面的东西填充     train['Embarked'] = train['Embarked'].fillna('S')     train.loc[train['Embarked'] == 'S''Embarked'] = 0     train.loc[train['Embarked'] == 'C''Embarked'] = 1     train.loc[train['Embarked'] == 'Q''Embarked'] = 2     test['Embarked'] = test['Embarked'].fillna('S')     test.loc[test['Embarked'] == 'S''Embarked'] = 0     test.loc[test['Embarked'] == 'C''Embarked'] = 1     test.loc[test['Embarked'] == 'Q''Embarked'] = 2     test['Fare'] = test['Fare'].fillna(test['Fare'].median())     traindata, trainlabel = train.drop('Survived', axis=1), train['Survived']  # train.pop('Survived')     testdata = test     print(traindata.shape, trainlabel.shape, testdata.shape)     # (891, 11) (891,) (418, 11)     return traindata, trainlabel, testdata   def logistic_regression_train(traindata, trainlabel, testdata):     # the columns we'll use to predict the target     all_variables = ['PassengerID''Survived''Pclass''Name''Sex''Age''SibSp''Parch',                      'Ticket''Fare''Cabin''Embarked']     predictors = ['Pclass''Sex''Age''SibSp''Parch''Fare''Embarked']     traindata, testdata = traindata[predictors], testdata[predictors]     # print(traindata.shape, trainlabel.shape, testdata.shape)  # (891, 7) (891,) (418, 7)     # print(testdata.info())     trainSet, testSet, trainlabel, testlabel = train_test_split(traindata, trainlabel,                                                                 test_size=0.2, random_state=12345)     # initialize our algorithm class     clf = LogisticRegression()     # training the algorithm using the predictors and target     clf.fit(trainSet, trainlabel)     test_accuracy = clf.score(testSet, testlabel) * 100     print("正确率为   %s%%" % test_accuracy)  # 正确率为   81.56424581005587%     # res = clf.predict(testdata)       if __name__ == '__main__':     trainfile = 'data/titanic_train.csv'     testfile = 'data/test.csv'     traindata, trainlabel, testdata = load_dataset(trainfile, testfile)     logistic_regression_train(traindata, trainlabel, testdata)

 

5.2,随机森林模型

  我们依旧选择和上面相同的特征,使用随机森林来做,准确率为:81.56424581005587%。效果还行,不过也只是和逻辑回归一样,代码如下:

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 import pandas as pd import numpy as np import matplotlib.pyplot as plt import warnings import seaborn as sns from sklearn.linear_model import LinearRegression, LogisticRegression from sklearn.model_selection import KFold, train_test_split from sklearn.ensemble import RandomForestClassifier   warnings.filterwarnings('ignore')     def load_dataset(trainfile, testfile):     train = pd.read_csv(trainfile)     test = pd.read_csv(testfile)     train['Age'] = train['Age'].fillna(train['Age'].median())     test['Age'] = test['Age'].fillna(test['Age'].median())     # replace all the occurences of male with the number 0     train.loc[train['Sex'] == 'male''Sex'] = 0     train.loc[train['Sex'] == 'female''Sex'] = 1     test.loc[test['Sex'] == 'male''Sex'] = 0     test.loc[test['Sex'] == 'female''Sex'] = 1     # .fillna() 为数据填充函数  用括号里面的东西填充     train['Embarked'] = train['Embarked'].fillna('S')     train.loc[train['Embarked'] == 'S''Embarked'] = 0     train.loc[train['Embarked'] == 'C''Embarked'] = 1     train.loc[train['Embarked'] == 'Q''Embarked'] = 2     test['Embarked'] = test['Embarked'].fillna('S')     test.loc[test['Embarked'] == 'S''Embarked'] = 0     test.loc[test['Embarked'] == 'C''Embarked'] = 1     test.loc[test['Embarked'] == 'Q''Embarked'] = 2     test['Fare'] = test['Fare'].fillna(test['Fare'].median())     traindata, trainlabel = train.drop('Survived', axis=1), train['Survived']  # train.pop('Survived')     testdata = test     print(traindata.shape, trainlabel.shape, testdata.shape)     # (891, 11) (891,) (418, 11)     return traindata, trainlabel, testdata     def random_forestclassifier_train(traindata, trainlabel, testdata):     predictors = ['Pclass''Sex''Age''SibSp''Parch''Fare''Embarked']     traindata, testdata = traindata[predictors], testdata[predictors]     # print(traindata.shape, trainlabel.shape, testdata.shape)  # (891, 7) (891,) (418, 7)     # print(testdata.info())     trainSet, testSet, trainlabel, testlabel = train_test_split(traindata, trainlabel,                                                                 test_size=0.2, random_state=12345)     # initialize our algorithm class     clf = RandomForestClassifier(random_state=1, n_estimators=100,                                  min_samples_split=4, min_samples_leaf=2)     # training the algorithm using the predictors and target     clf.fit(trainSet, trainlabel)     test_accuracy = clf.score(testSet, testlabel) * 100     print("正确率为   %s%%" % test_accuracy)  # 正确率为   81.56424581005587%     if __name__ == '__main__':     trainfile = 'data/titanic_train.csv'     testfile = 'data/test.csv'     traindata, trainlabel, testdata = load_dataset(trainfile, testfile)     random_forestclassifier_train(traindata, trainlabel, testdata)

 

 5.3,集成学习模型

  这里简单的集成GradientBoostingClassifier和LogisticRegression 两种算法。

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 import pandas as pd import numpy as np import matplotlib.pyplot as plt import warnings import seaborn as sns from sklearn.linear_model import LinearRegression, LogisticRegression from sklearn.model_selection import KFold, train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.feature_selection import SelectKBest, f_classif from sklearn.ensemble import GradientBoostingClassifier import re   warnings.filterwarnings('ignore')     # A function to get the title from a name def get_title(name):     # use a regular expression to search for a title     title_search = re.search('([A-Za-z]+)\.', name)     # if the title exists, extract and return it     if title_search:         return title_search.group(1)     return ''     def load_dataset(trainfile, testfile):     train = pd.read_csv(trainfile)     test = pd.read_csv(testfile)     train['Age'] = train['Age'].fillna(train['Age'].median())     test['Age'] = test['Age'].fillna(test['Age'].median())     # replace all the occurences of male with the number 0     train.loc[train['Sex'] == 'male''Sex'] = 0     train.loc[train['Sex'] == 'female''Sex'] = 1     test.loc[test['Sex'] == 'male''Sex'] = 0     test.loc[test['Sex'] == 'female''Sex'] = 1     # .fillna() 为数据填充函数  用括号里面的东西填充     train['Embarked'] = train['Embarked'].fillna('S')     train.loc[train['Embarked'] == 'S''Embarked'] = 0     train.loc[train['Embarked'] == 'C''Embarked'] = 1     train.loc[train['Embarked'] == 'Q''Embarked'] = 2     test['Embarked'] = test['Embarked'].fillna('S')     test.loc[test['Embarked'] == 'S''Embarked'] = 0     test.loc[test['Embarked'] == 'C''Embarked'] = 1     test.loc[test['Embarked'] == 'Q''Embarked'] = 2     test['Fare'] = test['Fare'].fillna(test['Fare'].median())     # generating a familysize column  是指所有的家庭成员     train['FamilySize'] = train['SibSp'] + train['Parch']     test['FamilySize'] = test['SibSp'] + test['Parch']       # the .apply method generates a new series     train['NameLength'] = train['Name'].apply(lambda x: len(x))     test['NameLength'] = test['Name'].apply(lambda x: len(x))       titles_train = train['Name'].apply(get_title)     titles_test = test['Name'].apply(get_title)     title_mapping = {         'Mr': 1,         'Miss': 2,         'Mrs': 3,         'Master': 4,         'Rev': 6,         'Dr': 5,         'Col': 7,         'Mlle': 8,         'Ms': 2,         'Major': 7,         'Don': 9,         'Countess': 10,         'Mme': 8,         'Jonkheer': 10,         'Sir': 9,         'Dona': 9,         'Capt': 7,         'Lady': 10,     }     for k, v in title_mapping.items():         titles_train[titles_train == k] = v     train['Title'] = titles_train     for k, v in title_mapping.items():         titles_test[titles_test == k] = v     test['Title'] = titles_test     # print(pd.value_counts(titles_train))     traindata, trainlabel = train.drop('Survived', axis=1), train['Survived']  # train.pop('Survived')     testdata = test     print(traindata.shape, trainlabel.shape, testdata.shape)     # (891, 11) (891,) (418, 11)     return traindata, trainlabel, testdata       def emsemble_model_train(traindata, trainlabel, testdata):     # the algorithms we want to ensemble     # we're using the more linear predictors for the logistic regression,     # and everything with the gradient boosting classifier     algorithms = [         [GradientBoostingClassifier(random_state=1, n_estimators=25, max_depth=3),          ['Pclass''Sex''Fare''FamilySize''Title''Age''Embarked', ]],         [LogisticRegression(random_state=1),          ['Pclass''Sex''Fare''FamilySize''Title''Age''Embarked', ]]     ]     # initialize the cross validation folds     kf = KFold(n_splits=3, random_state=1)     predictions = []     for train_index, test_index in kf.split(traindata):         # print(train_index, test_index)         full_test_predictions = []         for alg, predictors in algorithms:             train_predictors = (traindata[predictors].iloc[train_index, :])             train_target = trainlabel.iloc[train_index]             alg.fit(train_predictors, train_target)             test_predictions = alg.predict(traindata[predictors].iloc[test_index, :])             full_test_predictions.append(test_predictions)         # use a simple ensembling scheme         test_predictions = (full_test_predictions[0] + full_test_predictions[1]) / 2         test_predictions[test_predictions <= 0.5] = 0         test_predictions[test_predictions >= 0.5] = 1         predictions.append(test_predictions)     predictions = np.concatenate(predictions, axis=0)     # compute accuracy bu comparing to the training data     accuracy = sum(predictions[predictions == trainlabel]) / len(predictions)     print(accuracy)   def emsemble_model_train(traindata, trainlabel, testdata):     # the algorithms we want to ensemble     # we're using the more linear predictors for the logistic regression,     # and everything with the gradient boosting classifier     predictors = ['Pclass''Sex''Fare''FamilySize''Title''Age''Embarked', ]     traindata, testdata = traindata[predictors], testdata[predictors]     trainSet, testSet, trainlabel, testlabel = train_test_split(traindata, trainlabel,                                                                 test_size=0.2, random_state=12345)     # initialize our algorithm class     clf1 = GradientBoostingClassifier(random_state=1, n_estimators=25, max_depth=3)     clf2 = LogisticRegression(random_state=1)     # training the algorithm using the predictors and target     clf1.fit(trainSet, trainlabel)     clf2.fit(trainSet, trainlabel)     test_accuracy1 = clf1.score(testSet, testlabel) * 100     test_accuracy2 = clf2.score(testSet, testlabel) * 100     print(test_accuracy1, test_accuracy2)  # 78.77094972067039   80.44692737430168     print("正确率为   %s%%" % ((test_accuracy1+test_accuracy2)/2))  # 正确率为   79.60893854748603%     if __name__ == '__main__':     trainfile = 'data/titanic_train.csv'     testfile = 'data/test.csv'     traindata, trainlabel, testdata = load_dataset(trainfile, testfile)     emsemble_model_train(traindata, trainlabel, testdata)

 

 

 6.总结

通过大量数据分析,我们可得出如下结论:

①女性的获救率依旧远远高于男性,所以说,很有可能性别Sex对Survived具有显著的影响

②随着等级舱的降低,不论是男性或女性,获救率也在降低。所以可能Pclass也对Surived有显著影响,

也就是说乘客的身份/地位/财富/背景 对乘客的获救率可能有显著影响。

 

标签:Fare,泰坦尼克号,机器,幸存者,Embarked,Age,train,Survived,test
From: https://www.cnblogs.com/zhangzhanglingling/p/17471249.html

相关文章

  • 业余开源项目训练出最准确新冠预测机器学习模型
    什么样的机器学习项目会被美国疾控中心CDC、纽约时报、经济学人杂志等多家机构和媒体所引用提及,还被Facebook的ChiefAIExecutor称为最准确的新冠死亡预测模型?这就是今天要给大家分享的covid-projection——一个来自一名普通美国华裔数据科学家的的业余开源机器学习项目。covid-......
  • 业余开源项目训练出最准确新冠预测机器学习模型
    什么样的机器学习项目会被美国疾控中心CDC、纽约时报、经济学人杂志等多家机构和媒体所引用提及,还被Facebook的ChiefAIExecutor称为最准确的新冠死亡预测模型?这就是今天要给大家分享的covid-projection——一个来自一名普通美国华裔数据科学家的的业余开源机器学习项目。covid......
  • 钉钉机器人客服系统AI知识库对接
    钉钉机器人比较灵活方便,可以按照下面的方式操作,我们现在创建企业内部应用机器人可以单聊,也可以在群里进行@,机器人会通过GPT私有数据知识库自动回复应用场景企业内部知识库机器人,企业员工可以在钉钉上对内部的知识进行咨询支持关键词匹配自动回复支持GPT私有数据聊天咨询创建应......
  • 使用Python开发会聊天的智能小机器人
    本文重点演示使用socket实现TCP通信以及字典和集合的用法,客户端发来信息之后,服务端会尽量猜测客户端要表达的真正意思,然后选择合适的内容进行回复。服务端小机器人代码:importsocketfromos.pathimportcommonprefixwords={'howareyou?':'Fine,thankyou.','howo......
  • 高考答题卡怎么被机器识别?基于OpenCV答题卡识别模拟-米尔ARM+FPGA异构开发板
    本篇测评由优秀测评者“筑梦者与梦同行”提供。 01.前言MYD-JX8MMA7SDK发布说明 根据下图文件内容可以知道myir-image-full系统支持的功能,其支持OpenCV,也就不用在格外安装相关驱动包等,省了很多事情。02.MYD-JX8MMA7软件评估指南本文介绍了Python的基本操作,在文档中10......
  • 开启人机协作新时代:协作机器人的应用与展望
    原创|文BFT机器人01 蓄势待发,产业变革新引擎近年来,在政策扶持、资本助推和技术创新的共同作用下,产业迎来发展黄金期。日前,各行各业正经历产业智能化转型,机器人市场规模不断扩大,发展前景广阔,但机器人赛道的竞争也日趋激烈。其中,协作机器人凭借其安全性强,易于编程,便于融入产线,落......
  • 机器学习算法(一)之KNN算法理论
    KNN算法又称为K近邻算法,是机器学习中比较简单的数据挖掘算法,其基本思想也简单,将“距离相近的,判定为同一类”,在整个样本空间中,k个最为接近的样本,大多数属于同一类别。对其进行一个细致的理解如下:如果在操场中心有一只羊,在以它为中心的周围,分布着奶牛和山羊,现在要对这只羊进行分类,......
  • 机器翻译​
    机器翻译现成工具:沙拉查词机器翻译原理最佳翻译会意会的机器翻译:你有算法,我有意会 现成工具:沙拉查词网页:https://saladict.crimx.com/大赞,Google浏览器最好用的扩展之一! 机器翻译原理如果一个事件的概率会因为某个条件而产生变化,那在这个条件发生的情况下,这个事件发生的概率......
  • QuasarRAT-windows下远程控制工具 之前用过 生成Client.exe 然后远控你的机器
    QuasarRAT-windows下远程控制工具怀揣梦想的大鸡腿2018-02-2810:00:314873收藏1分类专栏:安全版权资源:https://github.com/quasar/QuasarRATQuasar是一种用C#编码的快速轻量级远程管理工具。Quasar提供高稳定性和简单易用的用户界面,是远程管理解决方案。就一开源的远控......
  • 《机器学习实战》学习笔记(4)—— Logistic 回归
    1Logistic回归算法描述工作原理:为了实现Logistic回归分类器,可以在每个特征上都乘以一个回归系数,然后把所有结果的值相加,将这个总和带入Sigmoid函数中,进而得到一个范围在0-1之间的数值。任何大于0.5的数据被分入1类别,任何小于0.5的数据被分入0类别。Logistic回归也可以被看......