当前位置: 首页 > news >正文

泰坦尼克号生存预测三模型实战包:逻辑回归+ID3决策树+随机森林Python完整实现

本文还有配套的精品资源,点击获取

简介:直接运行就能出结果的泰坦尼克号生存预测代码包,含清洗数据的DataProcess.py、逻辑回归LogisticRegression.py、ID3决策树DecisionTree.py、集成调用随机森林的Main.py,以及配套train.csv和test.csv标准Kaggle数据。运行后自动生成LR_submission.csv、DT_submission.csv、RF_submission.csv三个提交文件,所有脚本基于Python 3.x,依赖库在requirements.txt中列明(pandas/scikit-learn/numpy等),说明.md详细写了环境配置、各脚本作用和执行顺序。适合课程设计、大作业快速上手,也方便进阶者替换特征工程、调整超参或改用XGBoost等其他模型。无需修改代码即可完成端到端预测与结果导出。

1. 项目概述:为什么这个“泰坦尼克号三模型包”值得你花30分钟认真读完

如果你正在为《机器学习导论》《数据挖掘》或《人工智能基础》这类课程赶大作业,或者刚学完逻辑回归、决策树、集成学习,手头却连一个能跑通、能出结果、能交上去的完整案例都没有——那你点进来就对了。这不是一个只贴几行代码、配两张截图、最后说“大家自己试试”的敷衍教程;这是一个我带过七届本科生做课程设计后,反复打磨、压测、拆解到每个函数命名都经得起推敲的最小可行教学级实战包。它不炫技,不堆模型,就老老实实把三个最经典、最常考、最容易理解偏差的算法——逻辑回归(LR)、ID3决策树(DT)、随机森林(RF)——用同一套数据、同一套清洗流程、同一套评估口径,从零跑通。关键词里提到的“泰坦尼克预测”“逻辑回归”“ID3决策树”“随机森林”“Python机器学习”,每一个都不是标签,而是你接下来30分钟内会亲手敲、亲手改、亲手看到结果的真实模块。

这个包的核心价值,不在“它能跑”,而在“它为什么这样跑”。比如,为什么DataProcess.py里对Age字段用中位数填充而不是均值?为什么ID3实现没直接调sklearn.tree.DecisionTreeClassifier,而是手写了信息增益计算和递归分裂?为什么Main.py里随机森林的n_estimators设为100而不是50或200?这些不是随意拍脑袋的数字,背后是数据分布特性、算法数学本质、工程实践权衡的综合判断。我试过用均值填Age,结果在验证集上准确率掉0.8%;也试过把ID3换成CART,发现学生在理解“纯度下降”时普遍卡壳;更试过让随机森林只建10棵树,提交Kaggle后Public Score直接从0.78跌到0.74——这些细节,说明.md里不会写,但我会在这里掰开揉碎讲清楚。它适合谁?计算机类专业大三、大四学生,正在准备课程设计或毕业设计初期建模环节;也适合自学Python机器学习、卡在“理论懂了但代码写不出来”阶段的转行者。你不需要先啃完《统计学习方法》,只要会pip install、会运行python script.py,就能拿到三个CSV文件,然后对着Kaggle提交页面点上传,亲眼看到自己的模型在真实排行榜上跑分。更重要的是,它是一块干净的画布:你想加特征交叉?改在DataProcess.py里;想换XGBoost?删掉Main.py里RandomForestClassifier那一行,换成xgb.XGBClassifier;想调参?所有超参都在各脚本顶部集中定义。它不绑架你,只支撑你。下面我们就从整体设计思路开始,一层层剥开这个看似简单、实则处处有讲究的实战包。

2. 整体架构与设计思路:为什么是这三个模型?为什么是这个结构?

2.1 选型逻辑:不是为了堆模型,而是为了建立认知阶梯

很多初学者一上来就想上XGBoost、LightGBM,觉得“高级=好”,结果连逻辑回归的sigmoid函数输出概率是什么意思都没搞清,就去调一堆超参。这个包刻意选择逻辑回归→ID3决策树→随机森林这个序列,是按认知负荷递进设计的。逻辑回归是线性模型的基石,它强迫你思考特征如何加权组合、如何用概率解释预测;ID3是纯粹基于信息论的树模型,没有剪枝、没有基尼不纯度,只有信息增益和递归分裂,让你看清“树是怎么长出来的”;而随机森林则是前两者的集大成者——它用多个ID3(或CART)树投票,天然解决过拟合,又保留了树模型的可解释性优势。这三者放在一起,不是并列关系,而是演进关系:你理解了LR的局限性(无法处理非线性),才会明白DT的价值;你尝到了单棵DT在测试集上波动大的苦头,才真正懂得RF为什么要“随机抽样+随机特征+多数投票”。

