我们需要根据训练集已有的数据训练一个模型,从而在缺少基本事实的预测集上判断乘客的存活。

这是一个很显然的二分类任务,传统并且经典的机器学习算法或许值得尝试。

加载数据

使用pandas读取训练集文件(CSV)。pandas还可以方便的读取Excel、Json、Html、Txt等类型的文件。

import numpy as np
import pandas as pd
import os

train_df = pd.read_csv("/kaggle/input/titanic/train.csv")
test_df = pd.read_csv("/kaggle/input/titanic/test.csv")

Kaggle Titanic数据集通常包含训练集(train.csv)和测试集(test.csv),我们首先对数据集进行查看。

print(train_df.shape)
print("\n训练集缺失值统计:")
print(train_df.isnull().sum())
print("\n测试集缺失值统计:")
print(test_df.isnull().sum())
train_df.head(5)

通过简单的查看数据集信息,发现数据存在大量缺失。
其次,查看训练集前5项数据,结合竞赛数据介绍中的内容对数据集进行分析。
* PassengerId 需要在提交预测结果时使用,保留。
* Survived 幸存与否
* Pcalss 车票等级--一定程度想着象征着乘客的社会地位与财富多少
* Name-模型处理中用处不大,但或许能从中提取一些信息
* Sex  性别也许会影响幸存与否
* Age 年龄缺失很多,应该去除,单考虑到年龄是重要影响因素,或许可以从其他信息获取一些相关内容以进行数据填充
* sliSp Parch,无缺失,尽量利用
* Ticket 或许这个应该去除
* fare 与Pclass 存在交叉信息。
* cabin 缺失太多,去除
* Embarked 少量缺失,填充。

为统一进行处理,将训练集和测试集拼接到一起:

#合并train-test,统一处理后再分开
test_df["Survived"] = np.nan  # 测试集存活标签设为NaN,方便train-test后期再分开
combined_df = pd.concat([train_df, test_df], ignore_index=True)
print("合并后数据形状:", combined_df.shape)  # (1309, 12),共1309个样本

数据处理:

#处理缺失值
## 1、 Age(年龄):用"头衔"分组填充中位数(更合理,如"Master"多为儿童,"Mr"多为成年人)
# 从Name中提取头衔(如Mr.、Mrs.、Miss.、Master.)
combined_df["Title"] = combined_df["Name"].str.extract(r"([A-Za-z]+)\.")  # 正则提取"."前的头衔
# 合并小众头衔(减少类别数)
rare_titles = ["Dona", "Lady", "Countess", "Capt", "Col", "Don", "Dr", "Major", "Rev", "Sir", "Jonkheer"]
combined_df["Title"] = combined_df["Title"].replace(rare_titles, "Rare")
combined_df["Title"] = combined_df["Title"].replace("Mlle", "Miss")  # Mlle=Miss
combined_df["Title"] = combined_df["Title"].replace("Ms", "Miss")    # Ms=Miss
combined_df["Title"] = combined_df["Title"].replace("Mme", "Mrs")    # Mme=Mrs

#按Title分组填充Age缺失值
age_median = combined_df.groupby("Title")["Age"].median()
for title in combined_df["Title"].unique():
    combined_df.loc[(combined_df["Age"].isnull()) & (combined_df["Title"] == title), "Age"] = age_median[title]

#2、 Fare(船票价格):测试集1个缺失,用同Pclass的中位数填充
combined_df["Fare"].fillna(combined_df.groupby("Pclass")["Fare"].median()[3], inplace=True)  # 缺失值在Pclass=3

#3、 Embarked(登船港口):训练集2个缺失,用最频繁值(S)填充
combined_df["Embarked"].fillna(combined_df["Embarked"].mode()[0], inplace=True)
drop_cols = [ "Name", "Ticket", "Cabin", "Title"]  # Title已用于填充Age,无需保留
combined_df = combined_df.drop(columns=drop_cols)


# 组合新特征

## 1 FamilySize(家庭规模):SibSp + Parch + 1(自己)
combined_df["FamilySize"] = combined_df["SibSp"] + combined_df["Parch"] + 1
## 2 IsAlone(是否独自旅行):FamilySize=1→1,否则0
combined_df["IsAlone"] = 1
combined_df.loc[combined_df["FamilySize"] > 1, "IsAlone"] = 0

