从数据清洗到模型优化:泰坦尼克号生存预测的完整技术栈解析
1. 项目背景与数据理解
泰坦尼克号数据集是机器学习领域最经典的入门案例之一。1912年这艘"永不沉没"的豪华邮轮在首航中撞上冰山,导致1502人遇难。但分析发现,生存并非完全随机——妇女、儿童和头等舱乘客的生还率明显更高。这正是机器学习可以发挥作用的典型场景:通过乘客特征预测生存概率。
原始数据集包含以下关键字段:
| 字段名 | 类型 | 描述 | 缺失比例 |
|---|---|---|---|
| Age | 数值 | 乘客年龄 | 约20% |
| Fare | 数值 | 船票价格 | 0.2% |
| Cabin | 字符串 | 客舱编号 | 77.5% |
| Embarked | 分类 | 登船港口 | 0.15% |
数据探索的核心发现:
- 女性生存率(74%)显著高于男性(19%)
- 头等舱生存率(63%)是三等舱(24%)的2.6倍
- 5岁以下儿童生存率超过60%
- 南安普顿登船的乘客数量最多但生存率最低
# 基础数据探索代码示例 import pandas as pd train = pd.read_csv('train.csv') print(f"女性生存率: {train[train.Sex=='female'].Survived.mean():.0%}") print(f"头等舱生存率: {train[train.Pclass==1].Survived.mean():.0%}")2. 特征工程的艺术
2.1 缺失值处理策略
不同特征的缺失需要差异化处理:
- 年龄:采用基于称呼(Mr/Miss等)的分组中位数填充
- 船舱:首字母提取后标记缺失为'U'
- 登船港口:用众数'S'填充
# 高级年龄填充方法 titles = train.Name.str.extract(' ([A-Za-z]+)\.', expand=False) age_median = train.groupby(titles)['Age'].median() train['Age'] = train.apply( lambda x: age_median[x.Name.split(',')[1].split('.')[0].strip()] if pd.isnull(x.Age) else x.Age, axis=1)2.2 特征创造
从原始数据挖掘深层信息:
- 姓名:提取称呼(Title)并归类为6种社会等级
- 家庭规模:SibSp + Parch + 1
- 票价分组:按分位数离散化为4个等级
称呼映射表示例:
title_mapping = { "Capt": "Officer", "Col": "Officer", "Major": "Officer", "Dr": "Officer", "Rev": "Officer", "Dona": "Royalty", "Countess": "Royalty", "Mme": "Mrs", "Mlle": "Miss", "Ms": "Mrs" }2.3 特征编码技巧
- 有序分类(如客舱等级):直接映射为数值
- 无序分类(如登船港口):使用One-Hot编码
- 高基数特征(如船舱):取首字母后One-Hot
# 优雅的One-Hot编码实现 embarked_dummies = pd.get_dummies(train['Embarked'], prefix='Embarked', drop_first=True) train = pd.concat([train, embarked_dummies], axis=1)3. 模型构建与优化
3.1 基础模型对比
我们测试了7种常见算法的表现:
| 模型 | 准确率 | 训练时间 | 适合场景 |
|---|---|---|---|
| 逻辑回归 | 82.1% | 0.5s | 线性可分数据 |
| 随机森林 | 81.2% | 3.2s | 特征交互强 |
| XGBoost | 83.6% | 1.8s | 结构化数据 |
| SVM | 83.2% | 8.7s | 小样本数据 |
from sklearn.ensemble import RandomForestClassifier rf = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=1) rf.fit(X_train, y_train) print(f"RF准确率: {rf.score(X_test, y_test):.1%}")3.2 超参数调优
使用GridSearchCV优化随机森林:
param_grid = { 'n_estimators': [50, 100, 200], 'max_depth': [3, 5, 7], 'min_samples_split': [2, 5] } grid = GridSearchCV(RandomForestClassifier(), param_grid, cv=5) grid.fit(X_train, y_train) print(f"最佳参数: {grid.best_params_}")3.3 集成方法提升
- Stacking:组合逻辑回归、随机森林和XGBoost
- 特征重要性:识别最有预测力的特征
随机森林特征重要性图示:
Age ************* Fare ********** Sex ******* Pclass **** FamilySize *** ...4. 实战技巧与避坑指南
4.1 常见错误
- 直接删除缺失值导致样本偏差
- 忽视特征间的多重共线性
- 在测试集上做特征工程导致数据泄露
4.2 性能提升技巧
- 使用交叉验证评估模型稳定性
- 添加乘客分组统计特征
- 尝试不同的分箱策略
# 高级特征创造:家庭生存率 train['Family_Survival'] = 0.5 for _, group in train.groupby(['LastName', 'Fare']): if len(group) > 1: for idx, row in group.iterrows(): train.loc[idx, 'Family_Survival'] = group['Survived'].mean()4.3 比赛进阶策略
- 特征组合:客舱等级×性别
- 模型融合:投票集成+加权平均
- 伪标签:用测试集预测结果反哺训练
在Kaggle比赛中,这些技巧帮助我的模型排名进入前10%。实践中发现,将乘客的社交关系网络纳入考虑能进一步提升预测准确率约2-3个百分点。