提示:包里DecisionTree.py实现的是标准ID3,而非sklearn默认的CART。ID3只支持离散特征、使用信息增益作为分裂准则、不自动剪枝——这些限制恰恰是教学价值所在。它逼你手动处理连续特征(如Age分箱)、手动设定深度限制(max_depth=5),而不是依赖库的黑盒优化。

2.2 目录结构解析:每个文件存在的唯一理由

资源包目录不是随意堆砌,每个文件都承担明确角色,且彼此解耦:

  • train.csv/test.csv:Kaggle官方原始数据,未做任何预处理。这是所有分析的起点,保证复现性。
  • DataProcess.py唯一的数据清洗入口。它不负责建模,只做三件事:缺失值填充(Age用中位数、Embarked用众数)、类别编码(Sex、Embarked映射为数值)、特征缩放(仅对逻辑回归需要的数值特征标准化)、特征构造(如是否独自旅行IsAlone、家庭规模FamilySize)。它输出两个pandas DataFrame:X_train, y_train, X_test,供后续所有模型直接调用。
  • LogisticRegression.py:独立实现逻辑回归训练与预测。核心是梯度下降法(非sklearn的liblinear求解器),手动编写损失函数、梯度计算、参数更新循环。好处是:你能看到权重w如何一步步变化,能打印每轮loss下降曲线,能直观理解“学习率太大导致震荡,太小导致收敛慢”。
  • DecisionTree.py:从零实现ID3算法。关键函数包括calc_entropy()(计算香农熵)、calc_info_gain()(计算信息增益)、build_tree()(递归构建)、predict_sample()(单样本预测)。它不调用任何tree相关库,所有节点分裂逻辑、叶子节点判定(纯度阈值、最小样本数)全部手写。
  • Main.py集成调度中心。它不包含模型逻辑,只做三件事:加载DataProcess输出的数据、分别调用LogisticRegression.py和DecisionTree.py的训练/预测函数、用sklearn.ensemble.RandomForestClassifier训练RF模型(因手写RF工程量过大,此处务实采用成熟库)、统一格式生成三个submission.csv。这种设计让模块职责清晰:数据归DataProcess,算法归各自py,调度归Main。
  • LR_submission.csv/DT_submission.csv/RF_submission.csv:运行后自动生成,格式严格匹配Kaggle要求(PassengerId,Survived),可直接上传。
  • requirements.txt:精确锁定版本:pandas==1.5.3,numpy==1.24.3,scikit-learn==1.2.2。为什么锁版本?因为sklearn 1.3+对DecisionTree的默认参数有调整,会导致ID3实现结果漂移。这是踩过坑后的硬性约束。
  • 说明.md:不是说明书,而是执行地图。它明确写出四步命令:①pip install -r requirements.txt;②python DataProcess.py;③python LogisticRegression.py;④python Main.py。没有多余解释,因为所有解释都在本文展开。

2.3 关键设计取舍:为什么不用Pipeline?为什么不用GridSearch?

有两个常见疑问必须提前回应:第一,为什么不把数据清洗和模型训练封装成sklearn Pipeline?第二,为什么不内置超参搜索(GridSearchCV)?答案很实在:教学场景下,封装是障碍,暴露才是捷径。Pipeline把fit/transform/predict打包成黑盒,学生看不到中间数据形态变化;而本包中,DataProcess.py运行后,你能在控制台直接print(X_train.head()),看到Age已填充、Sex已编码、FamilySize已构造——这种“所见即所得”对建立数据直觉至关重要。同理,GridSearchCV一键扫参很爽,但学生根本不知道它在搜什么、为什么搜这个范围。本包所有超参(如LR的学习率lr=0.01、DT的最大深度max_depth=5、RF的树数量n_estimators=100)都明确定义在脚本顶部,并附带注释说明取值依据:“lr=0.01:经10轮实验,在train loss下降速度与val acc稳定性间取得平衡”、“max_depth=5:防止单棵树过深导致在test.csv上过拟合,实测depth=6时RF线下验证score下降0.015”。这些不是默认值,而是经过实证的“教学最优解”。

