1. 数据探索与初步分析
第一次拿到泰坦尼克号数据集时,我习惯性地先看数据结构。用pandas的head()快速浏览前几行数据,发现每个乘客有12个特征,包括年龄、性别、舱位等级等。但很快注意到Age列有缺失,Cabin列更是大面积空白——这让我想起实际项目中常遇到的"脏数据"问题。
统计Survived列发现生还率仅38%,说明这是个类别不均衡问题。进一步用groupby分析发现:头等舱乘客生还率62%,而三等舱只有24%;女性生还率74%,男性仅18%。这些数字直观展示了"妇女儿童优先"的救援原则。可视化时我用matplotlib画了堆叠柱状图,不同舱位的生存对比一目了然。
2. 数据清洗实战技巧
处理缺失值时,Age列我尝试了三种方法:均值填充、中位数填充和基于称谓的智能填充。实测发现,从Name提取Mr/Miss/Mrs等称谓后,按称谓分组用中位数填充效果最好。比如"Master"称谓(未成年男性)的年龄中位数是5岁,比整体均值29.7岁更合理。
对于Embarked缺失的两条记录,通过票号查找发现都是头等舱乘客,且票价接近80英镑。查询历史资料发现这个价位乘客多从南安普顿登船,因此填充'S'。Cabin列缺失太多,但首字母代表甲板位置可能有价值,于是提取出Deck特征后再删除原列。
# 智能填充年龄示例 titles = df['Name'].str.extract(' ([A-Za-z]+)\.', expand=False) title_median_age = df.groupby(titles)['Age'].median() df['Age'] = df.apply( lambda x: title_median_age[x['Title']] if pd.isnull(x['Age']) else x['Age'], axis=1 )3. 特征工程深度挖掘
3.1 姓名中的隐藏信息
Name列看似无用,但提取称谓后发现有趣模式:"Dr""Rev"等职业称谓的生还率低于平均值,而"Countess"等高身份称谓生还率更高。我将称谓归纳为6类:贵族、职业人士、成年男性、成年女性、未婚女性、儿童,做成分类特征。
3.2 家庭关系特征
SibSp和Parch原始特征可以衍生出更多信息:
- FamilySize:家庭成员总数(SibSp + Parch + 1)
- IsAlone:是否独自乘船(FamilySize == 1)
- 分箱处理:将家庭规模分为独行、小家庭(2-4人)、大家庭(5人以上)
3.3 舱位与票价特征
Fare票价与Pclass舱位等级高度相关,但相同舱位内票价差异也蕴含信息:
- FarePerPerson:总票价除以家庭人数
- FareBin:将票价分为5个等级
- CabinPremium:根据Cabin首字母判断是否位于高级甲板
4. 特征编码与选择
对于分类特征,测试了三种编码方式:
- LabelEncoder:简单但会引入虚假顺序
- OneHotEncoder:维度爆炸但无顺序假设
- TargetEncoding:用目标变量均值编码,需防范数据泄露
最终方案:
- 有序类别(如Pclass)用LabelEncoder
- 无序类别(如Embarked)用OneHotEncoder
- 高基数特征(如Ticket前缀)用TargetEncoding
# 目标编码示例 from sklearn.preprocessing import TargetEncoder encoder = TargetEncoder() df['Deck_encoded'] = encoder.fit_transform( df['Deck'], df['Survived'] )5. 模型构建与优化
5.1 基线模型选择
先用逻辑回归建立基线,准确率约79%。然后尝试:
- 随机森林:处理非线性关系效果好
- XGBoost:自动特征选择能力强
- SVM:小样本表现稳定
5.2 特征重要性分析
通过随机森林的feature_importance发现:
- 性别是最强预测因子
- 票价和舱位次之
- 自建特征Deck和Title排名靠前
5.3 超参数调优
用GridSearchCV优化随机森林:
param_grid = { 'n_estimators': [100, 200], 'max_depth': [4, 6, None], 'min_samples_split': [2, 5] } grid = GridSearchCV(RandomForestClassifier(), param_grid) grid.fit(X_train, y_train)6. 集成学习提升效果
单模型最好成绩是XGBoost的83.5%。尝试三种集成方法:
- VotingClassifier:结合逻辑回归、随机森林、SVM
- Stacking:用XGBoost作为元模型
- Bagging:对随机森林做二次采样
最终Stacking方案将准确率提升到85.2%,关键代码如下:
from sklearn.ensemble import StackingClassifier base_models = [ ('rf', RandomForestClassifier(n_estimators=200)), ('xgb', XGBClassifier(max_depth=3)) ] stack = StackingClassifier( estimators=base_models, final_estimator=LogisticRegression() )7. 避免常见陷阱
在这个项目中我踩过几个坑:
- 数据泄露:在填充Age缺失值时,错误地在全数据集计算均值
- 过拟合:早期版本在训练集达到92%但测试集只有80%
- 评估偏差:用accuracy评价不均衡数据,改用F1-score
解决方案:
- 严格区分训练/测试集
- 早停法防止过拟合
- 使用交叉验证
- 关注混淆矩阵而非单一指标
处理泰坦尼克号数据集就像在考古,每个特征都可能隐藏着1912年的社会密码。当我发现头等舱儿童的生还率比三等舱成人高出6倍时,突然理解了特征工程的魅力——它让数据讲出了那个夜晚的真实故事。