数据处理完成后,将训练集和测试集重新分割:

# 拆分回训练集和测试集(根据Survived是否为NaN)
train_processed = combined_df[combined_df["Survived"].notna()].copy()
test_processed = combined_df[combined_df["Survived"].isna()].copy()

使用逻辑回归实现预测:

1、导入需要用到的库:

# 导入库
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, roc_auc_score

2、设定逻辑回归需要的变量:X-Y

# 分离特征(X)和目标变量(y)
X = train_processed.drop(columns=["Survived","PassengerId"])
y = train_processed["Survived"].astype(int)  # 转为整数型(避免浮点警告)
test_X = test_processed.drop(columns=["Survived","PassengerId"])  # 测试集特征

print("\n处理后训练集特征形状:", X.shape)  # (891, 9),9个有效特征
print("处理后测试集特征形状:", test_X.shape)  # (418, 9),与训练集特征数一致

3、划分数据集,方便评估模型

# 1. 划分训练集和验证集(用于评估模型)
X_train, X_val, y_train, y_val = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y  # stratify=y:保持验证集与原数据存活比例一致
)

4、定义特征类型

#定义特征类型(区分数值型和分类型)
numeric_features = ["Age", "Fare", "SibSp", "Parch", "FamilySize"]  # 数值型特征
categorical_features = ["Sex", "Pclass", "Embarked", "IsAlone"]  # 分类型特征

5、对数值特征进行标准化;对分类特征使用One-Hot Encoding 进行处理

#定义预处理步骤
## 数值型特征:标准化(逻辑回归对特征尺度敏感)
numeric_transformer = Pipeline(steps=[
    ("scaler", StandardScaler())
])

## 分类型特征:独热编码(One-Hot Encoding,处理无顺序的分类特征)
categorical_transformer = Pipeline(steps=[
    ("onehot", OneHotEncoder(drop="first", sparse=False))  # 将sparse_output改为sparse
])

preprocessor = ColumnTransformer(
    transformers=[
        ("num", numeric_transformer, numeric_features),
        ("cat", categorical_transformer, categorical_features)
    ])

6、使用 pipeline 构建逻辑回归模型
 

#构建逻辑回归模型管道
logreg_pipeline = Pipeline(steps=[
    ("preprocessor", preprocessor),
    ("classifier", LogisticRegression(random_state=42, max_iter=1000))
])

模型训练与评估

logreg_pipeline.fit(X_train, y_train)



#验证集预测与评估
y_val_pred = logreg_pipeline.predict(X_val)
y_val_proba = logreg_pipeline.predict_proba(X_val)[:, 1]  # 预测存活概率(正类概率)

#输出评估指标
print("=== 逻辑回归模型验证集评估结果 ===")
print(f"准确率(Accuracy):{accuracy_score(y_val, y_val_pred):.4f}")
print(f"ROC-AUC 分数:{roc_auc_score(y_val, y_val_proba):.4f}")
print("\n混淆矩阵:")
print(confusion_matrix(y_val, y_val_pred))
print("\n分类报告(精确率、召回率、F1分数):")
print(classification_report(y_val, y_val_pred))

#交叉验证(更稳健的评估)
cv_scores = cross_val_score(logreg_pipeline, X, y, cv=5, scoring="accuracy")
print(f"\n5折交叉验证平均准确率:{cv_scores.mean():.4f}(标准差:{cv_scores.std():.4f})")

预测提交:

# 1. 用全量训练集重新训练模型(前一部分训练,为了评估模型对训练集Train进行了划分)
logreg_pipeline.fit(X, y)

# 2. 测试集预测(预测存活标签)
test_y_pred = logreg_pipeline.predict(test_X)

# 3. 生成提交文件(按Kaggle要求格式:PassengerId + Survived)
submission = pd.DataFrame({
    "PassengerId": test_df["PassengerId"],  
    "Survived": test_y_pred.astype(int)     # 预测结果转为整数
})

# 4. 保存提交文件
submission.to_csv("titanic_logreg_submission.csv", index=False)
print("\n提交文件已生成!前5行:")
print(submission.head())

受限于线性模型本质和特征深度,逻辑回归模型未能挖掘更复杂的存活模式。实际提交预测准确率在0.75-0.80左右。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