3. 核心细节解析与实操要点:从数据清洗到模型落地的每一处关键决策

3.1 DataProcess.py:清洗不是机械操作,而是建模的第一步

数据清洗常被当成“脏活累活”,但在泰坦尼克数据上,每一步清洗都直接影响模型天花板。我们逐行拆解DataProcess.py的核心逻辑:

# Age缺失值:为何用中位数而非均值? age_median = train_df['Age'].median() train_df['Age'].fillna(age_median, inplace=True) test_df['Age'].fillna(age_median, inplace=True) # 注意:test用train的中位数!

这里的关键是训练集与测试集的中位数必须一致。很多初学者直接对test_df单独fillna(test_df[‘Age’].median()),这是严重错误——它泄露了测试集信息。正确做法是:用训练集统计量(中位数)去填充测试集缺失值。为什么选中位数?因为Age分布右偏(大量儿童和老人,中年乘客居多),中位数比均值更能代表典型值。实测对比:用均值填充,LR模型在交叉验证中AUC下降0.023;用中位数,下降仅0.004。

# Embarked缺失值:为何用众数而非删除? embarked_mode = train_df['Embarked'].mode()[0] # mode()返回Series,取第一个值 train_df['Embarked'].fillna(embarked_mode, inplace=True)

Embarked只有2个缺失值,删除会损失信息。众数是S(Southampton),占全量64%,填充S引入的偏差最小。若强行用模型预测填充(如用其他特征训练一个分类器),工程复杂度陡增,对本项目目标无实质提升。

# 特征构造:FamilySize与IsAlone train_df['FamilySize'] = train_df['SibSp'] + train_df['Parch'] + 1 train_df['IsAlone'] = (train_df['FamilySize'] == 1).astype(int)

这是本包最具教学价值的特征工程。原始特征SibSp(兄弟姐妹/配偶数)和Parch(父母/子女数)本身预测力弱,但组合成FamilySize后,呈现明显生存规律:FamilySize=1(独自)生存率仅30%,FamilySize=2~4生存率超50%,FamilySize≥5生存率又降至25%以下。IsAlone是它的二值化表达,对树模型尤其友好。这个构造不是凭空想象,而是先用train_df.groupby(‘FamilySize’)[‘Survived’].mean().plot()画出折线图,观察拐点后确定的。

# 类别编码:为何不用One-Hot而用LabelEncoder? from sklearn.preprocessing import LabelEncoder le_sex = LabelEncoder() train_df['Sex'] = le_sex.fit_transform(train_df['Sex']) # male->1, female->0

对Sex这种二元变量,LabelEncoder足够且更简洁。若用One-Hot会生成Sex_male、Sex_female两列,造成冗余。但对Embarked(S/C/Q三类),本包仍用One-Hot:pd.get_dummies(train_df, columns=['Embarked'], prefix='Embarked'),因为三类变量用LabelEncoder会隐含序数关系(S<C<Q),而实际登船港口无此顺序。这个区别,正是特征编码的底层逻辑。

3.2 LogisticRegression.py:手写梯度下降,看清算法心跳

逻辑回归脚本的核心不是调用sklearn,而是用NumPy手写梯度下降。关键代码段如下:

def sigmoid(z): # 防止溢出:z很大时exp(-z)≈0,z很小时exp(z)≈0 return np.where(z >= 0, 1 / (1 + np.exp(-z)), np.exp(z) / (1 + np.exp(z))) def compute_cost(X, y, theta): m = len(y) h = sigmoid(X @ theta) # 交叉熵损失,加L2正则项(lambda=0.01) cost = (-1/m) * (y.T @ np.log(h + 1e-5) + (1-y).T @ np.log(1-h + 1e-5)) \ + (0.01/(2*m)) * np.sum(theta[1:]**2) # theta[0]是bias,不正则 return cost def gradient_descent(X, y, theta, alpha, num_iters): m = len(y) cost_history = [] for i in range(num_iters): h = sigmoid(X @ theta) gradient = (1/m) * X.T @ (h - y) # L2正则梯度:theta[1:]加lambda*theta[1:]/m gradient[1:] += (0.01/m) * theta[1:] theta = theta - alpha * gradient cost_history.append(compute_cost(X, y, theta)) return theta, cost_history

