Kaggle-练习赛-Titanic -机器学习 -逻辑回归
我们需要根据训练集已有的数据训练一个模型,从而在缺少基本事实的预测集上判断乘客的存活。
这是一个很显然的二分类任务,传统并且经典的机器学习算法或许值得尝试。
加载数据
使用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左右。
更多推荐



所有评论(0)