M现代统计模型/Titanic
返回课件Python实验室 ↗
课后阅读与复现

补充材料

围绕同一个逻辑回归案例,补充变量含义、预处理、验证与代码。

A1 数据字典与信息边界

本课响应变量为Survived。下表以衍生基准模型为起点;进阶方案另用分组年龄、FareLog、Deck、FamilyBand与明确的交互列。

字段含义课堂处理
PassengerId乘客记录标识对齐记录,不作为本课预测特征
Survived0遇难,1生还响应变量
Pclass舱位等级1、2、3按类别编码
Sex性别按类别编码
Age年龄,可缺失基准用训练折中位数;可比较Sex×Pclass分组与回退
SibSp同行兄弟姐妹或配偶数构造FamilySize
Parch同行父母或子女数构造FamilySize
Fare票价数值特征;本课不假定它必然等于单人的票价
Cabin船舱记录,可缺失基准用HasCabin;进阶以Deck替换
Embarked登船港口S、C、Q训练部分众数填补后编码
Name姓名文本提取头衔Title,使用固定的合并规则
Ticket票号不进入默认生还模型;候选频数在训练侧学习,并用于分组验证

HasCabin只表示记录有无;FamilySize由已记录的同行亲属数构造。数据中的关联不能自动解释为因果效应。

A2 怎样选择缺失值策略

中位数填补简单、可解释,适合作为起点。删除记录、分组填补与模型填补各有条件,不能仅凭方法更复杂就认定预测更好。

策略需要考虑的问题
删除缺失记录剩余样本是否还能代表目标群体?样本量会损失多少?
中位数或众数填补规则是否仅从训练部分学习?填补是否掩盖了缺失模式?
分组或模型填补能否在每个训练折内独立拟合?下游预测是否确有改善?
缺失指示变量缺失本身是否有预测信息?这种记录机制将来是否仍存在?

单次填补没有恢复真实的未知值,也通常没有传播填补不确定性。若任务重点是统计推断,可能还需要多重填补等方法,并检查缺失机制与分析目标。

A3 独热编码与参考类别

对港口使用0、1、2作为一个连续预测变量,会让逻辑回归假定相同的编码增量对应相同的线性评分变化。独热编码允许各类别相对参考类别具有独立效应。

港口是否C是否Q
S 参考类别00
C10
Q01

系数解释须同时说明参考类别与其他纳入模型的变量。数值变量经过标准化后,增加1单位对应增加一个训练部分的标准差。相关特征、编码和正则化都会影响系数,不能把绝对值直接当作通用重要性。

A4 从似然到正则化

在常用的条件独立建模下,逻辑回归将每名乘客真实结果的概率相乘。最大化似然,也可转化为最小化负对数似然,即二分类对数损失。

−∑i [yi log pi + (1 − yi) log(1 − pi)]

L2正则化对系数大小加入惩罚,限制过度复杂的估计。它不保证每次都提高预测,也不能替代样本外验证。本课使用带L2正则化的逻辑回归,数值特征先标准化。进阶方案使用Female×Class2与Female×Class3,并保留Sex与Pclass主效应,不额外加入六类SexClass。

同一似然函数中的系数,不是概率的百分点变化。二元特征由0变为1时,exp(β)表示其他模型变量相同条件下的优势比。

A5 划分方式怎样匹配预测对象

预测目标划分重点例子
同一总体中的新个体在样本近似可交换的条件下使用随机或分层划分本课分层五折演示
全新客户或家庭同一群组的记录不要跨入训练和验证按客户、家庭或票号分组
未来时间尊重时间顺序与预测时可用信息用过去训练,向未来验证

Titanic存在家庭与同行组关联。本课分层五折用于展示验证流程;若目标是对全新家庭进行外推,应进一步采用匹配该目标的分组验证。对同一批数据反复改变随机划分的结果,也不能当作彼此独立的实验。

五折均值和折间标准差是一种描述;它们不能直接构成模型泛化能力的95%置信区间。反复根据同一验证结果选择特征、参数或阈值,还会产生选择偏差。

打开16单元可运行Python实验室 ↗ · 下载完整Notebook与数据包 ↓

A6 最小复现代码与数据

解压完整下载包,将训练数据、course_model.py与validation-folds.csv放在同一目录。下面的流程在每个训练折内拟合填补、编码、缩放与模型。

下载训练数据
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler, FunctionTransformer
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from course_model import course_splits

df = pd.read_csv("train.csv")

def features(x):
    x = x.copy()
    x["FamilySize"] = x["SibSp"] + x["Parch"] + 1
    x["HasCabin"] = x["Cabin"].notna().astype(int)
    title = x["Name"].str.extract(r"([A-Za-z]+)\.", expand=False)
    title = title.replace({"Mlle": "Miss", "Ms": "Miss", "Mme": "Mrs"})
    x["Title"] = title.where(title.isin(["Mr", "Miss", "Mrs", "Master"]), "Rare")
    return x

numeric = ["Age", "Fare", "FamilySize", "HasCabin"]
categorical = ["Pclass", "Sex", "Embarked", "Title"]
preprocess = ColumnTransformer([
    ("num", Pipeline([
        ("fill", SimpleImputer(strategy="median")),
        ("scale", StandardScaler())
    ]), numeric),
    ("cat", Pipeline([
        ("fill", SimpleImputer(strategy="most_frequent")),
        ("encode", OneHotEncoder(drop="first", handle_unknown="ignore"))
    ]), categorical)
])
model = Pipeline([
    ("features", FunctionTransformer(features)),
    ("preprocess", preprocess),
    ("logit", LogisticRegression(max_iter=2000))
])
cv = course_splits(df)  # 按PassengerId复用已发布的折编号
scores = cross_val_score(model, df.drop(columns="Survived"), df["Survived"],
                         cv=cv, scoring="accuracy")
print("各折准确率:", scores)
print("平均准确率:", scores.mean())
print("折间标准差:", scores.std())

课堂参考结果:平均准确率约83.05%,折间标准差约1.32个百分点。不同软件版本与数值求解条件下,结果可能有小幅差异。

验证划分由validation-folds.csv固定,并按PassengerId对齐。环境与数据版本记录参考环境、浏览器环境及校验值。重新独立生成分组划分可能产生不同分配;本课默认计算共同复用这份划分。

本地安装与运行说明 · Kaggle原始数据说明