泰坦尼克号人员是否生存预测

作者: 艾瑞娅 | 来源:发表于2017-03-27 10:17 被阅读0次

    本篇文章的灵感来源于 han xiaoyang大神博主的博文,当然同时运用了kaggle的有关泰坦尼克号的数据。毕竟没有数据就没有研究嘛。。。

      现在就让我们进行本次的预测,首先说明一下本次预测的目的:通过分析原始数据集来进行预测假如当泰坦尼克号触礁时哪些乘客将会被救哪些乘客将会坠入大海死亡的怀抱。。。。虽然是马后炮,(PS:我们已经知道在泰坦尼克号触礁之后谁还活着,但是这也是一种预测,我们可以通过已有的数据进行未来的预测。)
      老套路,首先先看一下原始数据集:


    原始数据集.png

      看到这些原始数据集就感觉生活不美好。但是默默地说,,分析还是要做的。首先通过分析原始数据集:我们可以发现Survived,Sex,Embarked,Pclass是有分类的,譬如Survived只有存活或者不存活(0或者1),Sex只有男或者女(male or female 当然也有其他的。。。。性别。。在此笔者就不描述了),Embarked代表出发港口(这里也只有三个港口可供选择),Pclass则代表人群的高贵程度。。。(譬如Pclass==1代表这哥们或者姐妹起码也是马云级别的人物。。)所以呢,难道你们不对这些分类的存活数量感兴趣吗???!!反正我很感兴趣,譬如我想知道当Pclass==1时,存活比例是多少。。当Pclass==3时,存活比例是多少。。。我身为一个Pclass==3的屌丝当然关心自己的生存几率了。。。是时候展示真正的图表了

    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    plt.subplot2grid((2,3),(0,0))
    data['Survived'].value_counts().plot(kind='bar')
    plt.legend()
    plt.title('存活人数统计')
    
    plt.subplot2grid((2,3),(0,1))
    data['Pclass'].value_counts().plot(kind='bar')
    plt.title('乘客等级分布')
    
    plt.subplot2grid((2,3),(0,2))
    plt.title('存活比例与年龄的关系')
    sns.stripplot('Survived','Age',data=data[['Survived','Age']])
    
    plt.subplot2grid((2,3),(1,0),colspan=2)
    data[data['Pclass']==1]['Age'].plot(kind='kde')
    data[data['Pclass']==2]['Age'].plot(kind='kde')
    data[data['Pclass']==3]['Age'].plot(kind='kde')
    plt.xlabel('年龄')
    plt.ylabel('密度')
    plt.legend((u'头等舱',u'次等舱',u'低等舱'))
    
    plt.subplot2grid((2,3),(1,2))
    plt.title('登录港口人口统计')
    sns.countplot(x='Embarked',data=data[['Embarked']],palette='muted')
    # 计算不同等级的人群获救数量
    sns.factorplot(x='Survived',col='Pclass',hue='Pclass',kind='count',data=data,col_wrap=3,legend=True,palette='husl')
    

    最终显示图表如下所示:

    统计图表.png

    1.通过第一个图表可以看出存活认识要远远低于死亡人数。
    2.第二个图表表示像我这样的普通人还是比较多的。
    3.船上低等舱和次等舱所有的人的年龄基本都在20-40岁之间,但是可以发现头等舱中的年龄分布在20-60岁之间。同时可以发现40-60岁的上层人要高于低等舱和次等舱。。。这是不是可以表明我们在40-60岁有很大的可能性走上人生巅峰,迎娶白富美。从此步入上层生活。当然啦。。。前提是40岁前好好努力才可以。。。。
    4.最后一张图明确的表现出港口S绝对是个热门港口,因为基本一大半的游客都选择从这个港口登陆泰坦尼克号。
      在这部伟大的作品中有这么一段台词:Lady and childern first!(我瞎编的台词),所以我想观察一下这就话是否适用在这个预测中,那就观察一下男女获救比例吧:

    sns.factorplot(x='Survived',col='Sex',kind='count',data=data,col_wrap=3,legend=True,palette='Set3')
    
    男女获救比例.png

      很符合常识,不是吗?女性获救比例很高。。。同时可以发现死亡的绝大多数都是男性,这个其实可以想象的到。
      接下来就是见识见识是否人人平等的时候到了。。。。。:

    sns.factorplot(x='Survived',col='Pclass',hue='Pclass',kind='count',data=data,col_wrap=3,legend=True,palette='husl')
    
    各阶层存活人数.png

      看清楚了吗???没看清楚的话我再搞一个比例图供大家欣赏一下。。。

    各阶层存活比例.png

      是不是很想说一声:what's the fuck? 通过这两张图表我们可以很容易的发现:处于上层的人的的存活比例很明显的更高,。。同时低层的人死亡率明显更高。。。
      接下来我们可以观察一下每个阶层等级存活的人数。

    sns.factorplot(x='Pclass', col='Survived', hue='Sex', kind='count', data=data[['Pclass', 'Survived', 'Sex']],palette='Set2')
    

    最终显示如下所示:

    数据5.png

      从这张图中可以看出越有权势的人存活几率越大,,,对的,没说错。越有权势的人存活几率越大。
      当然我们可以观察一下不同港口的存活比例:

    sns.factorplot(x='Embarked', col='Survived', hue='Sex', kind='count', data=data[['Embarked', 'Survived', 'Sex']], palette='Set1')
    

    结果如下所示:

    口获救直方图.png

      从这张图可以看出S港口的存活率和死亡率都比较高,,,我猜想原因可能是因为该港口人数多。。也就是基数大。所以我制作了一张饼状图进行观察。

    plt.subplot2grid((1, 2), (0, 0))
    plt.title('判断不同港口的未获救比例')
    colors = ["#9b59b6", "#3498db", "#2ecc71"]
    data[data['Survived'] == 0]['Embarked'].value_counts().plot(kind='pie', autopct='%.2f', colors=colors,
                                                                explode=(0, 0.1, 0))
    plt.subplot2grid((1, 2), (0, 1))
    plt.title('判断不同港口的获救比例')
    data[data['Survived'] == 1]['Embarked'].value_counts().plot(kind='pie', autopct='%1.1f%%', colors=colors,
                                                                explode=(0, 0.1, 0))
    

    最终图表显示:

    港口获救比例图.png

      所以此时我对S港口进行格外留意。
    现在进行不同港口进出乘客人员总数统计:

     plt.title('不同港口的登陆人数')
     sns.countplot(x='Embarked',data=data[['Embarked']],palette='Set1')
    

      结果果然和我们的预期一样。S港口的基数很大。

    不同港口人数统计.png

    数据预处理

      通过观察原始数据可以发现。在Age 这一选项中存在一定量的缺失值。同时 Cabin 这一选项中也存在一定量的缺失值。Age 这一选项毋庸置疑必须要完整的数据,用脚想一下也知道,小孩子肯定是优先被考虑获救的。所以我们需要年龄这一选项进行评估。而cabin这一选项的话,并不确定,所以我选择查看一下有Cabin信息和无Cabin信息的获救比例:

    plt.subplot2grid((1,2),(0,0))
    plt.title('当Cabin有相关信息时')
    data[data['Cabin'].notnull()]['Survived'].value_counts().plot(kind='bar')
    plt.subplot2grid((1,2),(0,1))
    plt.title('当Cabin没有相关信息时')
    data[data['Cabin'].isnull()]['Survived'].value_counts().plot(kind='bar')
    plt.show()
    

    最终显示结果如下所示:

    Cabin影响因素.png

      通过这张图可以看出。若有Cabin这一选项可以发现获救的概率会大大增加。所以Cabin应该很有必要进行处理一下。但是此处我就舍弃了Name,Ticket,选项。因为我想不出这些有何联系。所以暂时先排除这些因素。
      所以此时就可以进行数据预处理,看过我第一篇文章的朋友应该知道我接下来要做什么。当然是将所有非数值类型的选项全部转换为数值类型。这样我们就需要pandas中的get_dummies()函数。废话不多说直接上代码:

    import pandas as pd
    from sklearn.ensemble import RandomForestRegressor
    from scipy.interpolate import lagrange
    from sklearn.preprocessing import Imputer
    filename = 'D:/数据/RMS/test.csv'
    # filename='D:/数据/RMS/age.xls'
    outputfile = 'D:/数据/RMS/trainprocess.csv'
    data = pd.read_csv(filename)
    
    age_data = data[['Age', 'Fare', 'Parch', 'SibSp', 'Pclass']]
    #     乘客分为已知和未知
    age_known = age_data[age_data['Age'].notnull()].as_matrix()
    age_unknown = age_data[age_data['Age'].isnull()].as_matrix()
    # y为目标年龄
    y = age_known[:, 0]
    # x为特征属性
    x = age_known[:, 1:]
    rfr = RandomForestRegressor(n_estimators=1000, n_jobs=-1, random_state=50, max_features="auto")
    rfr.fit(x, y)
    predict = rfr.predict(age_unknown[:, 1::])
    # data.loc[(data['Age'].isnull()), 'Age'] = predict
    score = rfr.score(x, y)
    

      为了证明插值的准确,可以进行测试其准确率:

    插值准确率.png

      上述步骤是为了对Age进行补全。

    import pandas as pd
    import numpy as np
    import sklearn.preprocessing as processing
    from sklearn.linear_model import LogisticRegression
    from sklearn.model_selection import train_test_split
    from sklearn.ensemble import RandomForestClassifier
    from sklearn import svm
    
    filename = 'D:/数据/RMS/train.csv'
    outputfile = 'D:/数据/RMS/final1.csv'
    train_filename = 'D:/数据/RMS/trainprocess.csv'
    data = pd.read_csv(filename)
    data_test = pd.read_csv(train_filename)
    data_test = data_test[['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked', 'Cabin']]
    data_test.loc[(data_test['Cabin'].notnull()), 'Cabin'] = 'Yes'
    data_test.loc[(data_test['Cabin'].isnull()), 'Cabin'] = 'No'
    dummies_Embarked = pd.get_dummies(data_test['Embarked'], prefix='Embarked')
    dummies_Sex = pd.get_dummies(data_test['Sex'], prefix='Sex')
    dummies_Pclass = pd.get_dummies(data_test['Pclass'], prefix='Pclass')
    dummies_Cabin = pd.get_dummies(data_test['Cabin'], prefix='Cabin')
    data_test = pd.concat([data_test, dummies_Embarked, dummies_Sex, dummies_Pclass, dummies_Cabin], axis=1)
    data_test = data_test.drop(['Embarked', 'Sex', 'Pclass', 'Cabin'], axis=1)
    
    data = data[['Survived', 'Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked', 'Cabin']]
    data.loc[(data['Cabin'].notnull()), 'Cabin'] = 'Yes'
    data.loc[(data['Cabin'].isnull()), 'Cabin'] = 'No'
    dummies_Embarked = pd.get_dummies(data['Embarked'], prefix='Embarked')
    dummies_Sex = pd.get_dummies(data['Sex'], prefix='Sex')
    dummies_Pclass = pd.get_dummies(data['Pclass'], prefix='Pclass')
    dummies_Cabin = pd.get_dummies(data['Cabin'], prefix='Cabin')
    data = pd.concat([data, dummies_Embarked, dummies_Sex, dummies_Pclass, dummies_Cabin], axis=1)
    data = data.drop(['Embarked', 'Sex', 'Pclass', 'Cabin'], axis=1)
    

      通过这一步骤就可以实现把所有的非数值类型转换为数值类型。但是观察Ages这一选项可以发现Age年龄范围跳跃太大。熟悉数据挖掘预处理的朋友应该都知道,我们在数据预处理时要避免这种情况,还好Sklearn中有这一种处理方法。

    scaler = processing.StandardScaler()
    age_scale = scaler.fit(data['Age'])
    data['Age_scale'] = scaler.fit_transform(data['Age'], age_scale)
    fare_scale = scaler.fit(data['Fare'])
    data['Fare_scale'] = scaler.fit_transform(data['Fare'], fare_scale)
    data = data.drop(['Age', 'Fare'], axis=1)
    
    age_scale = scaler.fit(data_test['Age'])
    data_test['Age_scale'] = scaler.fit_transform(data_test['Age'], age_scale)
    fare_scale = scaler.fit(data_test['Fare'])
    data_test['Fare_scale'] = scaler.fit_transform(data_test['Fare'], fare_scale)
    data_test = data_test.drop(['Age', 'Fare'], axis=1)
    

      这一步骤就可以实现把Age所有的数据都缩放至[-1,1]之间。接下来就是模型运用了。在这方面我首先想到的就是随机森林模型。
    同样的和第一篇博文一样。训练模型如下所示:

    data_information = data.drop(['Survived'], axis=1).values
    data_Survived = data['Survived'].values
    X_train, X_test, y_train, y_test = train_test_split(data_information, data_Survived, test_size=0.5)
    # 逻辑回归模型测试
    lr = LogisticRegression()
    lr.fit(X_test, y_test)
    # print('LR\'s accuracy rate is:', lr.score(X_train, y_train))
    # 随机森林模型测试
    rfr = RandomForestClassifier()
    rfr.fit(X_test, y_test)
    # print('rfr\'s accuracy rate is:', rfr.score(X_train, y_train))
    # svm模型测试
    svm_model = svm.SVC()
    svm_model.fit(X_test, y_test)
    

    精确度如下所示:

    模型正确率.png

      接下来就采用随机森林模型进行评估。最终可以得到预测准确率如下所示:

    预测.png

      可以看出预测准确率高达85%。
      最终得到结果如下所示:

    最终结果.png

      Survived1代表添加Cabin选项,Survived2代表没有添加,corrent代表真实的数据。

    相关文章

      网友评论

        本文标题:泰坦尼克号人员是否生存预测

        本文链接:https://www.haomeiwen.com/subject/npkfottx.html