【机器学习实战2】泰坦尼克号:从数据清洗到特征工程的生存预测指南

【机器学习实战2】泰坦尼克号:从数据清洗到特征工程的生存预测指南
1. 数据清洗从原始数据到可用特征处理泰坦尼克号数据集的第一步永远是数据清洗。我刚开始接触这个项目时发现原始数据存在大量缺失值和异常值。比如Age列有177个缺失值Cabin列更是缺失了687条记录。这就像拿到一本残缺的日记必须先把破损的页面修补好才能读懂故事。对于Age列的缺失值我尝试了多种填充方法。最开始用整体平均值填充但效果不佳。后来发现姓名中的称谓如Mr、Miss与年龄强相关于是改用各称谓组的年龄中位数填充title_mapping {Mr: 30, Miss: 22, Mrs: 35, Master: 5} df[Age] df.groupby(Title)[Age].apply(lambda x: x.fillna(x.median()))Cabin列的处理更有意思。由于缺失率超过77%直接删除会损失大量数据。我的解决方案是提取舱位首字母如C123→C作为新特征缺失值标记为UUnknown。后来发现这个简单操作竟能提升模型效果因为舱位首字母实际上反映了客舱在船上的位置区域。2. 特征工程从姓名中挖掘黄金原始数据中的Name列看似只是字符串但隐藏着重要信息。通过正则表达式提取称谓我发现不同称谓群体的生存率差异显著df[Title] df[Name].str.extract( ([A-Za-z])\., expandFalse)统计结果令人惊讶贵族如Countess生存率高达80%普通男性Mr生存率仅15%儿童Master生存率有60%这促使我创建了称谓分类特征df[Title] df[Title].replace([Lady, Countess], Royalty) df[Title] df[Title].replace([Mlle, Ms], Miss)3. 家庭关系特征工程实战原始数据中的SibSp兄弟姐妹/配偶数和Parch父母/子女数看似简单但组合后能产生强大特征。我创建了三个新特征家庭规模df[FamilySize] df[SibSp] df[Parch] 1是否独自旅行df[IsAlone] (df[FamilySize] 1).astype(int)家庭分组发现4人家庭生存率最高df[FamilyGroup] pd.cut(df[FamilySize], bins[0,1,4,7,11], labels[Solo,Small,Medium,Large])可视化分析显示2-4人的小家庭生存率最高超过60%而独自旅行者和8人以上大家庭生存率不足30%。这反映了灾难中的群体互助效应。4. 票价与舱位的特征组合票价Fare和客舱等级Pclass单独使用时效果一般但组合后能揭示更多信息。我采用了两种处理方式票价分段df[FareBand] pd.qcut(df[Fare], 4, labels[1,2,3,4])票价与舱位比值df[FarePerClass] df[Fare] / df[Pclass]有趣的是三等舱中支付高额票价的乘客生存率明显高于同舱位其他乘客这可能反映了经济实力带来的逃生优势。5. 同票号群体特征挖掘在分析Ticket列时我发现相同票号的乘客往往是一起出行的团体。于是创建了ticket_counts df[Ticket].value_counts() df[TicketGroup] df[Ticket].map(ticket_counts) df[TicketGroupSize] pd.cut(df[TicketGroup], bins[0,1,2,4,20], labels[Solo,Pair,SmallGroup,LargeGroup])这个特征后来被证明非常有效因为大型旅行团成员往往有相互照应生存率比单独乘客高出15-20%。6. 模型验证与特征选择完成特征工程后我使用随机森林进行特征重要性评估from sklearn.ensemble import RandomForestClassifier model RandomForestClassifier(n_estimators100) model.fit(X_train, y_train) features pd.DataFrame({Feature:X_train.columns, Importance:model.feature_importances_}) features.sort_values(Importance, ascendingFalse)结果显示前5位重要特征依次是性别、票价、称谓、年龄和舱位等级。有趣的是我创建的家庭规模特征重要性超过了原始的家庭关系特征。7. 避免过拟合的实用技巧在特征工程过程中我总结出几个避免过拟合的经验对连续变量如年龄、票价优先考虑分段处理而非直接使用原始值新创建的特征要与业务逻辑有合理关联定期检查特征间的相关性删除冗余特征使用交叉验证评估特征效果而不仅看训练集表现比如最初我创建了姓名长度特征虽然训练集上有效果但在交叉验证时表现不稳定最终决定舍弃这个特征。8. 特征工程完整代码示例以下是经过实战检验的特征工程完整代码def feature_engineering(df): # 称谓提取 df[Title] df[Name].str.extract( ([A-Za-z])\., expandFalse) title_mapping {Mr:1,Miss:2,Mrs:3,Master:4,Royalty:5,Officer:6} df[Title] df[Title].replace([Lady,Countess],Royalty) df[Title] df[Title].replace([Mlle,Ms],Miss) df[Title] df[Title].map(title_mapping).fillna(0) # 家庭特征 df[FamilySize] df[SibSp] df[Parch] 1 df[IsAlone] (df[FamilySize] 1).astype(int) # 票价处理 df[Fare] df[Fare].fillna(df[Fare].median()) df[FareBand] pd.qcut(df[Fare], 4, labels[1,2,3,4]) # 年龄处理 age_bins [0,5,12,18,35,60,100] df[AgeBand] pd.cut(df[Age], binsage_bins, labelsFalse) # 舱位处理 df[Deck] df[Cabin].str[0].fillna(U) # 票号分组 ticket_counts df[Ticket].value_counts() df[TicketGroup] df[Ticket].map(ticket_counts) return df这套特征工程方案在Kaggle上取得了0.82的准确率超过了85%的参赛者。记住好的特征工程不在于创造多少新特征而在于每个特征能否真实反映问题的本质。

最新新闻

日新闻

周新闻

月新闻