news 2026/10/22 3:23:26

泰坦尼克号生还预测:从数据清洗到特征工程的实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
泰坦尼克号生还预测:从数据清洗到特征工程的实战指南

1. 为什么叫“边境的悍匪”

1.1 一个看着简单、实际很不讲理的题目

“泰坦尼克号生还预测”大概是所有机器学习初学者第一个听到的比赛名。训练集不到900行,字段也就十来列,连图片、文本、时序这些复杂数据都没有,怎么看都像是个拿来练手的Hello World。但真动手做你就会发现,这个题就像蹲在应用机器学习边界线上的一股悍匪:外表粗犷、路径险恶,凡是带着“跑个模型就能交差”的心态来的人,基本都要在这里挨一顿毒打。

我说这话不是吓唬新手。当年我第一次做这个题,上来就取性别、年龄、票价三个字段丢进逻辑回归,自我感觉良好,结果本地准确率连0.78都不到,提交到榜上排名被一堆0.80+的压着。后来我才慢慢想明白,这道题真正考的不是你会不会用某个模型,而是你有没有把数据当成一个需要破译的系统,而不是一行行光秃秃的数字。

悍匪的凶残之处在于四个字:藏得深。表面上每个字段都一目了然,但年龄有缺失、船舱有大量缺失、票号看起来毫无规律,名字里却藏着身份信息。你要是只用现成字段硬跑,模型虽然也能出分,但永远卡在一个平庸的位置。等到你把缺失值、衍生特征、交叉验证这些手段都用上,才发现原来这个题的题库里早就埋好了下一关的钥匙。

1.2 从这个题里你能真正带走什么

这个题适合谁来做?我认为最适合两类人:一类是刚学会Pandas和Sklearn基础、想体验完整竞赛流程的人;另一类是已经跑过几个Demo、但从未认真评估过自己模型的人。对前者,它能让你走一遍“读数据、画图、清洗、建模、提交”的完整闭环;对后者,它能把你的自满情绪按在地上摩擦。

你以为你在学“预测生还”,其实你在学三件事:

  • 如何处理真实数据里的缺失与噪声,而不是用现成的干净数据集糊弄自己。
  • 如何构造特征,让人肉眼能看出的模式变成模型能计算的数值。
  • 如何用交叉验证说服自己,而不是被一波测试集分数冲昏头。

这三件事,放到任何一个工业界的建模项目里都是基本功。泰坦尼克号只是恰好用一个有趣的历史背景把它们串了起来。别把它当比赛,把它当成一次“从数据到决策”的完整演练,你才不会空手而归。

2. 动手之前先梳理比赛规则和指标

2.1 这次到底在预测什么

泰坦尼克号这个比赛,目标非常直接:给出一份测试集里每个人是否生还的预测,生还标为1,死亡标为0。训练集有891条乘客数据,测试集有418条。你的任务就是训练集里学出规律,再对测试集乘客输出一个两列提交文件:PassengerId和Survived。

听起来简单,但有个隐藏前提:历史和规则。泰坦尼克号沉没时,救生艇数量不足,船员遵循了“妇女儿童优先”的疏散规则。这导致幸存模式不是均匀随机的,而是高度偏向特定人群。所以数据里那些看似无关的性别、年龄、船舱等级,其实都是当年救生艇分配规则留下的记录。

理解这一点对建模至关重要。纯粹的数据竞赛可以靠暴力调参刷分,但泰坦尼克最能出分的模型,几乎都是因为特征里还原了“谁先上救生艇”这个决策逻辑。性别字段就是最典型的例子:船上女性生还比例远高于男性,任何合理的模型都应该把Sex作为最重要的变量之一。

2.2 评估指标里有个容易让人翻车的细节

这个比赛用的评估指标是Accuracy,也就是预测正确的比例。先别急着高兴,Accuracy在类别不平衡时是很阴险的。泰坦尼克数据里,生还人数比死亡人数少一些,整体大概四六开。如果你无脑预测“全员死亡”,也能拿到约60%的准确率。也就是说,准确率低于0.62的模型,还不如一个猜谜机器人。