这里有几个极易忽略但致命的细节:
-sigmoid防溢出:直接写1/(1+np.exp(-z))在z=-800时会因exp(800)溢出为inf。np.where分支处理是工业级写法。
-log防0np.log(h + 1e-5)避免h=0或h=1导致log(0)=-inf。
-正则化范围:bias项theta[0]不参与L2惩罚,这是标准做法,否则会强制截距趋近于0,破坏模型表达能力。
-学习率alpha=0.01:这是经过网格实验的。alpha=0.1时loss震荡不收敛;alpha=0.001时1000轮后loss仍缓慢下降。0.01在收敛速度与稳定性间取得最佳平衡。

运行该脚本后,你会得到cost_history列表,用matplotlib画出来是一条平滑下降曲线——这就是算法在“呼吸”,是你第一次亲眼看到模型如何通过迭代逼近最优解。

3.3 DecisionTree.py:ID3不是伪代码,是可执行的信息论

ID3实现的难点不在算法描述,而在工程细节。DecisionTree.py的build_tree()函数是核心:

def build_tree(data, labels, feature_names, max_depth=5, min_samples_split=2, depth=0): # 递归终止条件1:当前节点样本全属同一类 if len(np.unique(labels)) == 1: return {'type': 'leaf', 'class': labels[0]} # 递归终止条件2:达到最大深度 if depth >= max_depth: return {'type': 'leaf', 'class': np.bincount(labels).argmax()} # 递归终止条件3:样本数不足分裂 if len(labels) < min_samples_split: return {'type': 'leaf', 'class': np.bincount(labels).argmax()} # 寻找最优分裂特征:遍历所有特征,计算信息增益 best_gain = -1 best_feature_idx = None best_threshold = None for i, feature in enumerate(feature_names): # 对数值特征(如Age),尝试所有唯一值作为分割点 if is_numeric(data[:, i]): unique_vals = np.unique(data[:, i]) for val in unique_vals: left_mask = data[:, i] <= val right_mask = ~left_mask if np.sum(left_mask) == 0 or np.sum(right_mask) == 0: continue gain = calc_info_gain(labels, labels[left_mask], labels[right_mask]) if gain > best_gain: best_gain = gain best_feature_idx = i best_threshold = val # 对离散特征(如Sex),直接按类别分裂 else: # 分组计算信息增益... # 若找不到有效分裂,则设为叶子节点 if best_feature_idx is None: return {'type': 'leaf', 'class': np.bincount(labels).argmax()} # 递归构建左右子树 left_data = data[data[:, best_feature_idx] <= best_threshold] left_labels = labels[data[:, best_feature_idx] <= best_threshold] right_data = data[data[:, best_feature_idx] > best_threshold] right_labels = labels[data[:, best_feature_idx] > best_threshold] return { 'type': 'node', 'feature': feature_names[best_feature_idx], 'threshold': best_threshold, 'left': build_tree(left_data, left_labels, feature_names, max_depth, min_samples_split, depth+1), 'right': build_tree(right_data, right_labels, feature_names, max_depth, min_samples_split, depth+1) }

这段代码揭示了ID3的“灵魂”:
-信息增益驱动分裂:不是按规则写死,而是穷举所有可能分裂点,选增益最大的那个。这解释了为什么树长得“不规则”——它完全由数据纯度决定。
-数值特征处理:对Age这类连续特征,ID3需离散化。本包策略是:取该特征所有唯一值作为候选分割点,计算每个点的信息增益。虽非最优(最优是找中位数附近点),但实现简单,教学清晰。
-递归深度控制:max_depth=5是硬性约束。实测表明,depth=3时树太浅,欠拟合;depth=7时在train上acc达92%,但test上骤降至76%,过拟合明显。5是泛化能力拐点。
-叶子节点判定:当无法找到增益>0的分裂时,强制设为叶子,返回众数类别。这比sklearn的min_impurity_decrease参数更易理解。

运行DecisionTree.py后,脚本会打印出树的文本结构(类似if Age<=12: if Sex==0: Survived=1 else: Survived=0 else: ...),你可以对照Kaggle论坛上高分选手的手工分析,验证ID3是否抓住了“女性和儿童优先”的核心规则。

3.4 Main.py:集成不是拼凑,是统一接口下的模型协作

Main.py是整个包的“指挥官”,其精妙在于抽象统一。它定义了一个通用接口:

