简介这份泰坦尼克号幸存者预测Python项目资源包面向计算机相关专业学生与Python初学者可用于期末大作业、课程设计或机器学习入门实战帮助解决从数据清洗到模型预测的完整流程问题。压缩包共17个文件约4.78MB包含4个py脚本、2个ipynb笔记本、3个csv数据集、4个xml配置及readme、pdf说明等覆盖数据读取、特征工程、模型训练与结果提交等环节代码注释清晰新手也能看懂。目前已有108人学习下载。资源提供完整赛题方案与目录结构含数据清洗、分析与建模模块可直接部署运行便于快速复现并理解幸存者预测的建模思路适合作为高分课程设计参考。1. 泰坦尼克号幸存者预测一份能直接跑通的课程设计资源课程设计周最怕的不是不会写代码而是拿到一份跑不起来的压缩包。这份「泰坦尼克号幸存者预测 Python 代码数据集全套」的资源解压后目录结构是完整的code-master下挂着data、cleaning、example三个模块train.csv、test.csv、gender_submission.csv三个数据文件齐全还有一份Titanic.pdf和demo.py入口脚本。它解决的核心问题很具体——把 Kaggle 经典二分类任务从数据清洗到模型评估的整条链路用带注释的 Python 代码串起来新手照着demo.py就能跑出提交文件熟手可以直接拆cleaning模块换特征工程方案。适合正在做 Python 期末大作业、课程设计的学生也适合想拿一个干净 baseline 练手特征工程的从业者。数据集本身是泰坦尼克号乘客信息标签是是否幸存属于典型的表格二分类场景不涉及复杂环境依赖pandasscikit-learn就能覆盖主流程。2. 拆开压缩包目录结构与数据字段到底怎么对应2.1 三个数据文件的角色分工解压后data目录下有三个 CSV很多人第一次打开会懵为什么训练集和测试集之外还有一个gender_submission.csv。这三个文件的定位完全不同用错了整个流程就断了。文件名行数典型是否含标签用途train.csv891含Survived训练模型、做交叉验证test.csv418不含Survived生成预测结果、模拟提交gender_submission.csv418含Survived官方给的提交格式样例仅作对照train.csv的字段里PassengerId是唯一标识Survived是标签0 死亡、1 幸存Pclass是舱位等级1/2/3Name、Sex、Age、SibSp、Parch、Ticket、Fare、Cabin、Embarked是特征。test.csv少了Survived列其余字段一致。gender_submission.csv只有PassengerId和Survived两列它的作用是告诉你提交文件的列名和顺序应该长什么样不是拿来训练的。提示gender_submission.csv里的Survived是按性别硬猜的女性全 1、男性全 0准确率大约 0.765可以当作一个最低 baseline 来对比你的模型有没有白干。2.2 模块划分与调用关系code-master下的cleaning目录里放了data_analysis.ipynb这是整个项目里最值得先读的文件。它承担了缺失值统计、分布可视化、相关性初筛的工作。example目录下的demo.py是入口通常会import上级模块或直接读取data下的 CSV。__init__.py出现在多个目录里说明作者是按包结构组织的这意味着你可以在项目根目录用python -m example.demo的方式运行而不是只能cd进去再python demo.py。常见做法是先把data_analysis.ipynb跑一遍看Age、Cabin、Embarked三个字段的缺失比例再决定填充策略。Age缺失约 177 条Cabin缺失约 687 条Embarked只缺 2 条。这三个字段的处理方式直接决定后续模型上限不是随便fillna(0)就能糊弄过去的。2.3 环境依赖与最小运行条件这份资源没有附带requirements.txt但根据代码里会用到的库最小依赖是pandas、numpy、scikit-learn、matplotlib、seaborn。如果你用的是较新的 Python 版本3.9 以上scikit-learn建议 1.0 以上避免OneHotEncoder的sparse参数行为差异导致报错。# 建议先建虚拟环境避免和系统包冲突 python -m venv titanic_env source titanic_env/bin/activate # Windows 用 titanic_env\Scripts\activate # 安装最小依赖 pip install pandas numpy scikit-learn matplotlib seaborn jupyter装完后在项目根目录执行jupyter notebook打开cleaning/data_analysis.ipynb逐格运行。如果matplotlib中文显示乱码在 notebook 开头加两行配置即可不影响核心逻辑。3. 从原始 CSV 到特征矩阵清洗与编码的实操路径3.1 缺失值填充为什么 Age 用中位数而不是均值Age字段有偏态直接用均值填充会把分布往中间拉而泰坦尼克号乘客里年轻男性占比高均值填充会高估老年乘客的年龄。常见做法是按Pclass和Sex分组后取组内中位数填充这样既保留了舱位和性别带来的年龄差异又不会被极端值带偏。import pandas as pd import numpy as np train pd.read_csv(data/train.csv) test pd.read_csv(data/test.csv) # 按 Pclass Sex 分组用组内中位数填充 Age for df in [train, test]: df[Age] df.groupby([Pclass, Sex])[Age].transform( lambda x: x.fillna(x.median()) ) # Embarked 只缺 2 条用众数填充 train[Embarked] train[Embarked].fillna(train[Embarked].mode()[0]) # Fare 在 test 里缺 1 条用 Pclass 分组中位数填充 test[Fare] test.groupby(Pclass)[Fare].transform( lambda x: x.fillna(x.median()) )groupby后的transform保证填充后的行数和原表一致不会因为分组聚合丢行。mode()[0]取众数第一个值避免返回 Series 导致赋值失败。Fare在test.csv里缺的那一条如果不处理后面predict会直接报 NaN 错误。3.2 类别编码Sex、Embarked 和 Pclass 的处理差异Sex是二值类别直接映射成 0/1 即可。Embarked有三个取值S、C、Q用pd.get_dummies做独热编码注意drop_firstTrue避免多重共线性。Pclass虽然是有序类别1 2 3但直接当数值用会引入“1 和 2 的差距等于 2 和 3 的差距”这个错误假设常见做法是保留数值形式同时观察模型系数是否合理。# Sex 二值映射 for df in [train, test]: df[Sex] df[Sex].map({male: 0, female: 1}) # Embarked 独热编码drop_first 去掉一列 train pd.get_dummies(train, columns[Embarked], drop_firstTrue) test pd.get_dummies(test, columns[Embarked], drop_firstTrue) # 对齐列防止 train 和 test 编码后列数不一致 train, test train.align(test, joinleft, axis1, fill_value0)align这一步是血泪经验如果train里Embarked有三个值test里只有两个独热编码后列数不同直接喂给模型会报特征维度不匹配。align以train为准test缺的列补 0保证两边特征矩阵列名和顺序完全一致。3.3 特征衍生从 Name 和 Ticket 里再榨一点信息Name字段里藏着称呼Mr、Mrs、Miss、Master这个称呼和生存率强相关尤其是Master小男孩的生存率明显高于成年男性。Ticket的前缀也能反映舱位或同行人数。这两列原始形式没法直接用但衍生出Title和TicketPrefix后能提升模型区分度。# 从 Name 提取称呼 for df in [train, test]: df[Title] df[Name].str.extract(r ([A-Za-z])\., expandFalse) # 合并稀有称呼 df[Title] df[Title].replace( [Lady, Countess, Capt, Col, Don, Dr, Major, Rev, Sir, Jonkheer, Dona], Rare) df[Title] df[Title].replace({Mlle: Miss, Ms: Miss, Mme: Mrs}) # 独热编码 Title train pd.get_dummies(train, columns[Title], drop_firstTrue) test pd.get_dummies(test, columns[Title], drop_firstTrue) train, test train.align(test, joinleft, axis1, fill_value0)正则r ([A-Za-z])\.匹配名字里最后一个空格后、点号前的字母串这是提取称呼的通用写法。合并稀有称呼是为了防止某些类别样本太少导致模型过拟合。align再次出现逻辑同上。4. 模型训练与评估为什么随机森林比逻辑回归更适合这份数据4.1 基线模型选择与交叉验证逻辑回归在这份数据上通常能到 0.78 左右随机森林能到 0.82 以上梯度提升如GradientBoostingClassifier有时能到 0.84。差距主要来自特征交互Sex和Pclass的组合效应、Age和Title的非线性关系树模型能自动捕捉逻辑回归需要手动构造交互项。from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import cross_val_score from sklearn.preprocessing import StandardScaler # 选择特征列去掉 PassengerId、Name、Ticket、Cabin 等原始列 feature_cols [c for c in train.columns if c not in [PassengerId, Survived, Name, Ticket, Cabin]] X train[feature_cols] y train[Survived] # 随机森林树数量 100最大深度 5 防止过拟合 rf RandomForestClassifier(n_estimators100, max_depth5, random_state42) scores cross_val_score(rf, X, y, cv5, scoringaccuracy) print(fCV 准确率: {scores.mean():.4f} ± {scores.std():.4f})n_estimators100是起点树再多边际收益递减。max_depth5是控制过拟合的关键泰坦尼克号数据量小891 条树太深会记住训练集噪声。cv5做五折交叉验证scores.std()反映模型稳定性如果标准差超过 0.03说明模型对数据划分敏感需要调参或增加特征。4.2 特征重要性排序与无用特征剔除训练完随机森林后feature_importances_能告诉你哪些特征真正在起作用。常见结果是Sex、Fare、Age、Title_Mr排前几而SibSp、Parch单独看重要性低但组合成FamilySize后可能提升。import matplotlib.pyplot as plt rf.fit(X, y) importances pd.Series(rf.feature_importances_, indexfeature_cols) importances.sort_values(ascendingFalse).head(10).plot(kindbarh) plt.title(Top 10 Feature Importances) plt.show() # 剔除重要性低于 0.01 的特征重新训练对比 low_imp importances[importances 0.01].index.tolist() X_reduced X.drop(columnslow_imp) scores_reduced cross_val_score(rf, X_reduced, y, cv5, scoringaccuracy) print(f剔除低重要性特征后 CV: {scores_reduced.mean():.4f})如果剔除后准确率没降甚至略升说明那些特征确实是噪声。但要注意重要性低不代表一定没用可能是它和另一个特征高度相关被“分摊”了重要性。稳妥做法是每次只剔一两个观察 CV 变化。4.3 生成提交文件与格式校验test.csv没有标签预测完要按gender_submission.csv的格式输出。PassengerId必须和test.csv一致Survived是 0/1 整数不能带小数点。# 用全量训练集重新拟合 rf.fit(X, y) # 对 test 做同样特征选择 X_test test[feature_cols] predictions rf.predict(X_test) submission pd.DataFrame({ PassengerId: test[PassengerId], Survived: predictions.astype(int) }) submission.to_csv(submission.csv, indexFalse) # 校验行数和列名 assert submission.shape (418, 2), 行数或列数不对 assert list(submission.columns) [PassengerId, Survived], 列名不对 print(submission.head())astype(int)把预测结果转成整数避免输出 0.0/1.0 被平台判格式错误。assert两行是后悔药提交前跑一遍能拦住大部分低级错误。indexFalse防止把 DataFrame 索引写进 CSV 多出一列。5. 避坑与排查这份资源跑不起来时先看这五条5.1 报错 KeyError: Survived 出现在 test.csv 上现象执行test[Survived]或把test直接喂给需要标签的函数时报 KeyError。原因test.csv本身不含Survived列这是设计如此不是数据损坏。解决检查代码里是否误把test当训练集用所有涉及标签的操作只对train做test只用于predict。5.2 独热编码后 train 和 test 列数不一致现象model.predict(X_test)报特征维度不匹配比如训练时 12 列、预测时 11 列。原因Embarked或Title在test里缺少某个类别get_dummies生成的列数不同。解决在独热编码后立即用train, test train.align(test, joinleft, axis1, fill_value0)对齐以训练集列为准。5.3 Age 填充后出现负数或异常值现象填充后Age最小值变成负数或分布明显偏离原始数据。原因分组中位数计算时某些PclassSex组合样本太少中位数不稳定或者用均值减标准差做随机填充时没截断。解决填充后加df[Age] df[Age].clip(lower0)并检查各组的样本数少于 10 条的组考虑合并或改用全局中位数。5.4 交叉验证准确率很高但提交分数很低现象本地 CV 0.85提交到平台只有 0.76。原因过拟合模型记住了训练集的噪声或者特征工程里用了test的信息数据泄露比如用全体数据算均值再填充。解决检查所有填充、编码、标准化步骤是否只在train上fit然后transform到test降低模型复杂度比如减小max_depth或增加min_samples_leaf。5.5 Jupyter Notebook 里中文标题显示方块现象matplotlib图表标题中文变成方框。原因默认字体不支持中文。解决在 notebook 开头加plt.rcParams[font.sans-serif] [SimHei]和plt.rcParams[axes.unicode_minus] FalseWindows 下SimHei通常可用Mac 可换Arial Unicode MS。6. 进阶技巧把 0.82 推到 0.85 的两个具体操作第一个操作是构造FamilySize和IsAlone。SibSp和Parch单独看重要性低但加起来再加 1自己就是家庭规模。家庭规模 2 到 4 的生存率明显高于独自一人或超大家庭。这个特征在随机森林里通常能挤进重要性前五。for df in [train, test]: df[FamilySize] df[SibSp] df[Parch] 1 df[IsAlone] (df[FamilySize] 1).astype(int) # 重新选择特征列 feature_cols [c for c in train.columns if c not in [PassengerId, Survived, Name, Ticket, Cabin, SibSp, Parch]] X train[feature_cols] X_test test[feature_cols] rf RandomForestClassifier(n_estimators200, max_depth6, min_samples_leaf3, random_state42) scores cross_val_score(rf, X, y, cv5, scoringaccuracy) print(f加入 FamilySize 后 CV: {scores.mean():.4f} ± {scores.std():.4f})min_samples_leaf3是防止过拟合的另一个旋钮叶节点至少 3 个样本树不会为了个别样本长太深。n_estimators提到 200 配合max_depth6在数据量小的情况下比 100 棵树深度 5 略稳。第二个操作是Fare分箱。Fare是连续值但它的分布极度右偏少数高价票拉高了均值。把它按分位数切成 4 箱树模型更容易找到切分点。for df in [train, test]: df[FareBin] pd.qcut(df[Fare], 4, labelsFalse, duplicatesdrop) # 用 FareBin 替换原始 Fare feature_cols [c for c in feature_cols if c ! Fare] [FareBin] X train[feature_cols] X_test test[feature_cols] rf.fit(X, y) final_scores cross_val_score(rf, X, y, cv5, scoringaccuracy) print(fFare 分箱后 CV: {final_scores.mean():.4f})pd.qcut按分位数切保证每箱样本数接近。duplicatesdrop处理边界重复值避免报错。分箱后原始Fare列要去掉否则信息冗余反而干扰树的分裂选择。这两个操作做完CV 通常能从 0.82 推到 0.84 到 0.85 之间。但要注意如果FareBin和Pclass高度相关提升可能不明显这时候可以只保留其中一个。我一般会在 notebook 里同时跑三组对比原始特征、加FamilySize、再加FareBin看 CV 均值有没有实质提升而不是凭感觉堆特征。从那以后我每次做表格二分类都强制先跑一遍特征重要性再决定加什么、删什么不盲目抄网上的“必加特征”清单。希望帮到你。本文还有配套的精品资源点击获取