所以评估模型时不能只看总准确率,我会同时看三样东西:混淆矩阵、精确率、召回率。尤其是混淆矩阵,它能告诉你模型是把“死亡者猜对了”还是“生还者猜对了”。在泰坦尼克这种题目里,生还者识别得准不准确,往往反映了你有没有真的抓到特征规律,而不只是把多数类蒙对了。

另外,Kaggle排行榜上的公榜分数来自你提交到测试集的预测。但训练集和测试集不是同一个样本,线上分数和本地交叉验证分数之间会有波动。绝对不要为了刷公榜分数去反复调整个别样本的预测,那是自欺欺人。正确的做法是建立可靠的本地交叉验证流程,让它成为你判断模型好坏的唯一标准。

3. 把训练数据翻个底朝天:探索性数据分析

3.1 先看字段,再谈建模

拿到的原始数据常见字段包括:PassengerId、Survived、Pclass、Name、Sex、Age、SibSp、Parch、Ticket、Fare、Cabin、Embarked。Survived是只有训练集才有的标签字段,测试集没有。剩下的每一个字段都在描述一个人的身份或行程信息。

第一件事是把这些字段分类:

  • 数值连续型:Age、Fare。
  • 数值离散型:Pclass、SibSp、Parch、Survived。
  • 类别型:Sex、Embarked、Cabin、Ticket、Name。

一眼就能看出问题:Name这种字符串不可能直接进模型,Cabin和Ticket的格式也很乱,Age还有不少缺失。先把这些字段摊在桌面上,你才能规划哪些需要清洗、哪些能挖出衍生信息。

这里我习惯用.info()快速体检:

import pandas as pd train = pd.read_csv('train.csv') test = pd.read_csv('test.csv') print(train.info()) print(train.isnull().sum())

打印结果里最扎眼的就是Age约缺177个、Cabin约缺687个、Embarked缺2个。Cabin缺失这么多,很多初学者直接选择删除,这其实丢掉了一大块信息。有没有救生艇编号的人,本来就可能意味着不同的身份和生存条件。

3.2 画图看关系,别用肉眼硬猜

探索数据最忌讳只盯数值表格。我一般会先画几个箱线图和柱状图,看每个变量与Survived之间的关系。最经典的结论是:女性的生还率明显高于男性;头等舱的生还率高于三等舱;儿童生还率相对较高,而老年人生还率偏低。

别小看这几条结论。它们直接决定你后面特征工程的方向。你会发现,能让你从0.75提升到0.80的,不是换了个更强的模型,而是把“性别与船舱等级的组合”这个交互信号喂进了模型。比如女性且头等舱的乘客,生还概率会进一步拉高;男性且三等舱的乘客,生还概率近乎惨淡。

画图工具我一般直接用Matplotlib和Seaborn:

import seaborn as sns import matplotlib.pyplot as plt sns.barplot(data=train, x='Sex', y='Survived') plt.show()

看到这张图你就会明白,为什么Sex会是建模第一功臣。但EDA不是只看单变量,还要看多变量交叉。用Pclass和Sex组合的透视表看看生还率,也能发现很多单看一列时发现不了的规律。这一步做得越细,特征工程就越有谱。

4. 特征工程:把肉眼看到的规律变成模型能懂的东西

4.1 缺失值处理:最不能偷懒的一步

泰坦尼克题目里,Age缺失值处理是第一个分水岭。常见做法是直接填中位数或均值,简单但粗鲁。更好的做法是按Pclass、Sex、Title分组后再填充,因为不同身份的人年龄分布差异很大。我用的方法通常是:

  • 先从Name里提取Title字段,比如Mr、Mrs、Miss、Master。
  • 再把Title和Pclass结合,对每个分组计算Age中位数。
  • 用分组中位数去填充该组内的缺失年龄。

这么做比全局填充更接近真实分布,对后续模型收益明显。有人可能会问,是不是直接用模型预测缺失年龄更好?可以是可以,但要小心不要引入额外噪声。在泰坦尼克这种小数据量场景里,我倾向于分组填充加一个“Age是否缺失”的标识特征,让模型自己去判断。