def train_and_predict(model_name, X_train, y_train, X_test): if model_name == 'LR': from LogisticRegression import train_lr, predict_lr model = train_lr(X_train, y_train) y_pred = predict_lr(X_test, model) elif model_name == 'DT': from DecisionTree import build_tree, predict_tree tree = build_tree(X_train, y_train, feature_names=['Pclass','Sex','Age',...]) y_pred = np.array([predict_tree(tree, x) for x in X_test]) elif model_name == 'RF': from sklearn.ensemble import RandomForestClassifier rf = RandomForestClassifier(n_estimators=100, max_depth=5, random_state=42) rf.fit(X_train, y_train) y_pred = rf.predict(X_test) return y_pred # 统一调用 y_pred_lr = train_and_predict('LR', X_train, y_train, X_test) y_pred_dt = train_and_predict('DT', X_train, y_train, X_test) y_pred_rf = train_and_predict('RF', X_train, y_train, X_test) # 统一输出 for name, pred in zip(['LR', 'DT', 'RF'], [y_pred_lr, y_pred_dt, y_pred_rf]): submission = pd.DataFrame({ 'PassengerId': test_df['PassengerId'], 'Survived': pred.astype(int) }) submission.to_csv(f'{name}_submission.csv', index=False)

这种设计带来三大好处:
-可扩展性:新增模型(如XGBoost)只需在if-elif中加一段,不改动主干逻辑。
-可比性:所有模型用同一份X_train/y_train/X_test,排除数据不一致导致的结果偏差。
-可调试性:你可以在任意位置插入print(f"{model_name} train acc: {accuracy_score(y_train, model.predict(X_train))}"),实时监控各模型在训练集上的表现,快速定位过拟合(如DT train acc=95%, test acc=78%)或欠拟合(如LR train acc=72%)。

4. 实操过程与核心环节实现:从环境配置到Kaggle提交的完整链路

4.1 环境配置:三步到位,拒绝玄学报错

严格按照说明.md执行,但补充关键避坑点:

第一步:创建隔离环境

# 推荐用conda,避免pip全局污染 conda create -n titanic-env python=3.9 conda activate titanic-env

为什么指定python=3.9?因为requirements.txt中sklearn==1.2.2官方只支持Python 3.8-3.11,而3.9是该版本最稳定的发行版。用3.12可能触发ImportError: cannot import name 'xxx' from 'sklearn.xxx'

第二步:安装依赖

pip install -r requirements.txt

注意:如果国内网络慢,可临时换源:

pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/

但切勿用--trusted-host跳过证书验证,这可能导致安装恶意包。

第三步:验证安装

python -c "import pandas as pd; import numpy as np; from sklearn.ensemble import RandomForestClassifier; print('All libs loaded successfully')"

输出All libs loaded successfully即成功。若报错ModuleNotFoundError: No module named 'sklearn',大概率是conda环境没激活,或pip装到了base环境。

提示:.gitignore文件已预置,确保你不会误提交虚拟环境或__pycache__。.inscode是VS Code工作区配置,启用Python linting和格式化,新手可直接双击打开。

4.2 数据清洗实操:DataProcess.py运行日志解读

运行python DataProcess.py后,控制台输出如下:

[INFO] Loading train.csv and test.csv... [INFO] Train set shape: (891, 12), Test set shape: (418, 11) [INFO] Filling missing Age with median: 28.0 [INFO] Filling missing Embarked with mode: S [INFO] Constructing FamilySize and IsAlone features... [INFO] Encoding categorical features: Sex, Embarked... [INFO] Standardizing numerical features: Age, Fare... [INFO] Saving processed data to data/processed/...

关键信息解读:
-Train set shape: (891, 12):Kaggle原始train.csv共891行,12列(含Survived标签)。若你看到(890, 12),说明某行被意外删除,需检查DataProcess.py中是否有dropna()误用。
-Filling missing Age with median: 28.0:确认中位数是28.0,若显示27.5或29.0,说明数据加载有误(如csv编码问题)。
-Standardizing numerical features:仅对Age和Fare标准化(减均值除标准差),Pclass等有序类别变量不标准化,因为ID3不依赖距离度量。

运行后,data/processed/目录下生成X_train.npy,y_train.npy,X_test.npy三个文件。你可以用np.load('data/processed/X_train.npy')加载,print(X_train.shape)应输出(891, 10)——10是最终特征维度(Pclass, Sex, Age, SibSp, Parch, Fare, Embarked_S, Embarked_C, Embarked_Q, IsAlone)。

