跳转到内容

3:多层感知机实战

机器学习Banner

经过理论部分的学习,你已经了解了 MLP 的基本结构和训练原理。这一节,你要面对一个真实的分类任务——用 MLP 预测心脏病。和造轮子不同,真实任务的第一道门槛往往不是模型本身,而是数据


在动手之前,请先搞清楚以下问题。它们是你在实际项目中绕不过去的坎。

真实数据中,特征往往不是纯数值的。比如性别(男/女)、胸痛类型(TA/ATA/NAP/ASY)。

  • 什么是独热编码(One-Hot Encoding)? 写出一个具体例子(假设某特征有 3 个类别,编码后的矩阵是什么样的)。
  • 什么是标签编码(Label Encoding)? 它和独热编码有什么区别?
  • 对于神经网络,哪种编码方式更常用? 为什么?(提示:想想数值大小关系和梯度的关系)

看看下面两个特征:

  • Age:在 30~80 之间
  • Cholesterol:在 100~600 之间

它们被直接喂进 MLP,会发生什么?

  • 为什么 MLP 对输入特征的尺度敏感?(提示:从梯度下降的角度思考)
  • Z-Score 标准化(StandardScaler)和 Min-Max 归一化分别是什么?公式是什么?
  • 训练集上 fit 了一个 StandardScaler 后,测试集上的 transform 应该用什么?能重新 fit 一次吗?为什么?
  • 训练集(Train)、验证集(Validation)、测试集(Test)各自的用途是什么?
  • 为什么不能拿测试集来调参? 用训练集做验证会有什么问题?
  • 如果原始数据只有一个 train.csv,你如何获得验证集?
  • 准确率(Accuracy)在类别不均衡时会有什么问题? 举一个极端的例子。
  • 精确率(Precision)、召回率(Recall)、F1-Score 分别衡量什么?公式是什么?
  • 混淆矩阵(Confusion Matrix) 的四格分别代表什么?
  • ROC 曲线和 AUC 分别衡量什么?
  • 为什么用 Mini-Batch 而不是一次喂全部数据(Batch GD)或者一次喂一条(SGD)?
  • PyTorch 中 DataLoaderbatch_sizeshuffle 参数分别起什么作用?训练和验证时 shuffle 应该一样吗?

📥 数据文件请到 QQ 群下载 heart-disease-prediction-buaa-2026 文件夹。

心血管疾病是全球死亡率最高的疾病之一。本数据集整合了多个心脏病研究机构的临床记录,包含 11 个特征,目标是预测患者是否患有心脏病。

文件说明
train.csv训练集,819 条记录,含标签列 HeartDisease
test.csv测试集,100 条记录,不含标签
example_submission.csv提交格式示例,两列:id + HeartDisease
列名类型说明取值范围
Age数值年龄
Sex类别性别M, F
ChestPainType类别胸痛类型TA, ATA, NAP, ASY
RestingBP数值静息血压mm Hg
Cholesterol数值血清胆固醇mm/dl
FastingBS类别空腹血糖 > 120 mg/dl0, 1
RestingECG类别静息心电图Normal, ST, LVH
MaxHR数值最大心率60~202
ExerciseAngina类别运动诱发心绞痛Y, N
Oldpeak数值ST 段抑制数值
ST_Slope类别ST 段斜率Up, Flat, Down
HeartDisease标签1=心脏病,0=正常0, 1

也是几乎所有深度学习任务的基本流程。

  1. 加载数据,进行探索性数据分析(EDA)——至少看看各类别的样本分布、各特征的统计信息
  2. 数据预处理:类别特征编码、数值特征标准化、划分训练/验证集
  3. 搭建 MLP 模型(具体结构见下方核心任务)
  4. 训练模型,记录训练/验证损失和准确率
  5. 评估与可视化:绘制损失曲线和混淆矩阵
  6. 对测试集进行预测,生成符合 example_submission.csv 格式的提交文件

class HeartDiseaseClassifier(nn.Module):
def __init__(self, input_size):
super(HeartDiseaseClassifier, self).__init__()
# TODO: 定义网络层
# 建议:2~3 个隐藏层,配合 BatchNorm 和 Dropout
def forward(self, x):
# TODO: 前向传播
def train(model, train_loader, val_loader, epochs, lr):
# TODO: 训练循环
# 完成模型训练,并在每个 epoch 后评估验证集准确率

  • 推荐用 pandas 读取 CSV,用 sklearn.preprocessing 中的 StandardScalerOneHotEncoderLabelEncoder 做预处理
  • 类别特征编码后用 np.hstackpd.concat 拼回特征矩阵
  • 别忘了处理 train.csvtest.csv 时用同一套编码器(train 上 fit,test 上只 transform)
  • 819 条数据偏少,建议划分 10%~20% 作验证集

  1. 数据预处理中,你采用了什么方式处理类别特征?尝试对比 Label Encoding 和 One-Hot Encoding 对模型效果的影响。
  2. 819 条数据对于 MLP 来说是偏少的。你在训练过程中观察到了过拟合现象吗?你是如何缓解的?(Dropout?权重衰减?早停?)
  3. 查看特征重要性:如果让你删掉一个特征,你会删哪个?为什么?有没有什么方法可以定量评估特征的重要性?

报告需包含以下内容:

  1. 数据探索:样本分布、特征统计、类别平衡情况
  2. 预处理方案:编码方式和标准化方式的说明
  3. 模型结构:网络层数、神经元数、使用的正则化手段,并说明设计理由
  4. 训练过程:超参数设置、损失/准确率曲线、最终验证集结果
  5. 改进策略:尝试了哪些改进方法?效果如何?
  6. 收获与反思

  1. 手写核心代码:模型定义和训练循环必须自己写,不能直接使用 AI 生成
  2. 代码注释:每个关键步骤需要添加注释说明其作用
  3. 实验记录:记录不同超参数设置的实验结果,分析其影响
  4. 推荐使用 matplotlib 进行可视化,有条件的可以使用 GPU 训练

  • 代码文件

    将代码整合到 .ipynb 文件中,命名格式:ml-3-姓名-学号.ipynb

  • 文档报告

    将 Part 1 和 Part 6 的回答以及 Part 7 的报告写入 .md 文件,命名格式:ml-3-姓名-学号.md

  • 将两个文件压缩为 ml-3-姓名-学号.zip 提交

  • 邮箱: gimmerml401@163.com

  • 主题: 3-姓名-学号

出题人:出题人头像  Taffy

QQ:2078306188

邮箱:2078306188@qq.com