Cabin的处理思路不太一样。它缺失太严重,直接填值没什么意义。我更常做的是构造一个“是否有Cabin记录”的二值特征,因为从表现来看,有Cabin记录的人与没有Cabin记录的人,生存模式有明显差异。这就是从残缺数据里挖出的有效信号。

Ticket字段也是一种看似无用的文本。但如果把Ticket前缀拆出来,比如“PC”开头、“CA”开头,你会发现某些前缀对应了不同的舱区和购票渠道,对未来存活率也有轻微影响。我做的时候会把前几位字母提取出来,统一成几大类,再当类别特征编码。

4.2 衍生特征:让模型看到隐藏信息

单一字段能提供的信息有限,但组合之后往往威力惊人。我最常用的三个衍生特征:

  • FamilySize = SibSp + Parch + 1。一个人出行和带着全家人出行,行动逻辑完全不同。想想就知道,独自一人时逃生更灵活,拖家带口时决策会更复杂。这个特征提出来后,可以再划分成“Solo / Small / Large”三档,转成类别特征效果更直观。

  • Title从姓名里提取身份称谓。这个特征浓缩了年龄、性别、社会地位甚至婚姻状态,别看只是字符串里截几个字母,信息量极大,对缺失年龄的辅助填充也很有价值。

  • Fare分箱。Fare是连续数值,但票价和船舱等级、位置强相关。我会用分位数的形式把票价切成几个区段,或直接取对数压缩幅度,避免高端票价把模型带偏。

还有一个容易被忽略的组合特征:Pclass和Sex的交叉。比如“Female + Pclass 1”可以编码成一个新特征,因为这类乘客的生还率极高。本质上,这是在帮模型建立交互项,而不是只把字段平铺给它。做这步时不要贪多,每加一个特征之前都问问自己,它背后有没有业务逻辑支撑,没有逻辑的特征只会增加过拟合风险。

4.3 哑变量编码的细节

类别特征不能直接喂给线性模型,常规做法是转为哑变量。Pandas的get_dummies很方便,但要注意几点:

  • 训练集和测试集必须用相同的列结构,防止一边多出一列、另一边没有。
  • 对高基数类别,考虑合并稀有类别,避免哑变量矩阵过于稀疏。
  • 数值编码要区别对待:Pclass虽然写成1、2、3,但它是有序类别,可以用作数值特征,也可以做哑变量,两种方式都试一下,以验证结果为准。

我一般先用pd.get_dummies(train, columns=['Sex', 'Embarked', 'Pclass'])生成基础版本,再手动合并衍生特征,最后统一对齐训练集和测试集的列集合。

5. 建模与验证:不要一上来就调参

5.1 先跑一个正经的基线模型

很多人一上来就调到随机森林或XGBoost,调了半天参数发现分数波动很大。我的习惯是先跑一个逻辑回归,把所有基础特征喂进去,得到一个可以解释的基线分数。逻辑回归的优势是透明,你能看到每个特征的系数,判断哪些信息被模型真正用上了。

这个阶段的目标不是拿高分,而是建立一条完整的流水线:从原始数据到特征矩阵,再到模型预测,最后输出提交文件。只要这条流水线通了,后面换模型就是改三行代码的事。

from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split X_train, X_val, y_train, y_val = train_test_split( X, y, test_size=0.2, random_state=42 ) model = LogisticRegression(max_iter=1000) model.fit(X_train, y_train) print(model.score(X_val, y_val))

如果基线逻辑回归能到0.78左右,说明特征工程没有白做。如果连0.75都不到,先回头检查缺失值填充和编码方式,不要急着换模型。

5.2 交叉验证才是市侩大佬的底牌

固定划分训练集和验证集有一个隐患:你可能会在某个随机划分上运气好或运气差。泰坦尼克数据量小,随机性影响很大。我改用5折交叉验证之后,发现同一模型在5组不同划分下,分数能波到0.75到0.81之间。

