[机器学习入门]泰坦尼克生存预测

亿点题外话:

大家都熟悉『you jump i jump』的故事,豪华游艇倒了,大家都惊恐逃生,可是救生艇的数量有限,无法人人都有,副船长发话了『lady and kid first!』,所以是否获救其实并非随机,而是基于一些背景有rank先后的。
训练和测试数据是一些乘客的个人信息以及存活状况,要尝试根据它生成合适的模型并预测其他人的存活状况。

数据来源:

数据来源于 Kaggle,链接: TItanic 数据集

实践目标:

根据数据集中各个字段使用机器学习进行建模,来预测泰坦尼克沉船事件中的任一旅客生还的概率

初步分析:

首先观察给出的信息条目,检查数据的完整性,做出常识性推理

import pandas as pd
from pandas import Series,DataFrame

data_train =pd.read_csv('./titanic/train.csv')
data_train.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

再使用 describe(),得到数值型数据的一些分布

print(data_train.describe(include = 'all'))
 得到:
 PassengerIdSurvivedPclassAgeSibSpParchFare
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 NaN 0.000000 0.000000 7.910400
50% 446.000000 0.000000 3.000000 NaN 0.000000 0.000000 14.454200
75% 668.500000 1.000000 3.000000 NaN 1.000000 0.000000 31.000000
max 891.000000 1.000000 3.000000 80.000000 8.000000 6.000000 512.329200

从中,我们得到,整体的平均存活率为0.38,1等舱的人数少于2等舱少于3等舱,平均年龄为29.7,其余信息暂且也不知道是否有效这里先不罗列。

条目分析

  • PassengerId => 乘客ID,无关变量
  • Survived => 乘客是否存活
      为本次建模的因变量,其余为自变量
  • Pclass => 乘客等级(1/2/3等舱位)
  • Name => 乘客姓名
      按照常理,姓名应该是无关变量,但是本次建模中,姓名内包含了“Miss”、“Mrs”这类可以体现年龄的名称,以及“Master”这类体现身份地位的名称,故具有一定的参考意义。
  • Sex => 性别
  • Age => 年龄
      存在数据缺失,暂定通过姓名信息补全
  • SibSp => 堂兄弟/妹个数
  • Parch => 父母子女个数
  • Ticket => 船票信息,无关变量
  • Fare => 票价
  • Cabin => 客舱
      由于缺失过多,暂定以二元变量参与计算
  • Embarked => 登船港口
f,ax = plt.subplots(figsize=(16, 16))
sns.heatmap(data_train.corr(),annot=True,cmap = sns.diverging_palette(220, 10, as_cmap = True),linewidths=.9, fmt= '.3f',ax = ax)
plt.title('Pearson Correlation of Features', y=1.05, size=15)

相关性检验:各个变量之间的皮尔逊系数没有强相关性,可以直接选用这些变量进行建模

逐条分析

Pclass:

Survived_0 = data_train.Pclass[data_train.Survived == 0].value_counts()
Survived_1 = data_train.Pclass[data_train.Survived == 1].value_counts()
df = pd.DataFrame({u'live': Survived_1, u'unlive': Survived_0})
df.plot(kind='bar', stacked=True)
plt.show()

由常理推算,舱位可以体现经济状况,从而反映出是社会地位,那么在得救的时候就有了优先的权利,测了一下果然是酱紫,可见1/2等舱的存活率明显高于3等舱。那么这就成为了本次模型中一个很重要的特征。

Sex:

data_train = pd.read_csv('./titanic/train.csv')
Survived_m = data_train.Sex[data_train.Survived == 0].value_counts()
Survived_f = data_train.Sex[data_train.Survived == 1].value_counts()
df = pd.DataFrame({u'live': Survived_m, u'unlive': Survived_f})
df.plot(kind='bar', stacked=True)
plt.xticks(rotation=0)
plt.show()

由此可见船长那一句“lady first”大家践行的还是很好的,不只是喊喊口号,所以Sex也成为一项重要的特征。

Age:

与前两项自变量不同,Age缺少了部分的数据。

通常遇到缺值的情况,我们会有几种常见的处理方式

  • 如果缺值的样本占总数比例极高,我们可能就直接舍弃了,作为特征加入的话,可能反倒带入noise,影响最后的结果了
  • 如果缺值的样本适中,而该属性非连续值特征属性(比如说类目属性),那就把NaN作为一个新类别,加到类别特征中
  • 如果缺值的样本适中,而该属性为连续值特征属性,有时候我们会考虑给定一个step(比如这里的age,我们可以考虑每隔2/3岁为一个步长),然后把它离散化,之后把NaN作为一个type加到属性类目中。
  • 有些情况下,缺失的值个数并不是特别多,那我们也可以试着根据已有的值,拟合一下数据,补充上。
  • 本例中,后两种处理方式应该都是可行的,我们先试试拟合补全吧(虽然说没有特别多的背景可供我们拟合,这不一定是一个多么好的选择)

