9.3 泰坦尼克号生还预测#

在本章的前面几节内容中,我们分别介绍了三种集成学习算法的基本思想,并且就其中随机森林的原理做了详细介绍。在接下来的这节内容中将以泰坦尼克号生还预测(分类)[4]为例进行实战演示,并且还会介绍相关的数据预处理方法,例如缺失值填充和类型特征转换等。

本次用到的数据集为泰坦尼克号生还预测数据,原始数据集一共包含891个样本和11个特征维度,但是需要注意的是,在实际处理时这11个特征维度不一定都要用到,只选择部分有用的即可。同时,由于部分样本存在某些特征维度出现缺失的状况,因此还需要对其进行填充,完整代码可参见AllBooKCode/Chapter09/C07_titanic.py 文件。

9.3.1 读取数据集#

本次用到的数据集一共包含两个文件,其中一个为训练集,另一个为测试集。下载完成后放在本代码所在目录的data目录中即可。接着需要先读取本地数据,示例代码如下:

1 import pandas as pd
2 def load_data():
3     train = pd.read_csv('data/train.csv',sep=,)
4     test = pd.read_csv('data/test.csv')

在上述代码中,第1行用来导入库pandas,以便读取本地文件。第3行代码表示通过pandas中的read_csv()方法读取.csv文件,它返回的是一个DataFrame格式的数据类型,可以方便地进行各类数据预处理操作。这里值得一提的是,read_csv不仅可以用来读取.csv格式的数据,只要读取的数据满足条件: ①它是一个结构化的文本数据,即m行n列; ②列与列之间有相同的分隔符,例如默认情况下sep=','。这样的数据都可以通过该方法进行读取,不管文件的扩展名是.csv还是.txt,抑或没有后缀。当然,pandas还提供了很多常见数据的读取方法,例如excel、json数据等。

在读取完成后,可以通过如下方式查看数据集的相关信息:

 1 print(train.info())
 2 Data columns (total 12 columns):
 3  #   Column       Non-Null Count  Dtype  
 4 ---  ------       --------------  -----  
 5  0   PassengerId  891 non-null    int64  
 6  1   Survived     891 non-null    int64  
 7  2   Pclass       891 non-null    int64  
 8  3   Name         891 non-null    object 
 9  4   Sex          891 non-null    object 
10  5   Age          714 non-null    float64
11  6   SibSp        891 non-null    int64  
12  7   Parch        891 non-null    int64  
13  8   Ticket       891 non-null    object 
14  9   Fare         891 non-null    float64
15  10  Cabin        204 non-null    object 
16  11  Embarked     889 non-null    object

从上述输出信息可以知道,该数据集一共有11个特征维度(第1列Survived 为标签)和891个样本。同时还可以具体地看到每个特征维度的数据类型及有多少为非空值等信息。

9.3.2 特征选择#

在完成原始数据的载入后,就需要对特征进行选择。对于特征的选择这一步显然是仁者见仁智者见智,可以都用上也可以只选择你认为对最后预测结果有影响的特征。在本示例中,选择的是Pclass、Sex、Age、SibSp、Parch、Fare和Embarked这7个特征维度,其分别表示船舱等级、性别、年龄、乘客在船上兄弟姐妹/配偶的数量、乘客在船上父母/孩子的数量、船票费用和登船港口。当然, Survived这一列特征是作为最终进行预测的类标,即标签值。进一步,对于特征筛选示例代码如下:

1 features = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']
2 x_train = train[features]
3 x_test = test[features]
4 y_train = train['Survived']

在上述代码中,第1行用来定义需要选择的特征,第2~3行用来在训练集和测试集中取对应的特征维度,第4行用来获取训练集中的标签。由于这是比赛中的数据集,所以真实的测试集中并不含有标签。

9.3.3 缺失值填充#

在选择完成特征后下一步就是对其中的缺失值进行填充。从上面的输出结果可以看出,在训练集和测试集中特征Age、Embarked和Fare存在缺失值的情况,并且特征Age和Fare均为浮点型,对于浮点型的缺失值一般可采用该特征维度所有值的平均作为填充,而特征Embarked为类型值,对于类型值的缺失一般可以采用该特征维度出现次数最多的类型值进行填充,因此下面开始分别用这两种方法进行缺失值的补充,示例代码如下:

1 x_train['Age'].fillna(x_train['Age'].mean(), inplace=True) 
2 print(x_train['Embarked'].value_counts())# S 644 C 168  Q 77
3 x_train['Embarked'].fillna('S', inplace=True)
4 x_test['Age'].fillna(x_train['Age'].mean(), inplace=True)
5 x_test['Fare'].fillna(x_train['Fare'].mean(), inplace=True)

在上述代码中,第1行和第4行用来对特征Age以均值进行填充,这里需要注意的是测试集中的缺失值也应该用训练集中的均值进行填充。第2行用来统计输出特征Embarked中各个取值出现的次数,可以发现S出现次数最多(644次)。第3行则用来对特征Embarked的缺失值以S进行填充。

9.3.4 特征值转换#

在进行完上述几个步骤后,数据预处理的最后一步需要对特征进行转换。所谓特征转换就是将其中的非数值型特征,用数值进行代替,例如特征Embarked和Sex,代码如下:

1 x_train.loc[x_train['Sex'] == 'male', 'Sex'] = 0
2 x_train.loc[x_train['Sex'] == 'female', 'Sex'] = 1
3 x_train.loc[x_train['Embarked'] == 'S', 'Embarked'] = 0
4 x_train.loc[x_train['Embarked'] == 'C', 'Embarked'] = 1
5 x_train.loc[x_train['Embarked'] == 'Q', 'Embarked'] = 2

在上述代码中,.loc方法用获取对应行列索引中的值,而类似x_train['Sex'] =='male'则用来得到满足条件的行索引。经过上述步骤后,数据集中的字符特征就被替换成了对应的数值特征。

9.3.5 乘客生还预测#

在完成数据预处理的所有工作后,便可以建立相应的分类模型来对测试集中的乘客生还情况进行预测。下面以随机森林模型为例,示例代码如下:

 1 def random_forest():
 2     x_train, y_train, x_test = load_data()
 3     model = RandomForestClassifier()
 4     paras = {'n_estimators': np.arange(10, 100, 10), 
 5              'criterion': ['gini', 'entropy'], 
 6              'max_depth': np.arange(5, 50, 5)}
 7     gs = GridSearchCV(model, paras, cv=5, verbose=2, n_jobs=2)
 8     gs.fit(x_train, y_train)
 9     y_pre = gs.predict(x_test)
10     print('best score:', gs.best_score_) # 0.827
11     print('best parameters:', gs.best_params_)

由于上述示例代码在9.2节中均有介绍,所以在此不再赘述了。

9.3.6 小结#

在本节中,我们以泰坦尼克号生还预测数据集为例,首先介绍了如何通过pandas来读取结构化的文本数据,然后详细地展示了从数据预处理到模型预测的每个步骤,包括读取数据集、特征选择、缺失值补充、特征转换和模型选择等,最后以随机森林为例,完成了随机森林模型的训练及在测试集上的预测任务。