从0.75到0.784:Kaggle Titanic生存预测中的特征工程与模型优化实践
文章为我的探索学习过程有不足的地方还请批评改正感谢1.背景和目标本项目基于Kaggle Titanic数据集目标是预测乘客在灾难中的生存情况。项目的核心在于- 构建完整的机器学习流程EDA → 特征工程 → 模型训练- 通过实验验证特征设计的有效性- 分析特征之间的关系成果最终达到 0.78468 分。2.数据集2.1数据总览比赛提供了两个数据集一个训练集和一个测试集训练集train.csv包含了891名乘客的特征及其存活情况测试集test.csv包含了418名乘客的特征没有存活标签用于最终预测和提交。数据集中共有12个字段其中PassengerId乘客编号Survived是否存活0遇难, 1生还Pclass客舱等级1头等舱, 2二等舱, 3三等舱Name姓名Sex性别Age年龄SibSp同行的兄弟姐妹/配偶人数Parch同行的父母/子女人数Ticket船票编号Fare票价Cabin船舱号Embarked登船港口S南安普顿, C瑟堡, Q皇后镇使用train.head(10)预览前10行数据可以看到数据中存在缺失值并且Sex、Name字段是文本需要转换为数值才能让模型处理。紧接着再用train.isnull().sum()和test.isnull().sum()来分别查看训练集和测试集哪些字段有缺失值及其缺失值的数量。训练集缺失值情况测试集缺失值情况2.2可视化分析接下来对数据进行可视化分析首先是存活人数统计0代表遇难1代表存活在此次灾害中数据集中一共有342人存活549人遇难。下面分析各特征与存活率之间的关系Sex与Survived之间的柱状图如下从2-2中可以看出来女性存活率为74.2%男性存活率为18.9%性别间的存活率差距高达55%在救生艇数量有限的情况下女性拥有较高的救援优先权。Sex是预测存活的重要特征之一需要将其作为模型的判断依据。泰坦尼克号共有三个客舱等级其中1代表头等舱2代表二等舱3代表三等舱。客舱等级与存活率关系如下从上图可以看出头等舱存活率为63%二等舱存活率为47.3%三等舱存活率为24.2%。客舱等级与存活率呈现明显的负相关等级越低存活越难。这反映了当时社会阶层的残酷现实头等舱位于上层甲板离救生艇最近三等舱乘客住在底层逃生路径遥远可能还会因为混乱局面而被限制进入头等舱。Pclass是一个极强的特征需要将其纳入模型的判断依据中。泰坦尼克号上各年龄段人群数量及年龄与存活率之间的关系如下图所示从上面两个图中可以看出泰坦尼克号上20-40岁的人群占比居多其次是低龄儿童从存活率看出儿童具有绝对的生存优势生还者的年龄下限很低。同时可以看出有一些离群的圆圈分布在年龄较高的地方说明年长者逃生难度更大一旦遇到危险很容易成为语言群体中的极端案例。无论存活与否大部分乘客年龄都集中分布在20-40岁之间这部分人能够存活更大程度上取决于他们手中的船票和性别而非年龄本身。对于Age这个特征后续数据清理应处理好缺失值考虑将年龄段分段加工。泰坦尼克号总共有三个登船港口S南安普顿, C瑟堡, Q皇后镇。登船港口与存活率之间的关系如下图所示可以看出从瑟堡港口登船的乘客存活率最高皇后镇和南安普顿其次这其实是和乘客的舱位分布有关瑟堡港口登船的的乘客中头等舱比例较高而皇后镇港口登船的乘客多为三等舱所以这个特征后隐藏的还是社会差异Embarked是一个辅助性特征能够提供额外信息但是不如Pclass直接处理好缺失值后仍可以加入到模型中。最后是特征相关性热力图如下图所示从上面可以看出与存活率最相关的特征有Pclass与FarePclass与Survived的相关系数为-0.34呈现中度负相关这意味着客舱等级越低存活率越低其次是Fare与Survived的相关系数为0.26呈现中度正相关票价越高存活概率越大。Sex虽然经过上述分析确认是强特征但是尚未对原始数据进行编码未纳入相关性计算。特征之间的内部关联Pclass与Fare之间相关系数高达-0.55这符合常识头等舱票价远高于三等舱。SibSp与Parch之间相关系数为0.41说明携带配偶的乘客往往也带有子女。这两个特征可以组合成FamilySize以减少冗余。弱相关特征中Age与Survived的相关系数仅为-0.08说明年龄与存活率间不存在明显的线性关系。但这并不意味着年龄不重要从前面的箱线图分析可知年龄的影响是“两极化”的这种非线性模式是无法被相关系数捕捉的。总结来说Pclass和Fare是核心预测特征但它们之间存在较强的共线性在建模时需要留意或者通过特征组合来缓解。SibSp和Parch单独与存活的相关性很弱但将两者相加并 1 构造出FamilySize后可能挖掘出家庭规模的 U 型或倒 U 型影响。基于上述观察后确定后续策略对Age进行合理填充Cabin不作为核心特征构造新特征探索家庭关系对生存的影响构造与社会身份相关的特征。3.数据预处理3.1缺失值处理对于Age这一特征缺失了177条占总数近20%直接删除的话可能导致大量样本浪费所以选择中位数而不采取平均数填充因为年龄分布存在极端值如80岁以上的老人这些离群值会导致均值受到离群点影响中位数对离群值不敏感可以更稳健的反映乘客的年龄。注意测试集的年龄填充必须使用训练集的中位数而非测试集本身的中位数。Cabin的缺失值高达687占比77.1%对于这类缺失值很严重的特征不管采用哪种填充方式都相当于编造了大部分信息填充的话反而会引入大量噪声拉低模型的性能所以我选择将这一列直接删除。Embarked特征仅缺失2条占比较低对数据整体影响不大因为Embarked是分类变量所以我选择直接用众数填充。测试集的缺失值处理同训练集但注意需要用训练集的数据。3.2特征编码观察数据集可以看到Sex和Embarked这两个特征为文本数据接下来分别对这两个特征进行编码处理。Sex特征编码Embarked特征编码数据集总览4.特征工程此部分具体分数迭代情况请查看5.5分数迭代记录4.1Baseline模型初始模型使用以下特征Pclass, Sex, Age, SibSp, Parch, Fare, Embarked使用RandomForest默认参数。Baseline分数0.758374.2加入FamilySize将SibSp和Parch这两个特征合成一个更直观的特征FamilySize这样可以更好的反应乘客的家庭关系FamilySize1独行乘客可能更容易在混乱中逃生也可能因为无人协助而遇难FamilySize2-4人小家庭可能有部分人生还FamilySize4大家庭紧急情况下互相寻找等待可能会降低整体生还率。做了上述代码进行提交后发现从第一版的0.75837降低为了0.74641模型性能出现下降。后续排查后发现我的特征冗余了已经有的特征SibSp和Parch和新增特征FamilySize存在强相关性模型可能会混淆或者过拟合另一个方面就是FamilySize中1的生存率是低2-4生存率高5生存率低。关系是中间高两边低呈非线性关系。模型难以直接学习家庭规模与生存率之间的非线性关系导致学习效果差所以我设计了一个分箱函数把家庭人数切成三个区间并且删除了冗余特征。修改代码如下修改后再次提交分数变成了0.76794较上次分数提升了。4.3Title 提取观察数据集发现每个乘客前都有一个头衔Name头衔背后同时隐含了性别、年龄、婚姻状态以及社会地位这些信息。例如Mr指成年男性Mrs已婚女性通常有丈夫同行Miss婚女性可能较年轻Master未成年男孩年龄小。把这些信息提取出来模型就会多一个高密度的复合特征。我使用正则表达式从’Name’中提取头衔。提取完成后我用 value_counts() 检查了头衔分布。除了常见的 Mr、Mrs、Miss、Master 外还有一些稀有头衔如 Dr、Rev、Col等每种只有个位数样本。对于这些稀有头衔我采用合并策略——将它们统一归为“其他”类编码为0。进行完上述两种操作提交后分数下降了从0.76794降到了0.76076。这让我发现可能把剩下的稀有头衔全部编码为0会忽略重要的信息因为部分稀有头衔可能隐含更高的社会地位因此简单归为同一类别可能导致信息损失高社会地位往往与高存活率相关。所以下面我尝试对Title进行分组而不是直接填0。因为Title涵盖有Sex和Age的信息所以接下来我还做了一组对照实验看看Title是否能替代Sex。直接进行Title分组后我首先保持特征Sex发现分数从0.76076下降到了0.75837。然后去掉Sex之后发现分数又回到了0.76076。实验结果表明Title特征在一定程度上能够替代Sex特征中的部分信息并且可以让模型学习的更好。接着我尝试了更细致的社会身份划分比如区分专业人士和贵族但发现分数没有任何变化但是我也暂且保留了这个Title分组。除了改变Title分组之外我对Title的提取方式进行了优化刚开始的时候我使用正则表达式提取Title下面我用split方法对Title重新提取提交后分数上升到0.76287说明优化Title提取方式对模型学习有提升作用。5.模型训练和迭代5.1模型选择在模型选择上我选择随机森林有以下两点原因一是随机森林对异常值和缺失值鲁棒不会因为个别样本的异常而剧烈波动二是存活与否并非和年龄、票价等特征呈简单线性关系树模型天然能捕捉这种非线性模式。5.2模型调参与优化初始基线模型我使用默认参数训练了一个基线模型n_estimators100100 棵决策树在速度和稳定性之间取得平衡。其他参数均使用 sklearn 默认值。调参优化在基线模型的基础上我进行了两个方向的调参首先是将树的数量从100增加到200增加树的数量可以降低方差使投票效果更稳定。第二个是限制每棵树的最大深度为5防止模型记忆训练数据中的噪声提升泛化能力第三个是固定随机种子为42确保每次运行结果完全一致便于对比实验结果。调参后的效果交叉验证平均得分0.816Public Score0.784685.3交叉验证为了更客观的评估模型的性能我引入了5折交叉验证平均 81.6% 的准确率说明上述两个特征工程是有效的。五折得分波动极小最低 0.804最高 0.826差距仅 2.2%证明模型对数据的不同划分方式不敏感泛化能力良好。5.4模型局限性虽然随机森林能够较好的处理非线性关系但当前模型仍然存在一些局限性特征工程主要依赖人工经验缺少自动化特征搜索当前实验主要是基于单模型没有尝试模型融合Titanic数据集规模小模型结果容易受到数据划分影响。5.5分数迭代记录版本改动内容Public Score变化V1Baseline0.75837基础分数V2加入 FamilySize0.74641分数降低V3修改FamilySize0.76794分数升高V4加入Title0.76076分数降低V5修改TitleTitle分组保留Sex0.75837分数降低V6不保留Sex0.76076分数升高V7再次修改Title细致分组0.76076分数不变V8改变Title提取方式0.76287分数升高V9改变模型0.78468分数升高6.总结与反思以下是我收获的几个点第一新增特征并不一定能提升性能第二是特征之间可能存在共线性某些关系可能是非线性的交叉验证能够更稳定的评估模型的泛化性能。