ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

泰坦尼克号生存预测:从数据探索到机器学习建模的完整实践

泰坦尼克号生存预测:从数据探索到机器学习建模的完整实践 1. 从泰坦尼克号到数据科学一个经典的入门项目如果你对数据分析、机器学习或者Python编程感兴趣那么“泰坦尼克号生存预测”这个项目几乎是你绕不开的第一站。它就像数据科学界的“Hello World”但远比打印一行文字要复杂和迷人得多。这个项目之所以经典不仅仅是因为它基于那段广为人知的历史悲剧更因为它完美地封装了一个数据分析项目的完整生命周期从原始数据的获取、清洗、探索到特征工程、模型构建最终得出预测结论。今天我们就抛开那些教科书式的框架从一个一线从业者的角度手把手地带你走一遍这个流程重点不是让你“调包”跑通代码而是让你理解每一步背后的“为什么”以及那些新手最容易踩进去的坑。想象一下你手头有一份泰坦尼克号上部分乘客的名单记录了他们的船票等级、姓名、性别、年龄、是否携带兄弟姐妹或配偶、是否携带父母子女、船票编号、票价、客舱号、登船港口以及最重要的——是否幸存。你的任务就是利用这些信息去探索“什么样的人更有可能在灾难中活下来”并尝试构建一个模型去预测那些我们不知道结果的乘客的命运。这听起来像是一个侦探游戏而数据就是你的线索。我们将全程使用Python因为它丰富的数据科学生态Pandas, NumPy, Matplotlib, Seaborn, Scikit-learn能让这个过程变得高效且直观。通过这个项目你不仅能学会如何使用这些工具更能建立起面对一份陌生数据集时那种抽丝剥茧、寻找洞见的数据思维。2. 数据初窥加载与理解你的“线索档案”拿到数据后的第一步绝不是急着画图或跑模型。一个合格的数据从业者会像侦探勘察现场一样先对数据进行一次全面的“体检”理解每一列数据的含义、类型、完整性和分布情况。这能帮你避免后续分析中因数据误解而导致的严重错误。2.1 数据加载与初步审视我们通常从Kaggle等平台获取泰坦尼克号的数据集它一般包含两个文件train.csv训练集包含生存结果和test.csv测试集不包含生存结果用于最终模型评估。我们首先加载训练集。import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns # 设置绘图风格让图表更好看 sns.set_style(whitegrid) plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus] False # 用来正常显示负号 # 加载数据 train_df pd.read_csv(train.csv) test_df pd.read_csv(test.csv) # 看一眼数据形状和前面几行 print(f训练集形状: {train_df.shape}) print(f测试集形状: {test_df.shape}) print(\n训练集前5行:) print(train_df.head())运行后你可能会看到训练集有891行12列包括目标列Survived。head()方法让你直观地看到数据长什么样PassengerId是乘客IDSurvived是生存标签0遇难1幸存Pclass是船票等级1头等舱2二等舱3三等舱Name是姓名Sex是性别Age是年龄等等。注意这里有一个非常关键的细节。test.csv通常没有Survived列这是为了模拟真实预测场景。但在探索性数据分析EDA阶段我们主要甚至只使用train_df因为我们需要知道特征和结果之间的关系。测试集只在最后验证模型泛化能力时使用切记不要在EDA中不小心“窥探”了测试集的信息这会导致模型评估失真俗称“数据泄露”。2.2 数据字典与信息摘要接下来我们需要更系统地了解每一列。# 查看数据集的整体信息列名、非空值数量、数据类型 print(train_df.info())info()方法的结果会告诉你Age年龄、Cabin客舱、Embarked登船港口列存在大量缺失值。例如Age列有177个缺失值Cabin列缺失更是高达687个。这是数据清洗环节需要重点处理的。然后我们查看数值型数据的统计摘要。# 查看数值型列的统计描述计数、均值、标准差、最小值、四分位数、最大值 print(train_df.describe())describe()默认只针对数值列如Age,Fare,SibSp等。从这里你可以快速发现一些信息平均年龄约30岁但标准差约14.5岁说明年龄分布较广最低票价是0这可能是船员或特殊情况最高票价高达512贫富差距极大SibSp兄弟姐妹/配偶数和Parch父母/子女数的中位数都是0说明大多数乘客是独自或仅与伴侣/孩子同行。对于非数值型列对象类型我们也需要查看其唯一值分布。# 查看非数值型列的分布 print(train_df[[Sex, Embarked, Cabin, Ticket]].describe(include[O]))你会发现Sex只有‘male’和‘female’两个值Embarked有三个登船港口C, Q, S而Cabin和Ticket船票编号则非常杂乱包含大量唯一值这暗示它们可能需要特殊的处理方式而不是直接用于模型。2.3 识别缺失值与异常值缺失值处理是数据清洗的核心。我们必须先弄清楚缺失的机制是随机缺失还是与某些特征有关这会影响我们填充缺失值的方式。# 计算每列缺失值的数量和比例 missing_data train_df.isnull().sum().sort_values(ascendingFalse) missing_percent (train_df.isnull().sum() / train_df.isnull().count()).sort_values(ascendingFalse) missing_df pd.concat([missing_data, missing_percent], axis1, keys[Total, Percent]) print(missing_df.head(10))Cabin缺失超过77%通常对于缺失比例过高的特征比如50%我们会慎重考虑是否直接删除该列因为填充可能会引入巨大噪声。Age缺失约20%这是一个可以尝试填充的比例。Embarked仅缺失2个可以直接用众数填充。异常值方面我们可以通过箱线图或基于标准差的方法来探查。例如查看Fare票价的异常值。# 绘制Fare的箱线图 plt.figure(figsize(10, 6)) sns.boxplot(xtrain_df[Fare]) plt.title(船票价格分布箱线图查看异常值) plt.show()你会看到箱体上方的“胡须”之外有很多远离的点这些都是异常值。对于票价这些异常高值可能对应着头等舱的豪华套间它们本身是合理的并非错误数据。在建模时我们可能需要对其进行对数变换以减弱极端值对模型的影响。3. 单变量与多变量探索寻找生存的“密码”在摸清数据底细后我们就可以开始真正的探索——分析各个特征与生存率Survived之间的关系。这是EDA最有趣的部分我们将用可视化来讲述数据故事。3.1 目标变量分布幸存者与遇难者首先我们看看整体的生存情况。# 计算生存率 survival_count train_df[Survived].value_counts() survival_rate train_df[Survived].value_counts(normalizeTrue) * 100 print(f遇难人数: {survival_count[0]} ({survival_rate[0]:.2f}%)) print(f幸存人数: {survival_count[1]} ({survival_rate[1]:.2f}%)) # 绘制饼图 plt.figure(figsize(8, 8)) plt.pie(survival_count, labels[遇难, 幸存], autopct%1.1f%%, startangle90, colors[lightcoral, lightblue]) plt.title(泰坦尼克号乘客总体生存情况) plt.show()数据显示只有约38.4%的乘客幸存。这意味着我们的基线模型即总是预测“遇难”的准确率可以达到61.6%。任何我们构建的模型准确率必须显著高于这个值才有意义。3.2 关键特征与生存率的关联分析接下来我们逐一考察那些直觉上可能影响生存率的特征。性别Sex “妇女和儿童优先”的逃生原则是否在数据中体现# 按性别分组计算生存率 sex_survival train_df.groupby(Sex)[Survived].agg([mean, count]) print(sex_survival) # 绘制柱状图 plt.figure(figsize(10, 6)) sns.barplot(xSex, ySurvived, datatrain_df, ciNone, paletteSet2) # ciNone 不显示置信区间 plt.title(性别与生存率关系) plt.ylabel(生存率) plt.show()结果非常显著女性的生存率高达74%而男性仅为19%。性别将成为我们模型中一个极强的预测因子。船票等级Pclass 社会阶级是否决定了逃生机会头等舱乘客是否更靠近救生艇# 按船票等级分组计算生存率 pclass_survival train_df.groupby(Pclass)[Survived].agg([mean, count]) print(pclass_survival) # 绘制柱状图 plt.figure(figsize(10, 6)) sns.barplot(xPclass, ySurvived, datatrain_df, ciNone, paletterocket) plt.title(船票等级与生存率关系) plt.ylabel(生存率) plt.show()生存率随着船票等级的下降而急剧下降头等舱约63%二等舱约47%三等舱仅24%。阶级的影响一目了然。登船港口Embarked 从不同港口C Cherbourg, Q Queenstown, S Southampton登船的乘客生存率有差异吗这可能间接反映了乘客的构成如国籍、阶级。# 按登船港口分组计算生存率 embarked_survival train_df.groupby(Embarked)[Survived].agg([mean, count]) print(embarked_survival) plt.figure(figsize(10, 6)) sns.barplot(xEmbarked, ySurvived, datatrain_df, ciNone, paletteviridis) plt.title(登船港口与生存率关系) plt.ylabel(生存率) plt.show()从C瑟堡登船的乘客生存率最高约55%远高于S南安普顿和Q皇后镇。一个可能的解释是从瑟堡登船的头等舱乘客比例较高。3.3 连续型变量的深入分析年龄与票价对于像Age和Fare这样的连续变量简单的分组聚合可能不够我们需要更细致的可视化。年龄Age 儿童是否真的被优先救助# 由于Age有缺失值我们先创建一个不含缺失值的副本用于分析 age_data train_df[[Age, Survived]].dropna() # 绘制分布直方图与密度曲线 plt.figure(figsize(14, 6)) plt.subplot(1, 2, 1) sns.histplot(dataage_data, xAge, hueSurvived, elementstep, statdensity, common_normFalse) plt.title(按生存状态划分的年龄分布) # 绘制箱线图 plt.subplot(1, 2, 2) sns.boxplot(xSurvived, yAge, dataage_data) plt.title(生存组与遇难组的年龄分布箱线图) plt.tight_layout() plt.show() # 将年龄分箱看不同年龄段的生存率 train_df[AgeBand] pd.cut(train_df[Age], bins[0, 12, 18, 35, 60, 100], labels[儿童, 少年, 青年, 中年, 老年]) ageband_survival train_df.groupby(AgeBand, observedFalse)[Survived].mean().dropna() print(ageband_survival)从分布图可以看出幸存者中低龄儿童的比例确实更高。箱线图显示幸存者的年龄中位数略低于遇难者。分箱数据明确显示儿童的生存率约59%远高于其他年龄段。这证实了“儿童优先”的原则。票价Fare 票价与生存率的关系可能并非线性。# 绘制票价与生存率的散点图由于数据点密集使用蜂群图或小提琴图更好 plt.figure(figsize(14, 6)) plt.subplot(1, 2, 1) # 使用小提琴图展示不同生存状态下票价的分布 sns.violinplot(xSurvived, yFare, datatrain_df) plt.ylim(0, 200) # 限制y轴范围以看清主要分布 plt.title(票价分布小提琴图按生存状态) plt.subplot(1, 2, 2) # 对票价取对数使其分布更接近正态再看与生存率的关系 train_df[Fare_log] np.log1p(train_df[Fare]) # log1p处理0值 sns.boxplot(xSurvived, yFare_log, datatrain_df) plt.title(对数变换后票价与生存率关系) plt.tight_layout() plt.show()原始票价分布极度右偏大量低票价和少数极高票价。小提琴图显示幸存者的票价整体分布更高。经过对数变换后这种正相关关系在箱线图中表现得更加清晰。高票价通常意味着更高的船票等级和更好的位置从而带来更高的生存机会。3.4 特征组合与交叉分析故事变得更加复杂单一变量的分析有时会掩盖真相。我们需要进行交叉分析看看在控制一个变量的情况下另一个变量的影响如何变化。性别与船票等级的交互作用 一位三等舱的女士和一位头等舱的男士谁的生存几率更高# 使用Seaborn的pointplot或catplot可以很好地展示这种交互 plt.figure(figsize(12, 8)) sns.pointplot(xPclass, ySurvived, hueSex, datatrain_df, ciNone, paletteSet2, dodgeTrue) plt.title(不同性别下船票等级对生存率的影响) plt.ylabel(生存率) plt.show() # 或者使用交叉表 cross_tab pd.crosstab(index[train_df[Pclass], train_df[Sex]], columnstrain_df[Survived], normalizeindex) print(cross_tab)图表揭示了一个残酷的现实在所有舱等中女性的生存率都远高于男性。但即使是头等舱的男性其生存率约37%也低于三等舱的女性约50%。性别因素在灾难中的权重似乎超过了阶级因素。年龄与性别的交互作用 “妇女和儿童优先”中的“儿童”是否区分性别# 创建一个“是否儿童”的特征 train_df[IsChild] (train_df[Age] 12).astype(int) # 分析儿童中性别对生存率的影响 child_data train_df[train_df[IsChild] 1] if not child_data.empty: child_survival_by_sex child_data.groupby(Sex)[Survived].mean() print(f儿童生存率按性别:\n{child_survival_by_sex})数据显示女性儿童的生存率可能略高于男性儿童但由于儿童样本量本身不大且生存率普遍较高差异可能不显著。但这一分析展示了如何通过创建新特征来挖掘更深层次的信息。家庭成员数量与生存率 携带家人同行是优势还是劣势SibSp和Parch这两个特征可以合并。# 创建“家庭规模”特征 train_df[FamilySize] train_df[SibSp] train_df[Parch] 1 # 加上自己 # 查看家庭规模与生存率的关系 family_survival train_df.groupby(FamilySize)[Survived].agg([mean, count]) print(family_survival) plt.figure(figsize(12, 6)) sns.barplot(xFamilySize, ySurvived, datatrain_df, ciNone, palettecoolwarm) plt.title(家庭规模与生存率关系) plt.ylabel(生存率) plt.show()你会发现一个有趣的“U型”曲线独自旅行的人FamilySize1生存率较低小型家庭2-4人生存率最高这可能是因为家庭成员间可以互相协助而非常庞大的家庭4人生存率又急剧下降可能是因为在混乱中协调多人逃生非常困难。这个非线性关系提示我们在后续特征工程中可能需要对FamilySize进行分箱处理或者创建“是否独自旅行”、“是否小型家庭”等哑变量。4. 特征工程从原始数据中创造“超能力”探索分析给了我们洞见但原始数据并不总是以最友好的形式喂给机器学习模型。特征工程就是利用我们的领域知识在这里就是对泰坦尼克号数据的理解将原始数据转换、组合、创造为对预测目标更有用的新特征的过程。这是提升模型性能最关键的一步也是最能体现数据科学家功底的地方。4.1 处理姓名Name字段提取头衔姓名本身看似无用但其中包含的“头衔”如 Mr., Mrs., Miss., Master., Dr. 等却蕴含了丰富的社交地位、年龄和性别信息。# 使用正则表达式从头衔中提取头衔 train_df[Title] train_df[Name].str.extract( ([A-Za-z])\., expandFalse) # 查看头衔分布 print(train_df[Title].value_counts()) # 将一些罕见的头衔进行归类 title_mapping { Mr: Mr, Miss: Miss, Mrs: Mrs, Master: Master, # 对未成年男性的尊称 Dr: Rare, Rev: Rare, Col: Rare, Major: Rare, Mlle: Miss, # 法语“小姐” Mme: Mrs, # 法语“夫人” Ms: Mrs, Lady: Rare, Countess: Rare, Capt: Rare, Sir: Rare, Don: Rare, Dona: Rare, Jonkheer: Rare } train_df[Title] train_df[Title].map(title_mapping) print(train_df[Title].value_counts()) # 查看不同头衔的生存率 print(train_df.groupby(Title)[Survived].mean().sort_values(ascendingFalse))你会发现“Mrs”和“Miss”女性生存率极高“Master”男孩生存率也较高而“Mr”男性生存率很低。Rare头衔组贵族、军官等生存率各异。这个新特征Title比单纯的Sex包含了更多维度的信息。4.2 处理客舱Cabin字段提取甲板信息Cabin字段缺失严重但已有的信息中首字母代表甲板如 A, B, C, D...。不同甲板的位置可能影响逃生。# 提取客舱号的首字母作为甲板信息缺失值用‘U’(Unknown)表示 train_df[Deck] train_df[Cabin].apply(lambda x: x[0] if pd.notna(x) else U) print(train_df[Deck].value_counts()) print(train_df.groupby(Deck)[Survived].mean().sort_values(ascendingFalse))数据显示甲板B、D、E的生存率较高而甲板U未知和G的生存率较低。尽管缺失值多但甲板信息仍可能提供一些信号。在模型中可以将其作为分类特征使用或者与Pclass结合。4.3 创建家庭相关衍生特征基于之前的分析我们可以创建更多家庭相关的特征。# 是否独自旅行 train_df[IsAlone] (train_df[FamilySize] 1).astype(int) # 家庭规模分箱独自、小型、大型 train_df[FamilySizeGroup] pd.cut(train_df[FamilySize], bins[0, 1, 4, 20], labels[Alone, Small, Large]) print(train_df.groupby(IsAlone)[Survived].mean()) print(train_df.groupby(FamilySizeGroup, observedFalse)[Survived].mean())IsAlone特征清晰地显示独自旅行者生存率30%远低于有家人者50%。这验证了我们之前的观察。4.4 处理缺失值以Age为例的策略对于缺失比例较高的Age我们不能简单地用整体均值填充因为不同人群的年龄分布差异很大例如头衔为“Master”的肯定是孩子“Miss”和“Mrs”的年龄分布也不同。一个更聪明的办法是根据其他特征如Title,Pclass来分组估算年龄。# 按Title和Pclass分组用该组的年龄中位数来填充本组内的缺失年龄 # 先查看分组后的年龄中位数 grouped_age train_df.groupby([Title, Pclass])[Age].median() print(grouped_age) # 定义一个函数来填充年龄 def fill_age(row): if pd.isna(row[Age]): return grouped_age[row[Title], row[Pclass]] else: return row[Age] train_df[Age] train_df.apply(fill_age, axis1) # 验证是否还有缺失值 print(train_df[Age].isnull().sum())这种方法比全局均值填充合理得多它保留了不同群体间的年龄差异。对于Embarked仅缺失2个我们直接用众数填充train_df[Embarked].fillna(train_df[Embarked].mode()[0], inplaceTrue)。对于Fare测试集中有1个缺失用对应Pclass的中位数填充。对于Cabin由于缺失过多我们可能选择删除该列或者仅使用我们提取的Deck特征。4.5 编码分类变量与特征缩放机器学习模型通常只能处理数值。我们需要将Sex,Embarked,Title,Deck等文本类特征转换为数字。from sklearn.preprocessing import LabelEncoder # 对有序特征如Pclass, FamilySizeGroup通常使用LabelEncoder或映射 label_encoders {} categorical_cols [Sex, Embarked, Title, Deck, FamilySizeGroup] for col in categorical_cols: if col in train_df.columns: le LabelEncoder() # 同时处理训练集和测试集确保编码一致性实际中需先合并再编码或分别处理 # 这里为演示仅处理训练集 train_df[col_encoded] le.fit_transform(train_df[col].astype(str)) label_encoders[col] le # 对于名义特征无大小关系更推荐使用独热编码One-Hot Encoding避免引入虚假的顺序关系 # 例如Embarked使用pd.get_dummies # train_df pd.get_dummies(train_df, columns[Embarked, Title], prefix[Emb, Title])对于像Age,Fare这样的连续特征如果后续使用基于距离的模型如KNN、SVM或需要梯度下降的模型需要进行特征缩放如标准化或归一化使它们处于相近的数值范围。对于树模型如随机森林、XGBoost则不需要。5. 建模准备与初步尝试从逻辑回归开始经过一系列的数据探索和特征工程我们得到了一份“干净”且信息丰富的训练数据集。现在我们可以开始尝试构建预测模型了。对于二分类问题生存/遇难逻辑回归是一个优秀且可解释性强的基线模型。5.1 准备训练数据首先我们需要从处理好的数据框中选择我们认为有用的特征并分离出特征矩阵X和目标向量y。# 选择特征列 # 这里我们使用一些工程后的特征 feature_columns [Pclass, Sex_encoded, Age, SibSp, Parch, Fare_log, Embarked_encoded, Title_encoded, IsAlone, FamilySize] # 确保所有列都存在 selected_columns [col for col in feature_columns if col in train_df.columns] X_train train_df[selected_columns] y_train train_df[Survived] print(f特征矩阵形状: {X_train.shape}) print(f目标向量形状: {y_train.shape})5.2 划分训练集与验证集我们不能用全部训练数据来训练和评估模型否则无法知道模型对新数据的泛化能力。我们需要留出一部分作为验证集。from sklearn.model_selection import train_test_split X_train_split, X_val_split, y_train_split, y_val_split train_test_split( X_train, y_train, test_size0.2, random_state42, stratifyy_train ) print(f训练子集: {X_train_split.shape}, 验证子集: {X_val_split.shape})train_test_split的参数stratifyy_train非常重要它确保训练集和验证集中幸存与遇难的比例与原数据集一致这在小样本或不平衡数据中能防止划分带来的偏差。5.3 训练与评估逻辑回归模型from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler from sklearn.metrics import accuracy_score, classification_report, confusion_matrix # 特征标准化对逻辑回归很重要 scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train_split) X_val_scaled scaler.transform(X_val_split) # 创建并训练模型 logreg LogisticRegression(random_state42, max_iter1000) # max_iter确保收敛 logreg.fit(X_train_scaled, y_train_split) # 在验证集上预测 y_val_pred logreg.predict(X_val_scaled) # 评估模型 val_accuracy accuracy_score(y_val_split, y_val_pred) print(f验证集准确率: {val_accuracy:.4f}) print(\n分类报告:) print(classification_report(y_val_split, y_val_pred)) print(\n混淆矩阵:) print(confusion_matrix(y_val_split, y_val_pred))你的第一次建模尝试准确率可能会在80%左右。这已经比61.6%的基线高了不少。分类报告会展示精确率、召回率、F1分数等更细致的指标。混淆矩阵则告诉你模型具体错在了哪里是把幸存者预测成了遇难者False Negative还是把遇难者预测成了幸存者False Positive。5.4 模型可解释性查看特征重要性逻辑回归的一个优点是我们可以查看特征的系数了解每个特征对预测结果的“贡献”方向和大小。# 将系数与特征名对应 feature_importance pd.DataFrame({ feature: selected_columns, coefficient: logreg.coef_[0] }).sort_values(coefficient, ascendingFalse) print(feature_importance)正系数表示该特征值增大会增加生存几率逻辑回归输出0.5负系数则相反。你可能会看到Sex_encoded女性编码后可能为1有很高的正系数而Pclass舱等数字越大代表等级越低有负系数这与我们之前的探索分析完全吻合。6. 尝试更强大的模型与交叉验证逻辑回归给了我们一个不错的起点但我们可以尝试更复杂的模型如随机森林Random Forest或梯度提升树如XGBoost它们通常能捕捉更复杂的非线性关系。6.1 使用随机森林from sklearn.ensemble import RandomForestClassifier rf RandomForestClassifier(n_estimators100, random_state42, max_depth5) rf.fit(X_train_split, y_train_split) y_val_pred_rf rf.predict(X_val_split) val_accuracy_rf accuracy_score(y_val_split, y_val_pred_rf) print(f随机森林验证集准确率: {val_accuracy_rf:.4f}) print(classification_report(y_val_split, y_val_pred_rf))随机森林可能比逻辑回归有轻微提升。我们还可以查看它的特征重要性这与逻辑回归的系数不同是基于树模型计算的特征对减少不纯度的贡献度。rf_importance pd.DataFrame({ feature: selected_columns, importance: rf.feature_importances_ }).sort_values(importance, ascendingFalse) print(rf_importance)6.2 使用交叉验证进行更稳健的评估单次划分的验证集可能因为随机性导致评估不稳定。交叉验证Cross-Validation是更可靠的评估方法。from sklearn.model_selection import cross_val_score # 对逻辑回归进行5折交叉验证 logreg_cv LogisticRegression(max_iter1000, random_state42) cv_scores cross_val_score(logreg_cv, X_train_scaled_full, y_train, cv5, scoringaccuracy) print(f交叉验证准确率: {cv_scores.mean():.4f} (/- {cv_scores.std()*2:.4f}))交叉验证给出的准确率是一个区间能更好地反映模型的平均性能和稳定性。6.3 超参数调优模型的性能很大程度上依赖于超参数如随机森林的n_estimators,max_depth,min_samples_split等。我们可以使用网格搜索GridSearchCV来寻找最优组合。from sklearn.model_selection import GridSearchCV param_grid { n_estimators: [50, 100, 200], max_depth: [3, 5, 7, None], min_samples_split: [2, 5, 10] } rf_for_grid RandomForestClassifier(random_state42) grid_search GridSearchCV(rf_for_grid, param_grid, cv3, scoringaccuracy, n_jobs-1, verbose1) grid_search.fit(X_train_split, y_train_split) print(f最佳参数: {grid_search.best_params_}) print(f最佳交叉验证分数: {grid_search.best_score_:.4f})调优过程可能比较耗时但它能系统性地寻找更优的模型配置。在实际项目中这是提升模型性能的关键一步。7. 回顾、总结与下一步走完这一遍流程你已经完成了一个标准的数据科学微型项目。从数据加载、探索、清洗、特征工程到建模评估每一步都充满了选择与思考。我们看到了性别和阶级对生存率的决定性影响也看到了年龄、家庭规模等因素的复杂作用。通过特征工程我们从姓名、客舱等看似杂乱的字段中挖掘出了新的信息。在建模部分我们建立了一个逻辑回归基线模型并尝试了更强大的树模型。我们使用了验证集和交叉验证来评估模型并提到了超参数调优。最终一个精心处理的泰坦尼克号数据集配合适当的模型达到80%甚至更高的预测准确率是完全可能的。这个项目的价值远不止于一个预测结果。它训练的是你面对数据时的思维方式如何提出假设、如何用可视化验证、如何将领域知识转化为特征、如何严谨地评估模型。这些技能在你未来处理任何数据问题时都至关重要。你可以继续深入的方向还有很多尝试更多的特征组合如票价与舱等的交互、使用更高级的模型如XGBoost, LightGBM、进行更精细的调参、或者将多个模型的结果进行集成投票法、堆叠法。你也可以将同样的流程应用到测试集上生成预测文件提交到Kaggle上看看自己在全球的排名。每一次迭代都是对数据更深层次的理解和对机器学习工具更熟练的掌握。
返回列表