我们这里用scikit-learn中的RandomForest(参考CSDN韩小阳)来拟合一下缺失的年龄数据(注:RandomForest是一个用在原始数据中做不同采样,建立多颗DecisionTree,再进行average等等来降低过拟合现象,提高结果的机器学习算法)

from sklearn.ensemble import RandomForestRegressor
 
### 使用 RandomForestClassifier 填补缺失的年龄属性
def set_missing_ages(df):
    
    # 把已有的数值型特征取出来丢进Random Forest Regressor中
    age_df = df[['Age','Fare', 'Parch', 'SibSp', 'Pclass']]

    # 乘客分成已知年龄和未知年龄两部分
    known_age = age_df[age_df.Age.notnull()].values
    unknown_age = age_df[age_df.Age.isnull()].values

    y = known_age[:, 0]        # y即目标年龄
    X = known_age[:, 1:]        # X即特征属性值

    # fit到RandomForestRegressor之中
    rfr = RandomForestRegressor(random_state=0, n_estimators=2000, n_jobs=-1)
    rfr.fit(X, y)
    
    # 用得到的模型进行未知年龄结果预测
    predictedAges = rfr.predict(unknown_age[:, 1::])
    
    # 用得到的预测结果填补原缺失数据
    df.loc[ (df.Age.isnull()), 'Age' ] = predictedAges 
    
    return df, rfr

def set_Cabin_type(df):
    df.loc[ (df.Cabin.notnull()), 'Cabin' ] = 1
    df.loc[ (df.Cabin.isnull()), 'Cabin' ] = 0
    return df

data_train, rfr = set_missing_ages(data_train)
data_train = set_Cabin_type(data_train)

 对 'SibSp'、'Parch'、'Sex'列生成新列

data_train['FamilySize'] = data_train ['SibSp'] + data_train['Parch'] + 1
data_train['Sex'][data_train['Sex'] == 'male'] = 1
data_train['Sex'][data_train['Sex'] == 'female'] = 0
data_train['IsAlone'] = 1
data_train['IsAlone'].loc[data_train['FamilySize'] > 1] = 0
  • 用“FamilySize”代替 'SibSp'、'Parch',因为通过对 'SibSp'、'Parch'单独分析发现没有显著特征,于是尝试合并两项(体现家族人数,也许大家族优先?)
  • 生成 IsAlone 由于familysize数据较为分散,为了更好预测集中数据特征,将乘客分为一人与多人
  • 用0/1代替 male/female

“Age”和“Fare”的数据收敛处理:

from sklearn.preprocessing import LabelEncoder

data_train['FareBin'] = pd.qcut(data_train['Fare'], 4)
data_train['AgeBin'] = pd.cut(data_train['Age'].astype(int), 5)
label = LabelEncoder()
data_train['AgeBin'] = label.fit_transform(data_train['AgeBin'])
data_train['FareBin'] = label.fit_transform(data_train['FareBin'])
 PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedFamilySizeIsAloneFareBinAgeBin
0 1 0 3 Braund, Mr. Owen Harris 1 22.000000 1 0 A/5 21171 7.2500 0 S 2 0 0 1
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... 0 38.000000 1 0 PC 17599 71.2833 1 C 2 0 3 2
2 3 1 3 Heikkinen, Miss. Laina 0 26.000000 0 0 STON/O2. 3101282 7.9250 0 S 1 1 1 1
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) 0 35.000000 1 0 113803 53.1000 1 S 2 0 3 2
4 5 0 3 Allen, Mr. William Henry 1 35.000000 0 0 373450 8.0500 0 S 1 1 1 2
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
886 887 0 2 Montvila, Rev. Juozas 1 27.000000 0 0 211536 13.0000 0 S 1 1 1 1
887 888 1 1 Graham, Miss. Margaret Edith 0 19.000000 0 0 112053 30.0000 1 S 1 1 2 1
888 889 0 3 Johnston, Miss. Catherine Helen "Carrie" 0 16.185117 1 2 W./C. 6607 23.4500 0 S 4 0 2 0
889 890 1 1 Behr, Mr. Karl Howell 1 26.000000 0 0 111369 30.0000 1 C 1 1 2 1
890 891 0 3 Dooley, Mr. Patrick 1 32.000000 0 0 370376 7.7500 0 Q 1 1 0 1

 
 
posted @ 2022-01-18 15:20  流白李  阅读(109)  评论(0编辑  收藏  举报