交叉验证的目的不是让你挑出最高分的那一折,而是把5折分数的均值和标准差都看明白。均值代表真实水平,标准差代表稳定性。一个均值0.78、标准差0.01的模型,比一个均值0.80、标准差0.03的模型更值得信任。

from sklearn.model_selection import cross_val_score cv_scores = cross_val_score(model, X, y, cv=5, scoring='accuracy') print(cv_scores.mean(), cv_scores.std())

在这个基础上再去尝试随机森林、梯度提升树,你会发现它们的优势更明显。但这些树模型也需要小心的预处理和参数约束。别让单棵树的深度太大,别让叶子节点太少,防止模型把训练集里某些生还率特异的个案背下来,一到测试集就露馅。

5.3 从单个模型到组合模型

树模型在新样本上容易不稳定,所以我会考虑两个方向的改进:一是调参约束模型的复杂度,二是做模型融合。泰坦尼克最常见的融合方式是逻辑回归、随机森林、梯度提升树三者投票或取平均概率。

不过做融合前,必须保证每个模型都已经调得不错。如果底模本身有缺陷,融合只是把多个坏预测综合到一起。另一个常见做法是使用简单的Stacking:把基模型的预测概率作为新特征,再交给逻辑回归做第二层学习。在小数据集上要小心过拟合,所以我会给第二层模型很轻的复杂度,比如只用少量严格正则项的逻辑回归。

6. 全流程提交:从预测到出分

6.1 对齐训练集和测试集是硬道理

整个流程最后一步,最容易翻车的就是测试集预处理的列对齐。训练集经过特征工程后生成了一组列,测试集可能因为某个类别值没出现,生成的是另一组列。直接拿模型预测测试集会报错,或者更可怕的是不报错但列顺序错位。

我写了一个通用的小函数来处理对齐:

def align_columns(train_df, test_df): missing_in_test = set(train_df.columns) - set(test_df.columns) for col in missing_in_test: test_df[col] = 0 test_df = test_df[train_df.columns] return test_df

先把缺失列补成0,再按训练集的列顺序重排测试集。这一步做了之后,预测出来的结果才是可信的。另一个容易翻车的点是把PassengerId带丢了,提交文件里没有PassengerId会直接导致无法评分。

6.2 提交文件格式与线上分数回验

提交文件必须是一个CSV,两列,第一行是表头“PassengerId,Survived”,第二行起是每一行乘客ID和0/1预测值。我通常会让模型预测概率,然后按0.5阈值转成0或1。如果想让成绩再稳一点,也可以对阈值做小范围搜索,比如0.45到0.55之间,看交叉验证哪个阈值最合适。

test_pred = model.predict_proba(test_X)[:, 1] submission = pd.DataFrame({ 'PassengerId': test['PassengerId'], 'Survived': (test_pred >= 0.5).astype(int) }) submission.to_csv('submission.csv', index=False)

第一次提交后,经常会发现线上分数比本地低0.01到0.02。这不一定是代码有问题,而是公共测试集和训练集分布有差异。只要差值在合理范围内,我一般不会强烈针对公榜调参。但如果你写了一个本地0.85、线上0.78的模型,那基本可以断定过拟合了,回去查特征里是不是塞入了太多特殊个案的信息。

7. 避坑清单与进一步扩展

7.1 我踩过的那些坑

第一坑是手写验证集且不复用。早期我为了省时间,只划分一次验证集,分数稍微提升就以为自己进步了。后来发现,很多时候只是这次随机划分对某个模型更友好。现在无论做什么实验,我都会固定随机种子,并且用交叉验证而不是单次划分。

第二坑是特征工程和调参顺序弄反。先调参后做特征,会导致整个实验空间混乱,参数是为了某个特定特征组合调的,特征一变,参数全废。正确顺序是先定特征组合,再做参数搜索,最后才碰融合。

第三坑是忽略类别编码的一致性。曾有一次我在训练集对Cabin类别做了编码,但在测试集因为某些类别不存在,编码结果多了一列少了一列,模型预测时直接报错。从那以后,我在跨数据集操作后都会加一个shape检查,确保训练矩阵和测试矩阵列数一致。

