Python机器学习及实践——实战篇:泰坦尼克号罹难乘客预测
项目背景:
泰坦尼克号是一艘奥林匹克级邮轮,于194月处女航时撞上冰山后沉没。泰坦尼克号由位于爱尔兰岛贝尔法斯特的哈兰德与沃尔夫造船厂兴建,是当时最大的客运轮船。在它的处女航中,泰坦尼克号从英国南安普敦出发,途经法国瑟堡-奥克特维尔以及爱尔兰昆士敦,计划中的目的地为美国纽约。194月14日,船上时间夜里11时40分,泰坦尼克号撞上冰山;4月15日凌晨2时20分,船裂成两半后沉入大西洋。泰坦尼克号海难为和平时期死伤人数最惨重的海难之一。船上1500多人丧生。
提出问题
预测泰坦尼克号乘客的生存情况
数据集
下载test.csv和train.csv。
说明:test.csv是训练数据集;train.csv是测试数据集。
数据理解
先读取数据集。
import pandas as pd# 读取训练集和测试集train = pd.read_csv('./train.csv')test = pd.read_csv('./test.csv')# 输出数据集的基本信息print(train.info())print(test.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
Pclass891 non-null int64
Name891 non-null object
Sex891 non-null object
Age714 non-null float64
SibSp891 non-null int64
Parch891 non-null int64
Ticket891 non-null object
Fare891 non-null float64
Cabin204 non-null object
Embarked 889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB
None
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 418 entries, 0 to 417
Data columns (total 11 columns):
PassengerId 418 non-null int64
Pclass418 non-null int64
Name418 non-null object
Sex418 non-null object
Age332 non-null float64
SibSp418 non-null int64
Parch418 non-null int64
Ticket418 non-null object
Fare417 non-null float64
Cabin91 non-null object
Embarked 418 non-null object
dtypes: float64(2), int64(4), object(5)
memory usage: 36.0+ KB
None
训练数据集有12个字段,891条数据,训练集比测试数据集多一个Survived字段。测试数据集有11个字段,418条数据。
训练数据集的Age,Cabin,Embarked有数据缺失。测试数据集的Age,Fare,Cabin有数据缺失。
字段说明如下表:
数据处理
Fare的缺失值处理
X_test['Fare'].fillna(X_test['Fare'].mean(), inplace=True)
Age的缺失值处理
# 而对于Age这种数据类型的特征,使用求平均值或者中位数来填充缺失值X_train['Age'].fillna(X_train['Age'].mean(), inplace=True)X_test['Age'].fillna(X_test['Age'].mean(), inplace=True)
Embarked的缺失值处理
# 对于Embarded这种类型的特征,使用出现频率最高的特征值来填充,这也是相对可以减少引入误差的一种填充方法X_train['Embarked'].fillna('S', inplace=True)X_test['Embarked'].fillna('S', inplace=True)
完整代码
#!/usr/bin/env python# -*- coding: utf-8 -*-"""@File : Titanic.py@Author: Xinzhe.Pang@Date : /7/27 16:02@Desc : """import pandas as pd# 采用DictVectorizer对特征向量化from sklearn.feature_extraction import DictVectorizer# 导入RandomForestClassifierfrom sklearn.ensemble import RandomForestClassifier# 从xgboost导入XGBClassifier用于处理分类预测问题from xgboost import XGBClassifier# 导入交叉验证包from sklearn.model_selection import cross_val_score# 使用并行网格搜索的方式寻找更好的超参数组合,以期待进一步提高XGBClassifier的预测性能from sklearn.model_selection import GridSearchCV# 读取训练集和测试集train = pd.read_csv('./train.csv')test = pd.read_csv('./test.csv')# 输出数据集的基本信息print(train.info())print(test.info())# 人工选取对预测有效的特征selected_features = ['Pclass', 'Sex', 'Age', 'Embarked', 'SibSp', 'Parch', 'Fare']X_train = train[selected_features]X_test = test[selected_features]y_train = train['Survived']# 通过对数据的观察,得知Embarked特征存在缺失值print(X_train['Embarked'].value_counts())print(X_test['Embarked'].value_counts())X_test['Fare'].fillna(X_test['Fare'].mean(), inplace=True)# 对于Embarded这种类型的特征,使用出现频率最高的特征值来填充,这也是相对可以减少引入误差的一种填充方法X_train['Embarked'].fillna('S', inplace=True)X_test['Embarked'].fillna('S', inplace=True)# 而对于Age这种数据类型的特征,使用求平均值或者中位数来填充缺失值X_train['Age'].fillna(X_train['Age'].mean(), inplace=True)X_test['Age'].fillna(X_test['Age'].mean(), inplace=True)# 重新检查处理后的数据集print(X_train.info())print(X_test.info())if __name__ == '__main__':# 特征向量化dict_vec = DictVectorizer(sparse=False)X_train = dict_vec.fit_transform(X_train.to_dict(orient='record'))print(dict_vec.feature_names_)X_test = dict_vec.transform(X_test.to_dict(orient='record'))# 使用默认配置初始化RandomForestClassifierrfc = RandomForestClassifier()# 使用默认配置初始化XGBClassifier()xgbc = XGBClassifier()# 使用5折交叉验证的方法在训练集上分布对默认配置的RandomForestClassifier以及XGBClassifier进行性能评估,并获得平均分类准确性的得分cross_val_score(rfc, X_train, y_train, cv=5).mean()cross_val_score(xgbc, X_train, y_train, cv=5).mean()# 使用默认配置的RandomForestClassifier进行预测操作rfc.fit(X_train, y_train)rfc_y_pred = rfc.predict(X_test)rfc_submission = pd.DataFrame({'PassengerId': test['PassengerId'], 'Survived': rfc_y_pred})# 将默认配置的RFC对预测数据的预测结果存储到文件rfc_submission.csv中rfc_submission.to_csv("./rfc_submission.csv", index=False)# 使用默认配置的XGBClassifier进行预测操作xgbc.fit(X_train, y_train)xgbc_y_pred = xgbc.predict(X_test)# 将默认配置的XGBClassifier对测试数据的预测结果存储文件xgbc_submission.csv中xgbc_submission = pd.DataFrame({'PassengerId': test['PassengerId'], 'Survived': xgbc_y_pred})xgbc_submission.to_csv('./xgbc_submission.csv', index=False)params = {'max_depth': range(2, 7), 'n_estimators': range(100, 1100, 200),'learning_rate': [0.05, 0.1, 0.25, 0.5, 1.0]}xgbc_best = XGBClassifier()gs = GridSearchCV(xgbc_best, params, n_jobs=-1, cv=5, verbose=1)gs.fit(X_train, y_train)# 查验优化之后的XGBClassifier的超参数配置以及交叉验证的准确性print(gs.best_score_)print(gs.best_params_)# 使用经过优化的超参数配置的XGBClassifier对测试数据的预测结果存储在文件xgbc_best_submission.csv中xgbc_best_y_pred = gs.predict(X_test)xgbc_best_submission = pd.DataFrame({'PassengerId': test['PassengerId'], 'Survived': xgbc_best_y_pred})xgbc_best_submission.to_csv('./xgbc_best_submission.csv', index=False)