4.3 模型训练与预测:各脚本输出详解

运行python LogisticRegression.py

[INFO] Training Logistic Regression with 1000 iterations... [INFO] Final training loss: 0.427 [INFO] Training accuracy: 0.798 [INFO] Predicting on test set... [INFO] LR_submission.csv generated successfully!
  • Final training loss: 0.427:交叉熵损失,越低越好。若>0.5,检查sigmoid是否防溢出、学习率是否过大。
  • Training accuracy: 0.798:在训练集上准确率79.8%,合理范围(80%±2%)。若<75%,可能是特征未标准化或正则化过强。

运行python Main.py

[INFO] Training DT... [INFO] DT train acc: 0.923 [INFO] DT test acc (estimated): 0.812 [INFO] Training RF... [INFO] RF train acc: 0.956 [INFO] RF test acc (estimated): 0.835 [INFO] All submissions generated: LR_submission.csv, DT_submission.csv, RF_submission.csv
  • DT train acc: 0.923vsRF train acc: 0.956:单棵树92.3%,随机森林95.6%,证明集成有效提升拟合能力。
  • DT test acc (estimated): 0.812:这是用5折交叉验证在train.csv上估算的,非真实test.csv结果。真实test.csv无标签,只能提交Kaggle看分。

4.4 Kaggle提交与结果分析:三个CSV的真实战斗力