还有一个情绪坑:公榜排名焦虑。泰坦尼克的测试集只有418条,预测结果的随机波动比想象中更大。有时候你辛辛苦苦加了特征,公榜分数反而下降0.005,这不一定是特征没用,可能只是运气偏差。以交叉验证为准,别被单次数值牵着鼻子走。

7.2 这个题之后还可以往哪里走

做完泰坦尼克,下一个方向不要急着追求复杂比赛。可以试试两类任务:一类是类似的结构化表格题,比如房价预测,它同样考验特征工程和数据清洗;另一类是带文本或图像的数据集,开始接触非结构化数据。

如果想把泰坦尼克本身玩得更深,可以试着改进特征工程:用更细致的名字称谓分组,用乘客姓名里的家族关键词做家庭分组,甚至用Cabin的楼层和位置信息做空间特征的还原。每动一步,都用交叉验证对比一下是否真的变好,这个过程本身就是机器学习里最重要的一项能力:学会判断什么改变是有效的,什么只是偶然波动。

我个人在实际操作中的体会是:泰坦尼克不是一个比谁跑得快的问题,而是一个比谁对数据更耐心的问题。那些看起来花哨的0.83、0.84分数,背后的功夫几乎都下在了建模之前的数据整理里。先把数据摸透,把特征做扎实,再用简单的模型拿稳分数,比一上来就堆复杂模型要靠谱得多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 3:22:46

文件下载全解析:从HTTP原理到多线程与P2P排障实战

下载文件这件事,听起来简单到不值一提,可实际一上手,十个里起码有三四个会遇到“下载到一半断了”“速度忽快忽慢最后归零”“文件名变成一串乱码”这种糟心事。我自己折腾过一阵子各类下载工具,也帮人排查过不少下载问题&#xf…

作者头像 李华
网站建设 2026/10/22 3:22:25

Pr语音转文字实战指南:从转录到导出字幕的完整流程

做短视频和后期这行,几乎人人都被“手动打字幕”折磨过。片子剪好了,字幕却要逐句去对时间轴,一句一句敲键盘,遇到口播快的视频,一个小时的内容能干到天亮。后来 Pr 更新了语音转文字功能,我第一次用的时候…

作者头像 李华
网站建设 2026/10/22 3:22:16

3DMAX安装错误1624根源与修复:Windows Installer注册表残留清理指南

最近在处理一台旧笔记本的软件环境时,又撞上了那个熟悉的弹窗:安装3DMAX进行到一半,进度条停住,接着蹦出"错误1624:应用转换时错误,请验证路径是否有效"。第一次遇到这个报错的人,十有…

作者头像 李华
网站建设 2026/10/22 3:22:01

MSE训练分类模型精度上不去?交叉熵才是正确选择

先说结论:如果你现在正拿 MSE(均方误差)去训练一个带 softmax 的分类模型,而且发现验证集的精度总是上不去、训练 loss 还在往下走,那你先别急着调学习率或者换网络结构,大概率是损失函数在给你“慢性放血”…

作者头像 李华
网站建设 2026/10/22 3:22:01

反向传播算法详解:从链式法则到梯度计算与神经网络训练

1. 解开“AI写的”那层皮:反向传播到底在解决什么问题最近在翻资料的时候又看到不少标记着“某某AI写作工具生成”的技术教程,其中有一篇讲反向传播,题目写得挺唬人,叫“深度解析:反向传播在神经网络训练中的应用”。我…

作者头像 李华
网站建设 2026/10/22 3:21:36

老项目AI编程实战:让AI读懂旧代码,效率翻倍的完整指南

接手老项目的第一天,光是跑通构建就花了一下午。等到终于能看到运行界面时,需求群里又追加了三条改动要求。这种事干开发的老手应该都懂:老项目的可怕之处不在于代码多,而在于每一行代码背后都有一段理不清的历史,你不…

作者头像 李华