将生成的三个CSV上传至Kaggle Titanic比赛页面(https://www.kaggle.com/c/titanic/submit),约30秒后获得分数:

ModelPublic ScoreKey Insight
LR0.77990线性模型稳定,但无法捕捉Age与Pclass的交互效应(如头等舱老年乘客生存率高于三等舱青年乘客)
DT0.76555单棵树过拟合,对测试集噪声敏感;但规则清晰,可导出if Age<12: Survived=1等业务规则
RF0.79425集成显著提升,方差降低;Public Score比DT高2.87个百分点,验证了“三个臭皮匠顶个诸葛亮”

注意:Kaggle Public Score基于部分测试集(约50%),Private Score(最终排名)基于全部测试集。本包目标是Public Score≥0.78,RF达到0.794已属优秀课程设计水平。

5. 常见问题与排查技巧实录:那些让我熬夜调试的坑,现在都给你标好了

5.1 典型问题速查表

问题现象可能原因排查命令解决方案
ValueError: Input contains NaNDataProcess.py未填完缺失值python -c "import numpy as np; print(np.isnan(np.load('data/processed/X_train.npy')).sum())"检查DataProcess.py中fillna()是否漏掉某列,或test_df用了自己的中位数
ModuleNotFoundError: No module named 'LogisticRegression'Python路径问题,未在包根目录运行pwd确认当前路径;echo $PYTHONPATH检查路径必须在包根目录(含所有.py文件的目录)下运行命令,不要进入子文件夹
LR_submission.csv中Survived列为浮点数(如1.0)而非整数(1)predict_lr返回float数组python -c "import pandas as pd; d=pd.read_csv('LR_submission.csv'); print(d.dtypes)"修改LogisticRegression.py中return (h >= 0.5).astype(int),确保astype(int)
DT_submission.csv提交后Score为0.00000预测结果全为0或全为1python -c "import pandas as pd; d=pd.read_csv('DT_submission.csv'); print(d['Survived'].value_counts())"检查DecisionTree.py中predict_tree()是否正确递归,或build_tree()终止条件写错(如len(labels) < 2应为< min_samples_split
RandomForestClassifier not foundsklearn版本不符python -c "import sklearn; print(sklearn.__version__)"严格按requirements.txt安装,pip install scikit-learn==1.2.2

5.2 进阶调试技巧:如何让模型效果再提1-2个百分点

这不是“玄学调参”,而是基于泰坦尼克数据特性的实证技巧:

技巧1:Age分箱优于连续值(对DT/RF)
原始DataProcess.py中Age是连续数值,但ID3对连续特征需遍历所有值,效率低且易过拟合。改为分箱:

# 在DataProcess.py中替换Age处理 train_df['AgeBand'] = pd.cut(train_df['Age'], 5, labels=[0,1,2,3,4]) test_df['AgeBand'] = pd.cut(test_df['Age'], 5, labels=[0,1,2,3,4]) # 然后删除原Age列,用AgeBand作为特征

实测:DT Public Score从0.765升至0.779,因为分箱后信息增益计算更鲁棒。

技巧2:Fare对数变换(对LR)
Fare分布极度右偏(头等舱票价可达500,三等舱仅5),直接标准化效果差。添加:

# 在DataProcess.py中,标准化前 train_df['Fare'] = np.log1p(train_df['Fare']) # log1p(x) = log(1+x),防0 test_df['Fare'] = np.log1p(test_df['Fare'])

实测:LR Public Score从0.779升至0.785,因对数变换使分布更接近正态,利于线性模型。

技巧3:特征交叉(对RF)
构造Pclass×Sex交叉特征:

train_df['Pclass_Sex'] = train_df['Pclass'].astype(str) + '_' + train_df['Sex'].astype(str) # 然后One-Hot编码

实测:RF Public Score从0.794升至0.802,因为捕获了“头等舱女性生存率极高,三等舱男性生存率极低”的强交互模式。

5.3 课程设计答辩高频问题预演

如果你要用这个包做课程设计答辩,老师必问以下问题,答案已为你准备好:

Q:为什么ID3不用sklearn而要手写?
A:因为sklearn的DecisionTreeClassifier默认是CART算法,使用基尼不纯度且支持剪枝,而ID3是教学经典,只用信息增益、不剪枝、强制离散化。手写能让我们彻底理解“纯度下降”如何驱动树生长,这是理解所有树模型的基石。

Q:逻辑回归加了L2正则,λ=0.01怎么确定的?
A:我做了网格搜索:λ取[0.001, 0.01, 0.1, 1],在5折交叉验证上评估。λ=0.001时train acc=0.812但val acc=0.785,过拟合;λ=0.1时train/val acc均降至0.76左右,欠拟合;λ=0.01时val acc最高达0.791,故选定。

Q:随机森林100棵树,是越多越好吗?
A:不是。我测试了n_estimators=[10,50,100,200],Public Score分别为0.772、0.789、0.794、0.795。从100到200仅提升0.001,但训练时间翻倍。课程设计追求性价比,100是工程与效果的平衡点。

Q:这个包能直接用于Kaggle竞赛拿奖吗?
A:不能,但它是绝佳起点。Kaggle高分方案通常包含:更复杂的特征工程(如姓名Title提取Mr/Mrs/Miss)、集成多个模型(LR+DT+RF+XGB)、高级调参(Bayesian Optimization)。本包的目标是让你先跑通、理解、再超越。

6. 后续拓展建议:从课程设计到真实项目的跃迁路径

这个包不是终点,而是你机器学习旅程的“第一个稳固锚点”。基于它,你可以向三个方向自然延伸,每一步都保持代码复用性:

方向一:深化特征工程(1天可完成)
- 替换DataProcess.py中的特征构造逻辑,加入:
-Title提取:train_df['Name'].str.extract(' ([A-Za-z]+)\.', expand=False)→ 得到Mr, Mrs, Miss, Master等,Master(男孩)生存率高达58%,远超平均38%。
-Cabin首字母:train_df['Cabin'].str[0]→ A/B/C等甲板位置,与生存强相关。
- 所有新特征都通过pd.get_dummies()编码,无缝接入现有X_train。

方向二:升级模型栈(2天可完成)
- 在Main.py中新增XGBoost支持:
python elif model_name == 'XGB': from xgboost import XGBClassifier xgb = XGBClassifier(n_estimators=200, max_depth=4, learning_rate=0.1, random_state=42) xgb.fit(X_train, y_train) y_pred = xgb.predict(X_test)
- 要求:pip install xgboost,并在requirements.txt中添加。XGBoost在本数据上Public Score可达0.815+,是质的飞跃。

方向三:构建端到端Pipeline(3天可完成)
- 将DataProcess.py、各模型脚本封装为sklearn Pipeline:
python from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler pipeline = Pipeline([ ('preprocessor', CustomPreprocessor()), # 封装DataProcess逻辑 ('classifier', LogisticRegression()) ]) pipeline.fit(X_raw_train, y_train) # 输入原始df,自动清洗+建模
- 这是工业界标准做法,让你的代码具备生产环境部署潜力。

我个人在实际带学生做毕设时发现,90%的学生卡在“不知道下一步做什么”。这个包的设计哲学就是:每一步都给出明确出口。当你跑通RF_submission.csv并看到0.794的分数时,那种“我做到了”的实感,比任何理论讲解都更有力量。接下来,无论是加一个Title特征,还是换一个XGBoost模型,你都不再是盲目摸索,而是带着清晰的问题意识——“我想解决什么?这个改动如何影响信息增益/损失函数/特征重要性?”——这才是机器学习真正的入门。最后分享一个小技巧:每次修改代码后,先用python -m py_compile *.py检查语法,再运行,能省下80%的调试时间。祝你代码一次过,提交稳上榜。

本文还有配套的精品资源,点击获取

简介:直接运行就能出结果的泰坦尼克号生存预测代码包,含清洗数据的DataProcess.py、逻辑回归LogisticRegression.py、ID3决策树DecisionTree.py、集成调用随机森林的Main.py,以及配套train.csv和test.csv标准Kaggle数据。运行后自动生成LR_submission.csv、DT_submission.csv、RF_submission.csv三个提交文件,所有脚本基于Python 3.x,依赖库在requirements.txt中列明(pandas/scikit-learn/numpy等),说明.md详细写了环境配置、各脚本作用和执行顺序。适合课程设计、大作业快速上手,也方便进阶者替换特征工程、调整超参或改用XGBoost等其他模型。无需修改代码即可完成端到端预测与结果导出。


本文还有配套的精品资源,点击获取

http://www.jsqmd.com/news/952032/

相关文章:

  • 别再只调API了!用Keras从零复现Facenet人脸识别模型(附完整代码与CASIA-WebFace数据集处理)
  • 期货量化 wait_update 超时怎么办:天勤 TqTimeoutError 分级处理
  • 避坑指南:STM32低功耗停止模式唤醒后时钟配置的那些事儿
  • 列车轮对几何参数在线检测关键技术解析【附数据】
  • C++ 编码规范
  • 2026年大客户营销咨询选购指南,品牌排名 - mypinpai
  • 别再死记硬背!一张图+一个故事帮你理清正交、酉、正规矩阵的关系与区别
  • Zotero PDF预览插件:让文献浏览告别窗口切换的困扰
  • Transformer QKV 计算瓶颈?一次关于长上下文显存爆炸的硬核排查与优化
  • AI简历不是“加个ChatGPT”,而是重构求职链路——12个企业级落地案例拆解
  • 2026年深圳全屋定制一站式服务避坑 别被假工厂全流程忽悠了 - 产品测评官
  • 智能担保系统架构设计全图解(含LLM+规则引擎双模决策链路)
  • 别再死记硬背了!用Multisim/PSpice仿真带你直观理解PFC的三种工作模式(CCM/DCM/CrM)
  • PPTist:5分钟打造专业演示文稿的终极免费在线PPT制作工具
  • Mac窗口置顶神器Topit:如何让重要窗口永远在最前方
  • 紧急预警:标注数据漂移正 silently 毁掉你的模型效果!——用AI工具构建动态标注质量监控仪表盘(Python+Prometheus实战)
  • CentOS 7生产环境PHP 8.1安装避坑实录:Remi源、扩展冲突与SELinux策略
  • ov5647摄像头模块、MIPI的MCLK主时钟
  • 2026年酒泉驾考驾校价格比较:新亿阳驾校性价比高吗? - mypinpai
  • 从开关电源到第三代半导体:聊聊PFC技术这几十年的‘进化史’
  • Python 爬虫进阶技巧:自定义请求头编码适配多国语言网页爬取
  • 3步掌握iOS虚拟定位:iFakeLocation完全指南
  • 教育AI整合进入“深水区”:2024Q2行业报告显示,仅17%机构实现L1-L4能力跃迁——你的团队处在哪一级?
  • 2026运城市权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
  • 你的 AI 编程工具,每次请求都在干嘛?这个开源项目帮你分析得明明白白
  • 【字节跳动】巨量引擎五层创世内核全套终极封存码:ADOS-FIVE-GOD-ALL-7342-JN
  • 量化程序如何同时支持回测、模拟盘和实盘
  • Prompt工程入门:让AI按你的要求工作(1)--prompt概述与设计
  • 2026年硅胶密封圈供应商排名,哪家口碑好 - mypinpai
  • AI内容工作流会成为品牌基础设施