项目一教学文档:房价预测 ------ 从基准模型到集成
https://gitee.com/ghaweiuptgb/machine-learning-AI.git (代码包)
使用说明 :本文档是项目一的完整教学记录 。每完成一个步骤,我会把该步骤的详细教学过程(讲解、代码解读、概念、动手任务、验收标准、参考答案)写入对应章节。你可以按章节自学,也可以在对话中让我带你做,做完后回来对照本文档复习。
配套文件:
- 总体规划见
[../机器学习实战学习路线.md](../机器学习实战学习路线.md)- 你的个人笔记写在
[README.md](README.md)- 代码写在
[src/train.py](src/train.py)代码规范(全程遵守):
- 逐行注释:每一行可执行代码都必须有注释说明。
- 图表中文 :绘图标题、坐标轴、图例等优先使用中文;通过
setup_chinese_plot()配置中文字体。讲解规范(全程遵守):
- 详细讲解:每步说明背景、目标、操作、结果含义;逻辑清晰、层层递进,便于初学者理解。
- 新名词必解释:首次出现的术语须给出定义、为何需要、在本项目中的含义。
- Mermaid 图解 :涉及流程、数据流向、概念关系时,必须在文档中使用 Mermaid 图(见下方示例)。
目录
| 步骤 | 标题 | 状态 |
|---|---|---|
| [步骤 1](#步骤 标题 状态 步骤 1 搭建项目结构与环境 ✅ 已完成教学 步骤 2 加载数据并做初步 EDA ✅ 已完成教学 步骤 3 划分训练集与测试集 ✅ 已完成教学 步骤 4 建立基准模型 —— 线性回归 ✅ 已完成教学 步骤 5 特征缩放与 Ridge / Lasso ✅ 已完成教学 步骤 6 树模型 —— 随机森林与梯度提升 ✅ 已完成教学 步骤 7 简单特征工程 ✅ 已完成教学 步骤 8 总结与模型选择 ✅ 已完成教学) | 搭建项目结构与环境 | ✅ 已完成教学 |
| [步骤 2](#步骤 标题 状态 步骤 1 搭建项目结构与环境 ✅ 已完成教学 步骤 2 加载数据并做初步 EDA ✅ 已完成教学 步骤 3 划分训练集与测试集 ✅ 已完成教学 步骤 4 建立基准模型 —— 线性回归 ✅ 已完成教学 步骤 5 特征缩放与 Ridge / Lasso ✅ 已完成教学 步骤 6 树模型 —— 随机森林与梯度提升 ✅ 已完成教学 步骤 7 简单特征工程 ✅ 已完成教学 步骤 8 总结与模型选择 ✅ 已完成教学) | 加载数据并做初步 EDA | ✅ 已完成教学 |
| [步骤 3](#步骤 标题 状态 步骤 1 搭建项目结构与环境 ✅ 已完成教学 步骤 2 加载数据并做初步 EDA ✅ 已完成教学 步骤 3 划分训练集与测试集 ✅ 已完成教学 步骤 4 建立基准模型 —— 线性回归 ✅ 已完成教学 步骤 5 特征缩放与 Ridge / Lasso ✅ 已完成教学 步骤 6 树模型 —— 随机森林与梯度提升 ✅ 已完成教学 步骤 7 简单特征工程 ✅ 已完成教学 步骤 8 总结与模型选择 ✅ 已完成教学) | 划分训练集与测试集 | ✅ 已完成教学 |
| [步骤 4](#步骤 标题 状态 步骤 1 搭建项目结构与环境 ✅ 已完成教学 步骤 2 加载数据并做初步 EDA ✅ 已完成教学 步骤 3 划分训练集与测试集 ✅ 已完成教学 步骤 4 建立基准模型 —— 线性回归 ✅ 已完成教学 步骤 5 特征缩放与 Ridge / Lasso ✅ 已完成教学 步骤 6 树模型 —— 随机森林与梯度提升 ✅ 已完成教学 步骤 7 简单特征工程 ✅ 已完成教学 步骤 8 总结与模型选择 ✅ 已完成教学) | 建立基准模型 ------ 线性回归 | ✅ 已完成教学 |
| [步骤 5](#步骤 标题 状态 步骤 1 搭建项目结构与环境 ✅ 已完成教学 步骤 2 加载数据并做初步 EDA ✅ 已完成教学 步骤 3 划分训练集与测试集 ✅ 已完成教学 步骤 4 建立基准模型 —— 线性回归 ✅ 已完成教学 步骤 5 特征缩放与 Ridge / Lasso ✅ 已完成教学 步骤 6 树模型 —— 随机森林与梯度提升 ✅ 已完成教学 步骤 7 简单特征工程 ✅ 已完成教学 步骤 8 总结与模型选择 ✅ 已完成教学) | 特征缩放与 Ridge / Lasso | ✅ 已完成教学 |
| [步骤 6](#步骤 标题 状态 步骤 1 搭建项目结构与环境 ✅ 已完成教学 步骤 2 加载数据并做初步 EDA ✅ 已完成教学 步骤 3 划分训练集与测试集 ✅ 已完成教学 步骤 4 建立基准模型 —— 线性回归 ✅ 已完成教学 步骤 5 特征缩放与 Ridge / Lasso ✅ 已完成教学 步骤 6 树模型 —— 随机森林与梯度提升 ✅ 已完成教学 步骤 7 简单特征工程 ✅ 已完成教学 步骤 8 总结与模型选择 ✅ 已完成教学) | 树模型 ------ 随机森林与梯度提升 | ✅ 已完成教学 |
| [步骤 7](#步骤 标题 状态 步骤 1 搭建项目结构与环境 ✅ 已完成教学 步骤 2 加载数据并做初步 EDA ✅ 已完成教学 步骤 3 划分训练集与测试集 ✅ 已完成教学 步骤 4 建立基准模型 —— 线性回归 ✅ 已完成教学 步骤 5 特征缩放与 Ridge / Lasso ✅ 已完成教学 步骤 6 树模型 —— 随机森林与梯度提升 ✅ 已完成教学 步骤 7 简单特征工程 ✅ 已完成教学 步骤 8 总结与模型选择 ✅ 已完成教学) | 简单特征工程 | ✅ 已完成教学 |
| [步骤 8](#步骤 标题 状态 步骤 1 搭建项目结构与环境 ✅ 已完成教学 步骤 2 加载数据并做初步 EDA ✅ 已完成教学 步骤 3 划分训练集与测试集 ✅ 已完成教学 步骤 4 建立基准模型 —— 线性回归 ✅ 已完成教学 步骤 5 特征缩放与 Ridge / Lasso ✅ 已完成教学 步骤 6 树模型 —— 随机森林与梯度提升 ✅ 已完成教学 步骤 7 简单特征工程 ✅ 已完成教学 步骤 8 总结与模型选择 ✅ 已完成教学) | 总结与模型选择 | ✅ 已完成教学 |
步骤 1:搭建项目结构与环境
状态:✅ 已完成教学(已按详细讲解规范增补名词解释与 Mermaid 图)
1.1 本步目标
不做任何机器学习,只完成一件事:把「做项目」的工作环境搭好。后续 5 个项目都会复用同一套目录结构和编码习惯。
1.2 这一步在解决什么问题?
很多人学机器学习时,会把所有代码写在一个文件里,数据、模型、笔记混在一起。项目小的时候没问题,一旦步骤变多就很难维护。
专业做法是:
- 代码 放在
src/ - 数据 放在
data/ - 学习笔记 放在
README.md - 教学讲解 放在
教学文档.md(就是本文件)
这叫项目化思维。现在多花 5 分钟整理,后面会省很多时间。
1.2.5 本步在整体流程中的位置
本步是整条学习链的起点:先搭好「工地」,后面才能搬砖(数据)、盖楼(模型)。
#mermaid-svg-FnjHhQu00IhPXIuC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FnjHhQu00IhPXIuC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FnjHhQu00IhPXIuC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FnjHhQu00IhPXIuC .error-icon{fill:#552222;}#mermaid-svg-FnjHhQu00IhPXIuC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FnjHhQu00IhPXIuC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FnjHhQu00IhPXIuC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FnjHhQu00IhPXIuC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FnjHhQu00IhPXIuC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FnjHhQu00IhPXIuC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FnjHhQu00IhPXIuC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FnjHhQu00IhPXIuC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FnjHhQu00IhPXIuC .marker.cross{stroke:#333333;}#mermaid-svg-FnjHhQu00IhPXIuC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FnjHhQu00IhPXIuC p{margin:0;}#mermaid-svg-FnjHhQu00IhPXIuC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FnjHhQu00IhPXIuC .cluster-label text{fill:#333;}#mermaid-svg-FnjHhQu00IhPXIuC .cluster-label span{color:#333;}#mermaid-svg-FnjHhQu00IhPXIuC .cluster-label span p{background-color:transparent;}#mermaid-svg-FnjHhQu00IhPXIuC .label text,#mermaid-svg-FnjHhQu00IhPXIuC span{fill:#333;color:#333;}#mermaid-svg-FnjHhQu00IhPXIuC .node rect,#mermaid-svg-FnjHhQu00IhPXIuC .node circle,#mermaid-svg-FnjHhQu00IhPXIuC .node ellipse,#mermaid-svg-FnjHhQu00IhPXIuC .node polygon,#mermaid-svg-FnjHhQu00IhPXIuC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FnjHhQu00IhPXIuC .rough-node .label text,#mermaid-svg-FnjHhQu00IhPXIuC .node .label text,#mermaid-svg-FnjHhQu00IhPXIuC .image-shape .label,#mermaid-svg-FnjHhQu00IhPXIuC .icon-shape .label{text-anchor:middle;}#mermaid-svg-FnjHhQu00IhPXIuC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FnjHhQu00IhPXIuC .rough-node .label,#mermaid-svg-FnjHhQu00IhPXIuC .node .label,#mermaid-svg-FnjHhQu00IhPXIuC .image-shape .label,#mermaid-svg-FnjHhQu00IhPXIuC .icon-shape .label{text-align:center;}#mermaid-svg-FnjHhQu00IhPXIuC .node.clickable{cursor:pointer;}#mermaid-svg-FnjHhQu00IhPXIuC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FnjHhQu00IhPXIuC .arrowheadPath{fill:#333333;}#mermaid-svg-FnjHhQu00IhPXIuC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FnjHhQu00IhPXIuC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FnjHhQu00IhPXIuC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FnjHhQu00IhPXIuC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FnjHhQu00IhPXIuC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FnjHhQu00IhPXIuC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FnjHhQu00IhPXIuC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FnjHhQu00IhPXIuC .cluster text{fill:#333;}#mermaid-svg-FnjHhQu00IhPXIuC .cluster span{color:#333;}#mermaid-svg-FnjHhQu00IhPXIuC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FnjHhQu00IhPXIuC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FnjHhQu00IhPXIuC rect.text{fill:none;stroke-width:0;}#mermaid-svg-FnjHhQu00IhPXIuC .icon-shape,#mermaid-svg-FnjHhQu00IhPXIuC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FnjHhQu00IhPXIuC .icon-shape p,#mermaid-svg-FnjHhQu00IhPXIuC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FnjHhQu00IhPXIuC .icon-shape .label rect,#mermaid-svg-FnjHhQu00IhPXIuC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FnjHhQu00IhPXIuC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FnjHhQu00IhPXIuC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FnjHhQu00IhPXIuC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 步骤1 搭环境与目录
步骤2 加载数据 EDA
步骤3 划分训练/测试
步骤4 基准模型
步骤5~8 优化与选型
1.2.6 名词解释(本步首次出现)
| 名词 | 是什么 | 为什么需要 | 在本项目中 |
|---|---|---|---|
| 项目化思维 | 把代码、数据、文档分目录存放的习惯 | 避免所有内容堆在一个文件里,后期无法维护 | src/ 写代码,data/ 放数据,教学文档.md 写讲解 |
| 函数(function) | 一段完成特定任务的代码块,可重复调用 | 把「加载数据」「训练模型」分开,职责清晰 | load_data() 专门管数据,main() 管整体流程 |
pass |
Python 占位符,表示「这里先空着」 | 函数体不能为空,步骤 1 先搭骨架 | load_data() 里暂时用 pass,步骤 2 再填真实代码 |
main() |
程序主入口,运行脚本时从这里开始 | 统一执行顺序,避免代码散落各处 | 当前只打印「项目启动成功」,后面会扩展 |
if __name__ == "__main__" |
Python 脚本入口守卫 | 区分「直接运行」与「被 import」 | 直接运行 train.py 才执行 main() |
requirements.txt |
依赖清单文件 | 记录项目需要哪些库,便于一键安装 | 列出 pandas、sklearn 等 |
| 回归问题(预告) | 预测连续数值(如房价 1.5万、2.3万) | 本项目目标是预测房价中位数 | 与「分类」(预测类别)相对 |
1.2.7 项目目录关系图
#mermaid-svg-FtHSCbWHHlk7Mor3{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FtHSCbWHHlk7Mor3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FtHSCbWHHlk7Mor3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FtHSCbWHHlk7Mor3 .error-icon{fill:#552222;}#mermaid-svg-FtHSCbWHHlk7Mor3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FtHSCbWHHlk7Mor3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FtHSCbWHHlk7Mor3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FtHSCbWHHlk7Mor3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FtHSCbWHHlk7Mor3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FtHSCbWHHlk7Mor3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FtHSCbWHHlk7Mor3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FtHSCbWHHlk7Mor3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FtHSCbWHHlk7Mor3 .marker.cross{stroke:#333333;}#mermaid-svg-FtHSCbWHHlk7Mor3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FtHSCbWHHlk7Mor3 p{margin:0;}#mermaid-svg-FtHSCbWHHlk7Mor3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FtHSCbWHHlk7Mor3 .cluster-label text{fill:#333;}#mermaid-svg-FtHSCbWHHlk7Mor3 .cluster-label span{color:#333;}#mermaid-svg-FtHSCbWHHlk7Mor3 .cluster-label span p{background-color:transparent;}#mermaid-svg-FtHSCbWHHlk7Mor3 .label text,#mermaid-svg-FtHSCbWHHlk7Mor3 span{fill:#333;color:#333;}#mermaid-svg-FtHSCbWHHlk7Mor3 .node rect,#mermaid-svg-FtHSCbWHHlk7Mor3 .node circle,#mermaid-svg-FtHSCbWHHlk7Mor3 .node ellipse,#mermaid-svg-FtHSCbWHHlk7Mor3 .node polygon,#mermaid-svg-FtHSCbWHHlk7Mor3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FtHSCbWHHlk7Mor3 .rough-node .label text,#mermaid-svg-FtHSCbWHHlk7Mor3 .node .label text,#mermaid-svg-FtHSCbWHHlk7Mor3 .image-shape .label,#mermaid-svg-FtHSCbWHHlk7Mor3 .icon-shape .label{text-anchor:middle;}#mermaid-svg-FtHSCbWHHlk7Mor3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FtHSCbWHHlk7Mor3 .rough-node .label,#mermaid-svg-FtHSCbWHHlk7Mor3 .node .label,#mermaid-svg-FtHSCbWHHlk7Mor3 .image-shape .label,#mermaid-svg-FtHSCbWHHlk7Mor3 .icon-shape .label{text-align:center;}#mermaid-svg-FtHSCbWHHlk7Mor3 .node.clickable{cursor:pointer;}#mermaid-svg-FtHSCbWHHlk7Mor3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FtHSCbWHHlk7Mor3 .arrowheadPath{fill:#333333;}#mermaid-svg-FtHSCbWHHlk7Mor3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FtHSCbWHHlk7Mor3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FtHSCbWHHlk7Mor3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FtHSCbWHHlk7Mor3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FtHSCbWHHlk7Mor3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FtHSCbWHHlk7Mor3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FtHSCbWHHlk7Mor3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FtHSCbWHHlk7Mor3 .cluster text{fill:#333;}#mermaid-svg-FtHSCbWHHlk7Mor3 .cluster span{color:#333;}#mermaid-svg-FtHSCbWHHlk7Mor3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FtHSCbWHHlk7Mor3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FtHSCbWHHlk7Mor3 rect.text{fill:none;stroke-width:0;}#mermaid-svg-FtHSCbWHHlk7Mor3 .icon-shape,#mermaid-svg-FtHSCbWHHlk7Mor3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FtHSCbWHHlk7Mor3 .icon-shape p,#mermaid-svg-FtHSCbWHHlk7Mor3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FtHSCbWHHlk7Mor3 .icon-shape .label rect,#mermaid-svg-FtHSCbWHHlk7Mor3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FtHSCbWHHlk7Mor3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FtHSCbWHHlk7Mor3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FtHSCbWHHlk7Mor3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 机器学习/ 根目录
机器学习实战学习路线.md 总规划
requirements.txt 依赖
project_01_housing/
教学文档.md 详细讲解
README.md 你的笔记
data/ 数据文件
src/train.py 主程序
reports/figures/ 图表输出
1.3 任务清单
- 创建
project_01_housing/目录结构 - 安装依赖:
pandas、numpy、scikit-learn、matplotlib、seaborn - 编写
src/train.py骨架(含load_data()、main()) - 创建
requirements.txt与README.md - 运行
python src/train.py验证环境
1.4 目录结构说明
完成本步后,你的项目应如下所示:
机器学习/
├── 机器学习实战学习路线.md # 六个项目的总体规划
├── requirements.txt # 全部项目共用依赖
└── project_01_housing/
├── 教学文档.md # ← 你正在看的文件(详细教学过程)
├── README.md # 你的个人学习笔记
├── data/ # 存放外部 CSV(本数据集由 sklearn 在线加载,此目录备用)
├── notebooks/ # 可选:Jupyter 交互探索
└── src/
└── train.py # 主训练脚本,核心代码都写在这里
每个目录的职责:
| 目录/文件 | 职责 |
|---|---|
src/train.py |
可重复运行的训练脚本,是项目的「主程序」 |
data/ |
存放原始或下载的数据文件 |
notebooks/ |
适合快速试验、画图;成熟代码应迁回 train.py |
README.md |
你自己的简短笔记:日期、结论、疑问 |
教学文档.md |
完整教学讲解,用于复习和对照 |
1.5 核心代码解读
当前 src/train.py 内容:
python
"""
项目一:加州房价预测
主训练脚本 ------ 随着学习推进,我们会逐步往这里添加代码。
"""
def load_data():
"""加载加州房价数据集(步骤 2 会实现)。"""
pass
def main():
print("项目启动成功")
print("当前步骤:步骤 1 ------ 项目结构与环境搭建")
if __name__ == "__main__":
main()
逐段理解:
(1)def load_data():
- 专门负责「加载数据」的函数。
- 现在里面是
pass(占位,表示「暂时什么都不做」)。 - 步骤 2 会在这里写入真正的数据加载逻辑。
- 为什么要单独一个函数? 职责分离------以后换数据集时,只改这一处。
(2)def main():
- 程序的主入口,整个项目的执行流程从这里开始。
- 随着学习推进,
main()会依次调用:加载数据 → 划分数据集 → 训练模型 → 评估结果。 - 现在只打印两行字,用来确认环境正常。
(3)if __name__ == "__main__":
这是 Python 的标准入口写法,必须理解:
python
if __name__ == "__main__":
main()
| 运行方式 | 会发生什么 |
|---|---|
在终端执行 python src/train.py |
__name__ 等于 "__main__",会执行 main() |
被其他文件 import |
__name__ 等于模块名,不会 自动执行 main() |
好处:这个文件既可以独立运行 ,也可以被其他脚本导入复用,而不会产生副作用。
#mermaid-svg-7LzXmMwbOz5IPmBG{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7LzXmMwbOz5IPmBG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7LzXmMwbOz5IPmBG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7LzXmMwbOz5IPmBG .error-icon{fill:#552222;}#mermaid-svg-7LzXmMwbOz5IPmBG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7LzXmMwbOz5IPmBG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7LzXmMwbOz5IPmBG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7LzXmMwbOz5IPmBG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7LzXmMwbOz5IPmBG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7LzXmMwbOz5IPmBG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7LzXmMwbOz5IPmBG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7LzXmMwbOz5IPmBG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7LzXmMwbOz5IPmBG .marker.cross{stroke:#333333;}#mermaid-svg-7LzXmMwbOz5IPmBG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7LzXmMwbOz5IPmBG p{margin:0;}#mermaid-svg-7LzXmMwbOz5IPmBG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7LzXmMwbOz5IPmBG .cluster-label text{fill:#333;}#mermaid-svg-7LzXmMwbOz5IPmBG .cluster-label span{color:#333;}#mermaid-svg-7LzXmMwbOz5IPmBG .cluster-label span p{background-color:transparent;}#mermaid-svg-7LzXmMwbOz5IPmBG .label text,#mermaid-svg-7LzXmMwbOz5IPmBG span{fill:#333;color:#333;}#mermaid-svg-7LzXmMwbOz5IPmBG .node rect,#mermaid-svg-7LzXmMwbOz5IPmBG .node circle,#mermaid-svg-7LzXmMwbOz5IPmBG .node ellipse,#mermaid-svg-7LzXmMwbOz5IPmBG .node polygon,#mermaid-svg-7LzXmMwbOz5IPmBG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7LzXmMwbOz5IPmBG .rough-node .label text,#mermaid-svg-7LzXmMwbOz5IPmBG .node .label text,#mermaid-svg-7LzXmMwbOz5IPmBG .image-shape .label,#mermaid-svg-7LzXmMwbOz5IPmBG .icon-shape .label{text-anchor:middle;}#mermaid-svg-7LzXmMwbOz5IPmBG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7LzXmMwbOz5IPmBG .rough-node .label,#mermaid-svg-7LzXmMwbOz5IPmBG .node .label,#mermaid-svg-7LzXmMwbOz5IPmBG .image-shape .label,#mermaid-svg-7LzXmMwbOz5IPmBG .icon-shape .label{text-align:center;}#mermaid-svg-7LzXmMwbOz5IPmBG .node.clickable{cursor:pointer;}#mermaid-svg-7LzXmMwbOz5IPmBG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7LzXmMwbOz5IPmBG .arrowheadPath{fill:#333333;}#mermaid-svg-7LzXmMwbOz5IPmBG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7LzXmMwbOz5IPmBG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7LzXmMwbOz5IPmBG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7LzXmMwbOz5IPmBG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7LzXmMwbOz5IPmBG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7LzXmMwbOz5IPmBG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7LzXmMwbOz5IPmBG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7LzXmMwbOz5IPmBG .cluster text{fill:#333;}#mermaid-svg-7LzXmMwbOz5IPmBG .cluster span{color:#333;}#mermaid-svg-7LzXmMwbOz5IPmBG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7LzXmMwbOz5IPmBG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7LzXmMwbOz5IPmBG rect.text{fill:none;stroke-width:0;}#mermaid-svg-7LzXmMwbOz5IPmBG .icon-shape,#mermaid-svg-7LzXmMwbOz5IPmBG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7LzXmMwbOz5IPmBG .icon-shape p,#mermaid-svg-7LzXmMwbOz5IPmBG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7LzXmMwbOz5IPmBG .icon-shape .label rect,#mermaid-svg-7LzXmMwbOz5IPmBG .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7LzXmMwbOz5IPmBG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7LzXmMwbOz5IPmBG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7LzXmMwbOz5IPmBG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否被import
运行 python src/train.py
是否为 main 模块
执行 main
不执行 main 仅加载定义
打印项目启动成功
1.6 依赖说明
根目录 requirements.txt 内容:
pandas>=2.0
numpy>=1.24
scikit-learn>=1.3
matplotlib>=3.7
seaborn>=0.12
joblib>=1.3
安装命令(在 机器学习/ 根目录执行):
powershell
pip install -r requirements.txt
各库用途(先有个印象,用到时再细讲):
| 库 | 用途 |
|---|---|
pandas |
表格数据处理(类似 Excel 的编程版) |
numpy |
数值计算、矩阵运算 |
scikit-learn |
机器学习算法与工具(本项目核心) |
matplotlib |
画图 |
seaborn |
更美观的统计图(基于 matplotlib) |
joblib |
保存和加载训练好的模型(步骤 8 使用) |
1.7 动手任务
请在你的电脑上依次完成:
任务 A:运行脚本
powershell
cd "d:\JavaCode\机器学习\project_01_housing"
python src/train.py
预期输出:
项目启动成功
当前步骤:步骤 1 ------ 项目结构与环境搭建
若终端中文显示乱码,不影响学习,只要没有报错(Traceback)即可。
任务 B:小改动(建议)
打开 src/train.py,在 main() 里加一行:
python
def main():
print("项目启动成功")
print("当前步骤:步骤 1 ------ 项目结构与环境搭建")
print("你好,机器学习!") # ← 新增这一行
保存后再次运行,确认能看到新增输出。目的是熟悉「改代码 → 保存 → 运行 → 看结果」的循环。
任务 C:写学习笔记
打开 README.md,在步骤 1 下填写日期和一句话感受。
1.8 验收标准
- 目录结构与上文一致
-
python src/train.py无报错,打印「项目启动成功」 - 能解释
load_data()、main()、if __name__ == "__main__"各自的作用 -
README.md中已记录本步完成情况
1.9 本步核心概念
1.9 动手任务与验收标准参考答案
以下为教学标准答案,便于自学对照;
README.md学习记录仍建议用自己的话写。
动手任务答案
| 任务 | 参考答案 |
|---|---|
| A | 运行 python src/train.py,应看到「项目启动成功」,无 Traceback。 |
| B | 增加 print("你好,机器学习!") 后多一行输出。 |
| C | 在 README 步骤 1 填写日期与一句话感受。 |
验收标准答案
| 验收项 | 参考答案 |
|---|---|
| 目录结构 | 含 src/train.py、data/、reports/、models/、教学文档.md。 |
| 脚本无报错 | 打印「项目启动成功」。 |
| 三个概念 | load_data() 加载数据;main() 主流程;if __name__=="__main__" 仅直接运行时执行 main。 |
| README | 步骤 1 已记录。 |
| 概念 | 解释 |
|---|---|
| 项目化思维 | 代码、数据、文档分离,结构清晰,便于维护和复现 |
| 函数拆分 | 一个函数做一件事(加载、训练、评估分开) |
| 脚本入口 | if __name__ == "__main__" 保证直接运行才执行主流程 |
1.10 常见问题
Q: pass 是什么意思?
A:占位符,表示「这里暂时空着,以后再写」。函数体不能为空,所以用 pass 占一行。
Q:为什么不用 Jupyter Notebook 从头写到尾?
A:Notebook 适合探索;train.py 适合可重复运行的完整流程。我们会两者结合:notebooks/ 试验,成熟代码写入 src/train.py。
Q: data/ 现在是空的,正常吗?
A:正常。加州房价数据由 sklearn 内置接口在线加载,不需要手动下载 CSV。data/ 为后续扩展或其他数据源备用。
1.11 项目全景预告
完成全部 8 步后,你将用 加州房价数据集 (约 20,640 条记录、8 个特征)预测房价中位数 MedHouseVal。
这是典型的 回归问题:
- 回归:预测连续数值(房价可以是 1.5万、2.3万......)
- 分类(对比理解):预测类别(如「是/否」「猫/狗」)
#mermaid-svg-Kcluvr6yyijzHXtB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Kcluvr6yyijzHXtB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Kcluvr6yyijzHXtB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Kcluvr6yyijzHXtB .error-icon{fill:#552222;}#mermaid-svg-Kcluvr6yyijzHXtB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Kcluvr6yyijzHXtB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Kcluvr6yyijzHXtB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Kcluvr6yyijzHXtB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Kcluvr6yyijzHXtB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Kcluvr6yyijzHXtB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Kcluvr6yyijzHXtB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Kcluvr6yyijzHXtB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Kcluvr6yyijzHXtB .marker.cross{stroke:#333333;}#mermaid-svg-Kcluvr6yyijzHXtB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Kcluvr6yyijzHXtB p{margin:0;}#mermaid-svg-Kcluvr6yyijzHXtB .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Kcluvr6yyijzHXtB .cluster-label text{fill:#333;}#mermaid-svg-Kcluvr6yyijzHXtB .cluster-label span{color:#333;}#mermaid-svg-Kcluvr6yyijzHXtB .cluster-label span p{background-color:transparent;}#mermaid-svg-Kcluvr6yyijzHXtB .label text,#mermaid-svg-Kcluvr6yyijzHXtB span{fill:#333;color:#333;}#mermaid-svg-Kcluvr6yyijzHXtB .node rect,#mermaid-svg-Kcluvr6yyijzHXtB .node circle,#mermaid-svg-Kcluvr6yyijzHXtB .node ellipse,#mermaid-svg-Kcluvr6yyijzHXtB .node polygon,#mermaid-svg-Kcluvr6yyijzHXtB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Kcluvr6yyijzHXtB .rough-node .label text,#mermaid-svg-Kcluvr6yyijzHXtB .node .label text,#mermaid-svg-Kcluvr6yyijzHXtB .image-shape .label,#mermaid-svg-Kcluvr6yyijzHXtB .icon-shape .label{text-anchor:middle;}#mermaid-svg-Kcluvr6yyijzHXtB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Kcluvr6yyijzHXtB .rough-node .label,#mermaid-svg-Kcluvr6yyijzHXtB .node .label,#mermaid-svg-Kcluvr6yyijzHXtB .image-shape .label,#mermaid-svg-Kcluvr6yyijzHXtB .icon-shape .label{text-align:center;}#mermaid-svg-Kcluvr6yyijzHXtB .node.clickable{cursor:pointer;}#mermaid-svg-Kcluvr6yyijzHXtB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Kcluvr6yyijzHXtB .arrowheadPath{fill:#333333;}#mermaid-svg-Kcluvr6yyijzHXtB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Kcluvr6yyijzHXtB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Kcluvr6yyijzHXtB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Kcluvr6yyijzHXtB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Kcluvr6yyijzHXtB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Kcluvr6yyijzHXtB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Kcluvr6yyijzHXtB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Kcluvr6yyijzHXtB .cluster text{fill:#333;}#mermaid-svg-Kcluvr6yyijzHXtB .cluster span{color:#333;}#mermaid-svg-Kcluvr6yyijzHXtB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Kcluvr6yyijzHXtB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Kcluvr6yyijzHXtB rect.text{fill:none;stroke-width:0;}#mermaid-svg-Kcluvr6yyijzHXtB .icon-shape,#mermaid-svg-Kcluvr6yyijzHXtB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Kcluvr6yyijzHXtB .icon-shape p,#mermaid-svg-Kcluvr6yyijzHXtB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Kcluvr6yyijzHXtB .icon-shape .label rect,#mermaid-svg-Kcluvr6yyijzHXtB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Kcluvr6yyijzHXtB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Kcluvr6yyijzHXtB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Kcluvr6yyijzHXtB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 机器学习任务
回归:预测连续数值
分类:预测类别标签
例:房价 温度 销量
本项目:MedHouseVal
例:是否欺诈 猫或狗
步骤 2 将第一次真正接触数据。
1.12 学习记录(请你填写)
- 完成日期:
- 动手任务完成情况:任务 A / B / C
- 我的理解(用自己的话写 1~3 句):
- 疑问(如有):
步骤 2:加载数据并做初步 EDA
状态:✅ 已完成教学(已按详细讲解规范增补名词解释与 Mermaid 图)
2.1 本步目标
第一次真正接触机器学习数据。完成三件事:
- 加载加州房价数据集
- 认识每一列代表什么(特征 vs 标签)
- 探索数据分布与特征和房价的关系(EDA)
EDA(Exploratory Data Analysis,探索性数据分析)是建模前的「侦察」:不急着训练模型,先把数据摸清楚。
2.2 这一步在解决什么问题?
模型不是凭空猜的,它从历史数据里学规律。若连数据长什么样、要预测什么都不知道,后面的训练容易踩坑。
本步要回答四个问题:
| 问题 | 怎么回答 |
|---|---|
| 有多少条数据? | df.shape |
| 每列是什么类型?有无缺失? | df.info()、缺失值统计 |
| 数值大概什么范围? | df.describe() |
| 哪些因素和房价有关? | 相关性、散点图 |
2.2.5 本步在整体流程中的位置
步骤 1 搭好了环境;步骤 2 是第一次接触真实数据。只有先「看清数据」,后面的建模才有依据。
#mermaid-svg-UgWpKNrbykqfO6vE{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UgWpKNrbykqfO6vE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UgWpKNrbykqfO6vE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UgWpKNrbykqfO6vE .error-icon{fill:#552222;}#mermaid-svg-UgWpKNrbykqfO6vE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UgWpKNrbykqfO6vE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UgWpKNrbykqfO6vE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UgWpKNrbykqfO6vE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UgWpKNrbykqfO6vE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UgWpKNrbykqfO6vE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UgWpKNrbykqfO6vE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UgWpKNrbykqfO6vE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UgWpKNrbykqfO6vE .marker.cross{stroke:#333333;}#mermaid-svg-UgWpKNrbykqfO6vE svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UgWpKNrbykqfO6vE p{margin:0;}#mermaid-svg-UgWpKNrbykqfO6vE .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UgWpKNrbykqfO6vE .cluster-label text{fill:#333;}#mermaid-svg-UgWpKNrbykqfO6vE .cluster-label span{color:#333;}#mermaid-svg-UgWpKNrbykqfO6vE .cluster-label span p{background-color:transparent;}#mermaid-svg-UgWpKNrbykqfO6vE .label text,#mermaid-svg-UgWpKNrbykqfO6vE span{fill:#333;color:#333;}#mermaid-svg-UgWpKNrbykqfO6vE .node rect,#mermaid-svg-UgWpKNrbykqfO6vE .node circle,#mermaid-svg-UgWpKNrbykqfO6vE .node ellipse,#mermaid-svg-UgWpKNrbykqfO6vE .node polygon,#mermaid-svg-UgWpKNrbykqfO6vE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UgWpKNrbykqfO6vE .rough-node .label text,#mermaid-svg-UgWpKNrbykqfO6vE .node .label text,#mermaid-svg-UgWpKNrbykqfO6vE .image-shape .label,#mermaid-svg-UgWpKNrbykqfO6vE .icon-shape .label{text-anchor:middle;}#mermaid-svg-UgWpKNrbykqfO6vE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UgWpKNrbykqfO6vE .rough-node .label,#mermaid-svg-UgWpKNrbykqfO6vE .node .label,#mermaid-svg-UgWpKNrbykqfO6vE .image-shape .label,#mermaid-svg-UgWpKNrbykqfO6vE .icon-shape .label{text-align:center;}#mermaid-svg-UgWpKNrbykqfO6vE .node.clickable{cursor:pointer;}#mermaid-svg-UgWpKNrbykqfO6vE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UgWpKNrbykqfO6vE .arrowheadPath{fill:#333333;}#mermaid-svg-UgWpKNrbykqfO6vE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UgWpKNrbykqfO6vE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UgWpKNrbykqfO6vE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UgWpKNrbykqfO6vE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UgWpKNrbykqfO6vE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UgWpKNrbykqfO6vE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UgWpKNrbykqfO6vE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UgWpKNrbykqfO6vE .cluster text{fill:#333;}#mermaid-svg-UgWpKNrbykqfO6vE .cluster span{color:#333;}#mermaid-svg-UgWpKNrbykqfO6vE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UgWpKNrbykqfO6vE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UgWpKNrbykqfO6vE rect.text{fill:none;stroke-width:0;}#mermaid-svg-UgWpKNrbykqfO6vE .icon-shape,#mermaid-svg-UgWpKNrbykqfO6vE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UgWpKNrbykqfO6vE .icon-shape p,#mermaid-svg-UgWpKNrbykqfO6vE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UgWpKNrbykqfO6vE .icon-shape .label rect,#mermaid-svg-UgWpKNrbykqfO6vE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UgWpKNrbykqfO6vE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UgWpKNrbykqfO6vE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UgWpKNrbykqfO6vE :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否需清洗
步骤1 环境就绪
步骤2 EDA 探索数据
数据是否可用?
步骤3 划分训练测试
先清洗数据
2.2.6 名词解释(本步首次出现)
| 名词 | 是什么 | 为什么需要 | 在本项目中 | 易混淆 |
|---|---|---|---|---|
| EDA | Exploratory Data Analysis,探索性数据分析 | 建模前必须先了解数据分布、缺失、异常 | 看 shape、画图、算相关性 | 不是建模,是「侦察」 |
| DataFrame | Pandas 的二维表格结构 | 机器学习表格数据的标准容器 | load_data() 返回的就是 DataFrame |
类似 Excel 表 |
| 特征 Feature | 模型的输入变量 | 模型根据特征做预测 | 8 列:收入、房龄、房间数等 | 不是标签 |
| 标签 Label | 要预测的目标变量 | 监督学习需要「标准答案」来学习 | MedHouseVal 房价中位数 |
也称 Target |
| 样本 Sample | 一条观测记录 | 统计与训练的基本单位 | 一行 = 一个加州区域 | 不是单个房屋 |
| 皮尔逊相关系数 | 衡量两列数值线性相关程度,范围 -1~1 | 快速发现哪些特征与房价有关 | MedInc 约 +0.69 最强 | 相关≠因果 |
| 右偏分布 | 多数值集中在左侧,右侧有长尾 | 影响模型与指标解读 | 房价 histogram 低价多、高价少 | 与左偏相反 |
| 数据缓存 | 下载一次保存本地,后续直接读取 | 加速、离线、可复现 | data/california_housing.csv |
不是每次联网下载 |
2.2.7 特征、标签、样本三者关系
#mermaid-svg-7nxmDwwKhTTNs8RO{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7nxmDwwKhTTNs8RO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7nxmDwwKhTTNs8RO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7nxmDwwKhTTNs8RO .error-icon{fill:#552222;}#mermaid-svg-7nxmDwwKhTTNs8RO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7nxmDwwKhTTNs8RO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7nxmDwwKhTTNs8RO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7nxmDwwKhTTNs8RO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7nxmDwwKhTTNs8RO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7nxmDwwKhTTNs8RO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7nxmDwwKhTTNs8RO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7nxmDwwKhTTNs8RO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7nxmDwwKhTTNs8RO .marker.cross{stroke:#333333;}#mermaid-svg-7nxmDwwKhTTNs8RO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7nxmDwwKhTTNs8RO p{margin:0;}#mermaid-svg-7nxmDwwKhTTNs8RO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7nxmDwwKhTTNs8RO .cluster-label text{fill:#333;}#mermaid-svg-7nxmDwwKhTTNs8RO .cluster-label span{color:#333;}#mermaid-svg-7nxmDwwKhTTNs8RO .cluster-label span p{background-color:transparent;}#mermaid-svg-7nxmDwwKhTTNs8RO .label text,#mermaid-svg-7nxmDwwKhTTNs8RO span{fill:#333;color:#333;}#mermaid-svg-7nxmDwwKhTTNs8RO .node rect,#mermaid-svg-7nxmDwwKhTTNs8RO .node circle,#mermaid-svg-7nxmDwwKhTTNs8RO .node ellipse,#mermaid-svg-7nxmDwwKhTTNs8RO .node polygon,#mermaid-svg-7nxmDwwKhTTNs8RO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7nxmDwwKhTTNs8RO .rough-node .label text,#mermaid-svg-7nxmDwwKhTTNs8RO .node .label text,#mermaid-svg-7nxmDwwKhTTNs8RO .image-shape .label,#mermaid-svg-7nxmDwwKhTTNs8RO .icon-shape .label{text-anchor:middle;}#mermaid-svg-7nxmDwwKhTTNs8RO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7nxmDwwKhTTNs8RO .rough-node .label,#mermaid-svg-7nxmDwwKhTTNs8RO .node .label,#mermaid-svg-7nxmDwwKhTTNs8RO .image-shape .label,#mermaid-svg-7nxmDwwKhTTNs8RO .icon-shape .label{text-align:center;}#mermaid-svg-7nxmDwwKhTTNs8RO .node.clickable{cursor:pointer;}#mermaid-svg-7nxmDwwKhTTNs8RO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7nxmDwwKhTTNs8RO .arrowheadPath{fill:#333333;}#mermaid-svg-7nxmDwwKhTTNs8RO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7nxmDwwKhTTNs8RO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7nxmDwwKhTTNs8RO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7nxmDwwKhTTNs8RO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7nxmDwwKhTTNs8RO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7nxmDwwKhTTNs8RO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7nxmDwwKhTTNs8RO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7nxmDwwKhTTNs8RO .cluster text{fill:#333;}#mermaid-svg-7nxmDwwKhTTNs8RO .cluster span{color:#333;}#mermaid-svg-7nxmDwwKhTTNs8RO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7nxmDwwKhTTNs8RO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7nxmDwwKhTTNs8RO rect.text{fill:none;stroke-width:0;}#mermaid-svg-7nxmDwwKhTTNs8RO .icon-shape,#mermaid-svg-7nxmDwwKhTTNs8RO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7nxmDwwKhTTNs8RO .icon-shape p,#mermaid-svg-7nxmDwwKhTTNs8RO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7nxmDwwKhTTNs8RO .icon-shape .label rect,#mermaid-svg-7nxmDwwKhTTNs8RO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7nxmDwwKhTTNs8RO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7nxmDwwKhTTNs8RO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7nxmDwwKhTTNs8RO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 一条样本
MedInc 收入
HouseAge 房龄
共8个特征
MedHouseVal 房价
模型输入 X
模型目标 y
2.3 任务清单
- 用
fetch_california_housing/ 备用源加载为 DataFrame - 查看
shape、info()、describe() - 检查缺失值
- 画 3 张图:目标分布、相关性条形图、收入 vs 房价散点图
- 将数据缓存到
data/california_housing.csv
2.4 数据集说明
加州房价数据集记录的是加州各「街区 / 区域」的统计信息(不是每一套独立房屋,而是一个区域的汇总)。
| 列名 | 中文含义 | 角色 |
|---|---|---|
MedInc |
该区域收入中位数 | 特征 |
HouseAge |
房屋年龄中位数 | 特征 |
AveRooms |
平均房间数 | 特征 |
AveBedrms |
平均卧室数 | 特征 |
Population |
人口 | 特征 |
AveOccup |
平均入住人数 | 特征 |
Latitude |
纬度 | 特征 |
Longitude |
经度 | 特征 |
MedHouseVal |
房价中位数(要预测的目标) | 标签 |
三个核心概念:
| 概念 | 英文 | 本项目中指什么 |
|---|---|---|
| 特征 | Feature | 上面 8 列输入,如收入、房间数 |
| 标签 | Label / Target | MedHouseVal,我们要预测的房价 |
| 样本 | Sample | 表格中的一行,代表一个区域的一条记录 |
关于房价单位: MedHouseVal = 2.0 表示该区域房价中位数约为 20 万美元 (单位是「十万美元」)。数据集中上限常被截断在 5.0(即 50 万美元)。
2.5 运行本步
在项目目录执行:
powershell
cd "d:\JavaCode\机器学习\project_01_housing"
python src/train.py
预期输出要点:
- 样本数约 20,433 条(与 sklearn 官方 20,640 接近;备用数据源清洗后略少)
- 无缺失值
- 与房价相关性最强:
MedInc(收入中位数) ,相关系数约 +0.69 - 生成 3 张图到
reports/figures/
2.6 数据加载逻辑解读
load_data() 采用了「三级回退 + 本地缓存」策略(真实项目中很常见):
python
def load_data() -> pd.DataFrame:
# 1. 优先读本地缓存(最快、可离线)
if DATA_PATH.exists():
return pd.read_csv(DATA_PATH)
# 2. 尝试 sklearn 在线下载
try:
housing = fetch_california_housing(as_frame=True)
df = housing.frame.copy()
except Exception:
# 3. 失败则用 OpenML 备用源,并统一列名
df = _build_from_openml()
# 4. 首次成功后写入 data/,下次不用再下载
df.to_csv(DATA_PATH, index=False)
return df
为什么这样做?
你当前环境中 sklearn 官方数据源返回了 HTTP 403(被服务器拒绝),所以自动走了 OpenML 备用方案,并把结果保存到 data/california_housing.csv。之后再次运行会直接读本地文件,更快也更稳定。
教学点:做项目时,数据要能稳定复现 。缓存到 data/ 是好的习惯。
#mermaid-svg-Y3lOlztOW1TlXbdI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Y3lOlztOW1TlXbdI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Y3lOlztOW1TlXbdI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Y3lOlztOW1TlXbdI .error-icon{fill:#552222;}#mermaid-svg-Y3lOlztOW1TlXbdI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Y3lOlztOW1TlXbdI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Y3lOlztOW1TlXbdI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Y3lOlztOW1TlXbdI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Y3lOlztOW1TlXbdI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Y3lOlztOW1TlXbdI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Y3lOlztOW1TlXbdI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Y3lOlztOW1TlXbdI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Y3lOlztOW1TlXbdI .marker.cross{stroke:#333333;}#mermaid-svg-Y3lOlztOW1TlXbdI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Y3lOlztOW1TlXbdI p{margin:0;}#mermaid-svg-Y3lOlztOW1TlXbdI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Y3lOlztOW1TlXbdI .cluster-label text{fill:#333;}#mermaid-svg-Y3lOlztOW1TlXbdI .cluster-label span{color:#333;}#mermaid-svg-Y3lOlztOW1TlXbdI .cluster-label span p{background-color:transparent;}#mermaid-svg-Y3lOlztOW1TlXbdI .label text,#mermaid-svg-Y3lOlztOW1TlXbdI span{fill:#333;color:#333;}#mermaid-svg-Y3lOlztOW1TlXbdI .node rect,#mermaid-svg-Y3lOlztOW1TlXbdI .node circle,#mermaid-svg-Y3lOlztOW1TlXbdI .node ellipse,#mermaid-svg-Y3lOlztOW1TlXbdI .node polygon,#mermaid-svg-Y3lOlztOW1TlXbdI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Y3lOlztOW1TlXbdI .rough-node .label text,#mermaid-svg-Y3lOlztOW1TlXbdI .node .label text,#mermaid-svg-Y3lOlztOW1TlXbdI .image-shape .label,#mermaid-svg-Y3lOlztOW1TlXbdI .icon-shape .label{text-anchor:middle;}#mermaid-svg-Y3lOlztOW1TlXbdI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Y3lOlztOW1TlXbdI .rough-node .label,#mermaid-svg-Y3lOlztOW1TlXbdI .node .label,#mermaid-svg-Y3lOlztOW1TlXbdI .image-shape .label,#mermaid-svg-Y3lOlztOW1TlXbdI .icon-shape .label{text-align:center;}#mermaid-svg-Y3lOlztOW1TlXbdI .node.clickable{cursor:pointer;}#mermaid-svg-Y3lOlztOW1TlXbdI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Y3lOlztOW1TlXbdI .arrowheadPath{fill:#333333;}#mermaid-svg-Y3lOlztOW1TlXbdI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Y3lOlztOW1TlXbdI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Y3lOlztOW1TlXbdI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Y3lOlztOW1TlXbdI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Y3lOlztOW1TlXbdI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Y3lOlztOW1TlXbdI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Y3lOlztOW1TlXbdI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Y3lOlztOW1TlXbdI .cluster text{fill:#333;}#mermaid-svg-Y3lOlztOW1TlXbdI .cluster span{color:#333;}#mermaid-svg-Y3lOlztOW1TlXbdI div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Y3lOlztOW1TlXbdI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Y3lOlztOW1TlXbdI rect.text{fill:none;stroke-width:0;}#mermaid-svg-Y3lOlztOW1TlXbdI .icon-shape,#mermaid-svg-Y3lOlztOW1TlXbdI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Y3lOlztOW1TlXbdI .icon-shape p,#mermaid-svg-Y3lOlztOW1TlXbdI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Y3lOlztOW1TlXbdI .icon-shape .label rect,#mermaid-svg-Y3lOlztOW1TlXbdI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Y3lOlztOW1TlXbdI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Y3lOlztOW1TlXbdI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Y3lOlztOW1TlXbdI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
成功
失败403
load_data() 被调用
本地 CSV 存在?
pd.read_csv 直接读取
尝试 sklearn 在线下载
写入 data/ 缓存
OpenML 备用源
返回 DataFrame
2.7 EDA 整体流程
#mermaid-svg-LbXaZvBmB83lWBmT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LbXaZvBmB83lWBmT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LbXaZvBmB83lWBmT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LbXaZvBmB83lWBmT .error-icon{fill:#552222;}#mermaid-svg-LbXaZvBmB83lWBmT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LbXaZvBmB83lWBmT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LbXaZvBmB83lWBmT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LbXaZvBmB83lWBmT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LbXaZvBmB83lWBmT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LbXaZvBmB83lWBmT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LbXaZvBmB83lWBmT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LbXaZvBmB83lWBmT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LbXaZvBmB83lWBmT .marker.cross{stroke:#333333;}#mermaid-svg-LbXaZvBmB83lWBmT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LbXaZvBmB83lWBmT p{margin:0;}#mermaid-svg-LbXaZvBmB83lWBmT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LbXaZvBmB83lWBmT .cluster-label text{fill:#333;}#mermaid-svg-LbXaZvBmB83lWBmT .cluster-label span{color:#333;}#mermaid-svg-LbXaZvBmB83lWBmT .cluster-label span p{background-color:transparent;}#mermaid-svg-LbXaZvBmB83lWBmT .label text,#mermaid-svg-LbXaZvBmB83lWBmT span{fill:#333;color:#333;}#mermaid-svg-LbXaZvBmB83lWBmT .node rect,#mermaid-svg-LbXaZvBmB83lWBmT .node circle,#mermaid-svg-LbXaZvBmB83lWBmT .node ellipse,#mermaid-svg-LbXaZvBmB83lWBmT .node polygon,#mermaid-svg-LbXaZvBmB83lWBmT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LbXaZvBmB83lWBmT .rough-node .label text,#mermaid-svg-LbXaZvBmB83lWBmT .node .label text,#mermaid-svg-LbXaZvBmB83lWBmT .image-shape .label,#mermaid-svg-LbXaZvBmB83lWBmT .icon-shape .label{text-anchor:middle;}#mermaid-svg-LbXaZvBmB83lWBmT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LbXaZvBmB83lWBmT .rough-node .label,#mermaid-svg-LbXaZvBmB83lWBmT .node .label,#mermaid-svg-LbXaZvBmB83lWBmT .image-shape .label,#mermaid-svg-LbXaZvBmB83lWBmT .icon-shape .label{text-align:center;}#mermaid-svg-LbXaZvBmB83lWBmT .node.clickable{cursor:pointer;}#mermaid-svg-LbXaZvBmB83lWBmT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LbXaZvBmB83lWBmT .arrowheadPath{fill:#333333;}#mermaid-svg-LbXaZvBmB83lWBmT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LbXaZvBmB83lWBmT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LbXaZvBmB83lWBmT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LbXaZvBmB83lWBmT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LbXaZvBmB83lWBmT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LbXaZvBmB83lWBmT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LbXaZvBmB83lWBmT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LbXaZvBmB83lWBmT .cluster text{fill:#333;}#mermaid-svg-LbXaZvBmB83lWBmT .cluster span{color:#333;}#mermaid-svg-LbXaZvBmB83lWBmT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LbXaZvBmB83lWBmT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LbXaZvBmB83lWBmT rect.text{fill:none;stroke-width:0;}#mermaid-svg-LbXaZvBmB83lWBmT .icon-shape,#mermaid-svg-LbXaZvBmB83lWBmT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LbXaZvBmB83lWBmT .icon-shape p,#mermaid-svg-LbXaZvBmB83lWBmT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LbXaZvBmB83lWBmT .icon-shape .label rect,#mermaid-svg-LbXaZvBmB83lWBmT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LbXaZvBmB83lWBmT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LbXaZvBmB83lWBmT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LbXaZvBmB83lWBmT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 加载 DataFrame
shape 看规模
info 看类型与缺失
describe 看数值范围
corr 算与房价相关性
画3张图 分布/相关/散点
得出结论 谁与房价最相关
2.8 EDA 代码解读
(1)看数据规模
python
print(f"样本数(行): {df.shape[0]}")
print(f"字段数(列): {df.shape[1]}")
shape[0]= 行数 = 有多少个样本shape[1]= 列数 = 有多少个字段
(2)看类型与缺失
python
df.info()
df.isnull().sum()
info():每列类型、非空数量- 缺失值:本数据集清洗后无缺失;但检查缺失是每次 EDA 的固定动作
(3)看统计摘要
python
df.describe()
输出 count、mean、std、min、25%、50%、75%、max。快速判断:
- 收入
MedInc均值约 3.87 → 典型区域收入约 3.87 万美元量级(需结合数据集定义理解) - 房价
MedHouseVal最大值 5.0 → 存在截断(高价房被压在 5.0)
(4)算相关性
python
correlations = df.corr(numeric_only=True)["MedHouseVal"].drop("MedHouseVal")
相关系数范围 -1 到 +1:
| 值 | 含义 |
|---|---|
| 接近 +1 | 该特征越大,房价倾向于越高 |
| 接近 -1 | 该特征越大,房价倾向于越低 |
| 接近 0 | 线性关系弱 |
本步实际结果(你的环境):
| 特征 | 相关系数 | 解读 |
|---|---|---|
| MedInc | +0.688 | 收入越高,房价越高(最强) |
| AveRooms | +0.151 | 房间多,房价略高 |
| Latitude | -0.145 | 纬度与房价有弱负相关(地理位置效应) |
| HouseAge | +0.106 | 弱正相关 |
| AveBedrms | -0.047 | 很弱 |
| Longitude | -0.045 | 很弱 |
| Population | -0.025 | 很弱 |
| AveOccup | -0.024 | 很弱 |
重要提醒:相关性 ≠ 因果关系。
收入高往往伴随房价高,但不能简单说「涨收入就能涨房价」。EDA 阶段只做「线索发现」,不做因果断言。
#mermaid-svg-AMplj2ZiTw7aABc8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AMplj2ZiTw7aABc8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AMplj2ZiTw7aABc8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AMplj2ZiTw7aABc8 .error-icon{fill:#552222;}#mermaid-svg-AMplj2ZiTw7aABc8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AMplj2ZiTw7aABc8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AMplj2ZiTw7aABc8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AMplj2ZiTw7aABc8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AMplj2ZiTw7aABc8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AMplj2ZiTw7aABc8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AMplj2ZiTw7aABc8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AMplj2ZiTw7aABc8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AMplj2ZiTw7aABc8 .marker.cross{stroke:#333333;}#mermaid-svg-AMplj2ZiTw7aABc8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AMplj2ZiTw7aABc8 p{margin:0;}#mermaid-svg-AMplj2ZiTw7aABc8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-AMplj2ZiTw7aABc8 .cluster-label text{fill:#333;}#mermaid-svg-AMplj2ZiTw7aABc8 .cluster-label span{color:#333;}#mermaid-svg-AMplj2ZiTw7aABc8 .cluster-label span p{background-color:transparent;}#mermaid-svg-AMplj2ZiTw7aABc8 .label text,#mermaid-svg-AMplj2ZiTw7aABc8 span{fill:#333;color:#333;}#mermaid-svg-AMplj2ZiTw7aABc8 .node rect,#mermaid-svg-AMplj2ZiTw7aABc8 .node circle,#mermaid-svg-AMplj2ZiTw7aABc8 .node ellipse,#mermaid-svg-AMplj2ZiTw7aABc8 .node polygon,#mermaid-svg-AMplj2ZiTw7aABc8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AMplj2ZiTw7aABc8 .rough-node .label text,#mermaid-svg-AMplj2ZiTw7aABc8 .node .label text,#mermaid-svg-AMplj2ZiTw7aABc8 .image-shape .label,#mermaid-svg-AMplj2ZiTw7aABc8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-AMplj2ZiTw7aABc8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AMplj2ZiTw7aABc8 .rough-node .label,#mermaid-svg-AMplj2ZiTw7aABc8 .node .label,#mermaid-svg-AMplj2ZiTw7aABc8 .image-shape .label,#mermaid-svg-AMplj2ZiTw7aABc8 .icon-shape .label{text-align:center;}#mermaid-svg-AMplj2ZiTw7aABc8 .node.clickable{cursor:pointer;}#mermaid-svg-AMplj2ZiTw7aABc8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AMplj2ZiTw7aABc8 .arrowheadPath{fill:#333333;}#mermaid-svg-AMplj2ZiTw7aABc8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AMplj2ZiTw7aABc8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AMplj2ZiTw7aABc8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AMplj2ZiTw7aABc8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AMplj2ZiTw7aABc8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AMplj2ZiTw7aABc8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AMplj2ZiTw7aABc8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AMplj2ZiTw7aABc8 .cluster text{fill:#333;}#mermaid-svg-AMplj2ZiTw7aABc8 .cluster span{color:#333;}#mermaid-svg-AMplj2ZiTw7aABc8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AMplj2ZiTw7aABc8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AMplj2ZiTw7aABc8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-AMplj2ZiTw7aABc8 .icon-shape,#mermaid-svg-AMplj2ZiTw7aABc8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AMplj2ZiTw7aABc8 .icon-shape p,#mermaid-svg-AMplj2ZiTw7aABc8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AMplj2ZiTw7aABc8 .icon-shape .label rect,#mermaid-svg-AMplj2ZiTw7aABc8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AMplj2ZiTw7aABc8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AMplj2ZiTw7aABc8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AMplj2ZiTw7aABc8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 相关非因果
MedInc升高
房价倾向于升高
不等于涨收入导致涨房价
2.9 三张图分别说明什么
图表保存在 reports/figures/(标题与坐标轴均为中文):
图 1:01_target_distribution.png --- 房价中位数分布
- 标题:房价中位数分布
- 看什么 :
MedHouseVal的直方图 + 密度曲线 - 典型现象 :右偏分布 ------ 大量区域房价集中在较低区间,右侧有长尾(少数高价区域)
- 对建模的启示 :后面可能要对目标做
log变换(进阶);现在先记住「分布不均匀」
图 2:02_feature_correlation.png --- 各特征与房价的相关系数
- 标题:各特征与房价中位数的相关系数
- 看什么:纵轴为中文特征名,横轴为皮尔逊相关系数
- 典型现象 :
MedInc遥遥领先,其余特征相对较弱 - 对建模的启示:收入是核心特征;但弱特征组合起来仍可能有价值(后续树模型会体现)
图 3:03_medinc_vs_price.png --- 收入与房价散点图
- 标题:收入中位数与房价中位数的关系
- 看什么:横轴收入中位数,纵轴房价中位数
- 典型现象 :整体呈上升趋势,但点很分散 ------ 说明收入能解释一部分房价,但不是全部
- 对建模的启示:线性关系存在,但会有较大残差(预测误差)
2.10 动手任务
任务 A:运行并核对输出
运行 python src/train.py,确认:
- 终端打印了相关性排序,
MedInc排第一 -
reports/figures/下出现 3 张 PNG 图 -
data/california_housing.csv已生成
任务 B:用 Pandas 自己试两行(建议)
在项目根目录打开 Python 交互环境:
powershell
python
python
import pandas as pd
df = pd.read_csv("data/california_housing.csv")
df.head() # 看前 5 行
df.tail(3) # 看后 3 行
思考:head() 每一行代表什么?(答:一个加州区域的记录)
任务 C:改一处代码观察变化(可选)
在 explore_data() 里,把散点图的 x="MedInc" 改成 x="HouseAge",重新运行,看图 3 形态如何变化。体会「不同特征与目标的关系形态不同」。
任务 D:写学习笔记
在 README.md 的步骤 2 记录下:最强相关特征是什么、你对右偏分布的理解。
2.11 验收标准
- 能说出 8 个特征和 1 个标签各是什么
- 能解释「样本 = 一行数据」
- 能说出与房价相关性最强的特征(
MedInc) - 能描述
MedHouseVal大致呈右偏分布 - 能区分「相关性」与「因果关系」
- 3 张图成功生成
2.12 本步核心概念
2.12 动手任务与验收标准参考答案
以下为教学标准答案,便于自学对照;
README.md学习记录仍建议用自己的话写。
动手任务答案
| 任务 | 参考答案 |
|---|---|
| A | MedInc 相关性第一;01_~03_ PNG 已生成;california_housing.csv 已缓存。 |
| B | 每行 = 一个加州区域统计记录。 |
| C | 改 x=HouseAge 后关系弱于 MedInc,形态更分散。 |
| D | 示例:MedInc 最强相关;房价右偏。 |
验收标准答案
| 验收项 | 参考答案 |
|---|---|
| 8 特征 + 1 标签 | 8 个 MedInc 等特征;标签 MedHouseVal。 |
| 样本 | 一行 = 一个区域。 |
| 最强相关 | MedInc,r≈+0.69。 |
| 右偏 | 低价多、高价长尾。 |
| 相关≠因果 | 相关不等于因果。 |
| 3 张图 | 01/02/03 三张 PNG。 |
| 概念 | 解释 |
|---|---|
| EDA | 建模前对数据的系统性探查 |
| 特征 / 标签 / 样本 | 输入、输出、一行观测 |
| describe() | 数值列的分布摘要统计 |
| 相关系数 | 两列数值的线性相关强度(-1~1) |
| 右偏分布 | 多数值集中在左侧,右侧有长尾 |
| 数据缓存 | 下载一次存本地,保证复现与离线可用 |
2.13 常见问题
Q:为什么我的样本数是 20433 而不是 20640?
A:备用数据源在转换时去掉了少量含缺失卧室数的行,属于正常差异,不影响学习。
Q: MedHouseVal 为什么最大只有 5.0?
A:数据集制作时对高价区域做了截断(censoring),这是真实数据中常见的「封顶」现象。
Q:相关系数 0.69 算高吗?
A:在社会科学 / 房价这类问题里,单一特征能达到 0.6~0.7 已经相当不错;说明收入是强信号,但仍有大量方差需要其他特征或更复杂模型解释。
Q:图保存在哪?需要手动打开吗?
A:在 project_01_housing/reports/figures/,用资源管理器或 IDE 直接打开 PNG 即可。
2.14 本步小结
| 发现 | 内容 |
|---|---|
| 数据规模 | 约 2 万条区域记录,9 列(8 特征 + 1 标签) |
| 最强相关特征 | MedInc(收入中位数),r ≈ +0.69 |
| 目标分布 | 右偏,低价区域多,高价长尾 |
| 下一步 | 划分训练集与测试集,为建模做准备 |
2.15 学习记录(请你填写)
- 完成日期:
- 动手任务完成情况:任务 A / B / C / D
- 我看到的图表现象(用自己的话写 1~3 句):
- 疑问(如有):
步骤 3:划分训练集与测试集
状态:✅ 已完成教学(已按详细讲解规范增补名词解释与 Mermaid 图)
3.1 本步目标
在正式训练模型之前,把数据切成两块:
- 训练集(80%):给模型「学习」用
- 测试集(20%):给模型「考试」用,模拟未来没见过的新数据
本步要建立的核心习惯:永远不要把测试集混进训练过程。
3.2 这一步在解决什么问题?
想象你在备考:
- 用练习题学习 → 训练集
- 用从未见过的模拟卷检验水平 → 测试集
若用同一份题既背答案又自测,分数会虚高。机器学习也一样:若在「考过的题」上评估,模型可能只是背住了数据 ,对新区域预测很差。这叫过拟合,测试集就是用来发现这个问题的。
3.2.5 本步在整体流程中的位置
#mermaid-svg-cHvwxh1PGhIRQIFK{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cHvwxh1PGhIRQIFK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cHvwxh1PGhIRQIFK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cHvwxh1PGhIRQIFK .error-icon{fill:#552222;}#mermaid-svg-cHvwxh1PGhIRQIFK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cHvwxh1PGhIRQIFK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cHvwxh1PGhIRQIFK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cHvwxh1PGhIRQIFK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cHvwxh1PGhIRQIFK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cHvwxh1PGhIRQIFK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cHvwxh1PGhIRQIFK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cHvwxh1PGhIRQIFK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cHvwxh1PGhIRQIFK .marker.cross{stroke:#333333;}#mermaid-svg-cHvwxh1PGhIRQIFK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cHvwxh1PGhIRQIFK p{margin:0;}#mermaid-svg-cHvwxh1PGhIRQIFK .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cHvwxh1PGhIRQIFK .cluster-label text{fill:#333;}#mermaid-svg-cHvwxh1PGhIRQIFK .cluster-label span{color:#333;}#mermaid-svg-cHvwxh1PGhIRQIFK .cluster-label span p{background-color:transparent;}#mermaid-svg-cHvwxh1PGhIRQIFK .label text,#mermaid-svg-cHvwxh1PGhIRQIFK span{fill:#333;color:#333;}#mermaid-svg-cHvwxh1PGhIRQIFK .node rect,#mermaid-svg-cHvwxh1PGhIRQIFK .node circle,#mermaid-svg-cHvwxh1PGhIRQIFK .node ellipse,#mermaid-svg-cHvwxh1PGhIRQIFK .node polygon,#mermaid-svg-cHvwxh1PGhIRQIFK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cHvwxh1PGhIRQIFK .rough-node .label text,#mermaid-svg-cHvwxh1PGhIRQIFK .node .label text,#mermaid-svg-cHvwxh1PGhIRQIFK .image-shape .label,#mermaid-svg-cHvwxh1PGhIRQIFK .icon-shape .label{text-anchor:middle;}#mermaid-svg-cHvwxh1PGhIRQIFK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cHvwxh1PGhIRQIFK .rough-node .label,#mermaid-svg-cHvwxh1PGhIRQIFK .node .label,#mermaid-svg-cHvwxh1PGhIRQIFK .image-shape .label,#mermaid-svg-cHvwxh1PGhIRQIFK .icon-shape .label{text-align:center;}#mermaid-svg-cHvwxh1PGhIRQIFK .node.clickable{cursor:pointer;}#mermaid-svg-cHvwxh1PGhIRQIFK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cHvwxh1PGhIRQIFK .arrowheadPath{fill:#333333;}#mermaid-svg-cHvwxh1PGhIRQIFK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cHvwxh1PGhIRQIFK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cHvwxh1PGhIRQIFK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cHvwxh1PGhIRQIFK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cHvwxh1PGhIRQIFK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cHvwxh1PGhIRQIFK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cHvwxh1PGhIRQIFK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cHvwxh1PGhIRQIFK .cluster text{fill:#333;}#mermaid-svg-cHvwxh1PGhIRQIFK .cluster span{color:#333;}#mermaid-svg-cHvwxh1PGhIRQIFK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cHvwxh1PGhIRQIFK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cHvwxh1PGhIRQIFK rect.text{fill:none;stroke-width:0;}#mermaid-svg-cHvwxh1PGhIRQIFK .icon-shape,#mermaid-svg-cHvwxh1PGhIRQIFK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cHvwxh1PGhIRQIFK .icon-shape p,#mermaid-svg-cHvwxh1PGhIRQIFK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cHvwxh1PGhIRQIFK .icon-shape .label rect,#mermaid-svg-cHvwxh1PGhIRQIFK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cHvwxh1PGhIRQIFK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cHvwxh1PGhIRQIFK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cHvwxh1PGhIRQIFK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
步骤2 已了解数据
步骤3 划分 X/y 与 train/test
步骤4 只在 X_train 上 fit
步骤4 用 X_test 评估
测试集表现好?
继续优化模型
检查泄露或过拟合
3.2.6 名词解释(本步首次出现)
| 名词 | 是什么 | 为什么需要 | 在本项目中 | 易混淆 |
|---|---|---|---|---|
| X(特征矩阵) | 所有输入特征组成的表格 | 模型学习的是 X→y 的映射 | 8 列,16346/4087 行 | 不含房价列 |
| y(标签向量) | 要预测的目标一列 | 监督学习需要标准答案 | MedHouseVal |
一维,不是矩阵 |
| train_test_split | sklearn 随机划分训练/测试集的函数 | 公平评估泛化能力 | 80% 训练,20% 测试 | 不是按顺序切 |
| 泛化能力 | 模型对未见过数据的表现 | 部署后面对新区域能否准 | 用测试集 RMSE 衡量 | 不是训练集表现 |
| 过拟合 | 训练集很好、新数据变差 | 模型「背题」而非学规律 | 步骤4若 train RMSE 远小于 test 需警惕 | 不是欠拟合 |
| 数据泄露 | 测试集信息渗入训练过程 | 会导致评估虚高、上线后翻车 | 测试集不能参与 fit | 与缺失值无关 |
| random_state | 随机数种子 | 保证每次划分结果相同,实验可复现 | 固定为 42 | 不是模型参数 |
3.3 任务清单
- 分离
X(8 列特征)和y(MedHouseVal) - 使用
train_test_split(X, y, test_size=0.2, random_state=42) - 打印训练集、测试集形状与占比
- 对比训练集/测试集房价均值,检查划分是否均衡
- 绘制中文对比图
04_train_test_split.png
3.4 运行本步
powershell
cd "d:\JavaCode\机器学习\project_01_housing"
python src/train.py
你这步应看到的关键输出:
| 项目 | 数值 |
|---|---|
X_train 形状 |
(16346, 8) |
X_test 形状 |
(4087, 8) |
| 训练集占比 | 80.0% |
| 测试集占比 | 20.0% |
| 训练集房价均值 | 约 2.0664 |
| 测试集房价均值 | 约 2.0774 |
训练集与测试集的房价均值非常接近,说明随机划分后两边分布较均衡,评估会更公平。
3.6 数据划分与使用规则(Mermaid)
#mermaid-svg-Z0Blt145SZyMuQEc{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Z0Blt145SZyMuQEc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Z0Blt145SZyMuQEc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Z0Blt145SZyMuQEc .error-icon{fill:#552222;}#mermaid-svg-Z0Blt145SZyMuQEc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Z0Blt145SZyMuQEc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Z0Blt145SZyMuQEc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Z0Blt145SZyMuQEc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Z0Blt145SZyMuQEc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Z0Blt145SZyMuQEc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Z0Blt145SZyMuQEc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Z0Blt145SZyMuQEc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Z0Blt145SZyMuQEc .marker.cross{stroke:#333333;}#mermaid-svg-Z0Blt145SZyMuQEc svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Z0Blt145SZyMuQEc p{margin:0;}#mermaid-svg-Z0Blt145SZyMuQEc .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Z0Blt145SZyMuQEc .cluster-label text{fill:#333;}#mermaid-svg-Z0Blt145SZyMuQEc .cluster-label span{color:#333;}#mermaid-svg-Z0Blt145SZyMuQEc .cluster-label span p{background-color:transparent;}#mermaid-svg-Z0Blt145SZyMuQEc .label text,#mermaid-svg-Z0Blt145SZyMuQEc span{fill:#333;color:#333;}#mermaid-svg-Z0Blt145SZyMuQEc .node rect,#mermaid-svg-Z0Blt145SZyMuQEc .node circle,#mermaid-svg-Z0Blt145SZyMuQEc .node ellipse,#mermaid-svg-Z0Blt145SZyMuQEc .node polygon,#mermaid-svg-Z0Blt145SZyMuQEc .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Z0Blt145SZyMuQEc .rough-node .label text,#mermaid-svg-Z0Blt145SZyMuQEc .node .label text,#mermaid-svg-Z0Blt145SZyMuQEc .image-shape .label,#mermaid-svg-Z0Blt145SZyMuQEc .icon-shape .label{text-anchor:middle;}#mermaid-svg-Z0Blt145SZyMuQEc .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Z0Blt145SZyMuQEc .rough-node .label,#mermaid-svg-Z0Blt145SZyMuQEc .node .label,#mermaid-svg-Z0Blt145SZyMuQEc .image-shape .label,#mermaid-svg-Z0Blt145SZyMuQEc .icon-shape .label{text-align:center;}#mermaid-svg-Z0Blt145SZyMuQEc .node.clickable{cursor:pointer;}#mermaid-svg-Z0Blt145SZyMuQEc .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Z0Blt145SZyMuQEc .arrowheadPath{fill:#333333;}#mermaid-svg-Z0Blt145SZyMuQEc .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Z0Blt145SZyMuQEc .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Z0Blt145SZyMuQEc .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Z0Blt145SZyMuQEc .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Z0Blt145SZyMuQEc .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Z0Blt145SZyMuQEc .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Z0Blt145SZyMuQEc .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Z0Blt145SZyMuQEc .cluster text{fill:#333;}#mermaid-svg-Z0Blt145SZyMuQEc .cluster span{color:#333;}#mermaid-svg-Z0Blt145SZyMuQEc div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Z0Blt145SZyMuQEc .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Z0Blt145SZyMuQEc rect.text{fill:none;stroke-width:0;}#mermaid-svg-Z0Blt145SZyMuQEc .icon-shape,#mermaid-svg-Z0Blt145SZyMuQEc .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Z0Blt145SZyMuQEc .icon-shape p,#mermaid-svg-Z0Blt145SZyMuQEc .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Z0Blt145SZyMuQEc .icon-shape .label rect,#mermaid-svg-Z0Blt145SZyMuQEc .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Z0Blt145SZyMuQEc .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Z0Blt145SZyMuQEc .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Z0Blt145SZyMuQEc :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 全部 20433 条
train_test_split 80/20
训练集 16346 条
测试集 4087 条
model.fit 训练集 允许
model.predict 测试集 允许
测试集禁止 fit
四条铁律:
fit只用X_train,y_trainpredict可对X_test预测,再与y_test对比- 不要用
X_test参与任何「学习统计量」的步骤(缩放、填充等,步骤 5 会强调) - 测试集对模型来说是「未来的新区域」
3.7 核心代码解读
(1)分离特征与标签
python
X = df.drop(columns=[TARGET_COL]) # 8 个输入特征
y = df[TARGET_COL] # 1 个目标:房价中位数
| 符号 | 含义 | 形状 |
|---|---|---|
X |
特征矩阵 | (样本数, 8) |
y |
标签向量 | (样本数,) |
一行数据 :X 的一行是某区域的 8 个特征,y 的对应值是该区域真实的房价中位数。
(2)随机划分
python
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2, # 20% 测试,80% 训练
random_state=42, # 固定随机种子,结果可复现
)
参数说明:
| 参数 | 作用 |
|---|---|
test_size=0.2 |
20% 样本进测试集 |
random_state=42 |
固定随机种子,每次运行划分结果相同(便于复现与调试) |
四个变量的用途:
| 变量 | 用途 |
|---|---|
X_train, y_train |
步骤 4 起用于 model.fit() 训练 |
X_test, y_test |
只在评估时用 model.predict(),不参与训练 |
(3)可视化划分结果
新增函数 visualize_train_test_split() 生成中文条形图:
- 标题:训练集与测试集样本数量对比
- 柱顶数字:16346 / 4087
- 底部说明:训练集 80.0% | 测试集 20.0%
3.8 动手任务
任务 A:运行并核对
-
X_train约 16346 行,X_test约 4087 行 - 比例为 8:2
- 生成
04_train_test_split.png
任务 B:改 random_state 观察(建议)
把 RANDOM_STATE = 42 改成 0 或 100,重新运行,观察划分数量不变、但训练/测试均值可能略变。再改回 42,与文档结果对齐。
任务 C:思考一题
若把 test_size 改成 0.5,训练集和测试集各多少条?(答:各约 10216 条)训练数据变少会对模型有什么影响?(答:学得少一些,通常方差更大;此题先建立直觉即可。)
任务 D:在 README.md 记录
用一句话说明:为什么需要测试集。
3.9 验收标准
- 能区分
X/y、X_train/X_test/y_train/y_test - 能解释训练集与测试集各自用途
- 能说明为何不能用全部数据既训练又评估
- 知道
random_state用于可复现 - 划分比例约为 8:2
3.10 本步核心概念
3.10 动手任务与验收标准参考答案
以下为教学标准答案,便于自学对照;
README.md学习记录仍建议用自己的话写。
动手任务答案
| 任务 | 参考答案 |
|---|---|
| A | X_train (16346,8),X_test (4087,8);04_train_test_split.png。 |
| B | 改 random_state 数量不变、均值略变;改回 42 对齐文档。 |
| C | test_size=0.5 各约 10216 条;训练变少,模型可能更不稳定。 |
| D | 测试集模拟未来新数据,检验泛化。 |
验收标准答案
| 验收项 | 参考答案 |
|---|---|
| X/y 与划分 | X 8 列特征,y 为房价;train 学、test 考。 |
| 用途 | 训练 fit,测试 predict 评估。 |
| 不能全量既训又评 | 会虚高、无法发现过拟合。 |
| random_state | 固定种子保证可复现。 |
| 8:2 | 16346 / 4087。 |
| 概念 | 解释 |
|---|---|
| 泛化能力 | 模型对未见过数据的表现好坏 |
| 过拟合 | 在训练集上很好、在新数据上变差(像死记硬背) |
| 测试集 | 模拟未来新数据,只用于最终评估 |
| 数据泄露 | 测试集信息渗入训练过程,导致评估失真 |
| random_state | 控制随机划分的种子,保证实验可复现 |
3.11 常见问题
Q:为什么不用 100% 数据训练?
A:没有留出测试集,就无法知道模型对新数据好不好。就像没有模拟卷就无法检验真实水平。
Q: random_state=42 有什么特殊吗?
A:没有,只是社区常用的示例值。任何固定整数都可以,关键是固定下来便于复现。
Q:划分后特征数还是 8 吗?
A:是。划分只改变行数 (样本数),不改变列数(特征数)。
Q:步骤 2 的 EDA 图还能生成吗?
A:explore_data() 仍在 train.py 中,需要时可单独调用;main() 当前聚焦步骤 3,避免每次重复画图。复习步骤 2 可在 Python 里手动调用 explore_data(load_data())。
3.12 本步小结
| 要点 | 内容 |
|---|---|
| 特征 X | 8 列,不含房价 |
| 标签 y | MedHouseVal |
| 划分比例 | 80% 训练 / 20% 测试 |
| 下一步 | 在 X_train 上训练线性回归基准模型 |
3.13 学习记录(请你填写)
- 完成日期:
- 动手任务完成情况:任务 A / B / C / D
- 用一句话解释为何要测试集:
- 疑问(如有):
步骤 4:建立基准模型 ------ 线性回归
状态:✅ 已完成教学(已按详细讲解规范增补名词解释与 Mermaid 图)
4.1 本步目标
第一次真正训练机器学习模型 。用线性回归在训练集上学习,在测试集上评估,得到后续所有模型都要对比的 Baseline(基准) 指标。
4.2 这一步在解决什么问题?
EDA 只能「看」规律,模型才能「学」规律并给出数值预测。
线性回归是最简单的回归模型,适合作为第一条基准线:后面更复杂的模型,只有比它更好才有意义。
4.2.5 本步在整体流程中的位置
#mermaid-svg-mGoFCFeZHtsRYwJ6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mGoFCFeZHtsRYwJ6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .error-icon{fill:#552222;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .marker.cross{stroke:#333333;}#mermaid-svg-mGoFCFeZHtsRYwJ6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mGoFCFeZHtsRYwJ6 p{margin:0;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .cluster-label text{fill:#333;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .cluster-label span{color:#333;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .cluster-label span p{background-color:transparent;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .label text,#mermaid-svg-mGoFCFeZHtsRYwJ6 span{fill:#333;color:#333;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .node rect,#mermaid-svg-mGoFCFeZHtsRYwJ6 .node circle,#mermaid-svg-mGoFCFeZHtsRYwJ6 .node ellipse,#mermaid-svg-mGoFCFeZHtsRYwJ6 .node polygon,#mermaid-svg-mGoFCFeZHtsRYwJ6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .rough-node .label text,#mermaid-svg-mGoFCFeZHtsRYwJ6 .node .label text,#mermaid-svg-mGoFCFeZHtsRYwJ6 .image-shape .label,#mermaid-svg-mGoFCFeZHtsRYwJ6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .rough-node .label,#mermaid-svg-mGoFCFeZHtsRYwJ6 .node .label,#mermaid-svg-mGoFCFeZHtsRYwJ6 .image-shape .label,#mermaid-svg-mGoFCFeZHtsRYwJ6 .icon-shape .label{text-align:center;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .node.clickable{cursor:pointer;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .arrowheadPath{fill:#333333;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mGoFCFeZHtsRYwJ6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mGoFCFeZHtsRYwJ6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mGoFCFeZHtsRYwJ6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .cluster text{fill:#333;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .cluster span{color:#333;}#mermaid-svg-mGoFCFeZHtsRYwJ6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mGoFCFeZHtsRYwJ6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .icon-shape,#mermaid-svg-mGoFCFeZHtsRYwJ6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .icon-shape p,#mermaid-svg-mGoFCFeZHtsRYwJ6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .icon-shape .label rect,#mermaid-svg-mGoFCFeZHtsRYwJ6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mGoFCFeZHtsRYwJ6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mGoFCFeZHtsRYwJ6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mGoFCFeZHtsRYwJ6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 步骤3 已有 train/test
步骤4 fit 线性回归
predict 测试集
算 RMSE MAE R2
记录 Baseline
步骤5~8 与 Baseline 对比
4.2.6 名词解释(本步首次出现)
| 名词 | 是什么 | 为什么需要 | 在本项目中 | 易混淆 |
|---|---|---|---|---|
| fit(拟合/训练) | 用训练数据学习模型内部参数 | 模型不会自己变聪明,必须学习 | model.fit(X_train, y_train) |
不能对测试集 fit |
| predict(预测) | 用已训练模型输出预测值 | 评估模型是否好用 | model.predict(X_test) |
不是算指标 |
| Baseline | 第一个可对比的基准成绩 | 后续模型需证明「比它强」 | 测试 RMSE=0.7514 | 不是最终模型 |
| 线性回归 | 用特征的线性组合预测目标 | 最简单、可解释的回归模型 | LinearRegression |
不是逻辑回归 |
| 系数 coef | 每个特征对预测的贡献权重 | 理解「哪个因素影响房价」 | MedInc 系数约 0.44 | 未缩放时不便比大小 |
| 截距 intercept | 所有特征为 0 时的基准值 | 完整线性方程的一部分 | 约 -36.84 | 单独解读意义有限 |
| RMSE | 均方根误差,典型预测偏差大小 | 回归最常用的误差指标之一 | 测试集 0.7514 | 越小越好 |
| MAE | 平均绝对误差 | 对极端误差不那么敏感 | 测试集 0.5400 | 越小越好 |
| R2 | 决定系数,解释力 | 比「总猜均值」好多少 | 测试集 0.5871 | 越接近 1 越好 |
| 最小二乘 | 使误差平方和最小的训练方法 | 线性回归的经典目标 | sklearn 默认优化目标 | 不是梯度提升 |
4.3 任务清单
-
LinearRegression在训练集上fit - 在测试集上
predict - 计算 RMSE、MAE、R2
- 画「真实值 vs 预测值」散点图(中文)
- 保存指标报告
reports/baseline_linear_regression.txt
4.4 运行本步
powershell
cd "d:\JavaCode\机器学习\project_01_housing"
python src/train.py
你这步应看到的关键结果:
| 指标 | 训练集 | 测试集(Baseline) |
|---|---|---|
| RMSE | 0.7185 | 0.7514 |
| MAE | 0.5271 | 0.5400 |
| R2 | 0.6100 | 0.5871 |
| 模型参数 | 数值 | 含义 |
|---|---|---|
| 截距 intercept | -36.8404 | 线性方程的常数项 |
| MedInc 系数 | 0.4447 | 收入每增加 1 单位,预测房价约增加 0.44(十万美元) |
如何读这些数?
- RMSE ≈ 0.75 :典型预测误差约 0.75(十万美元),即约 7500 美元量级
- R2 ≈ 0.59 :模型能解释约 59% 的房价波动(相对「永远猜均值」)
- 测试集 RMSE 略高于训练集 → 轻微泛化差距,正常,暂无明显严重过拟合
4.5 机器学习三步曲(本步完整走通)
测试集 训练集 模型 用户 测试集 训练集 模型 用户 #mermaid-svg-UejuGEfB8hh5JmKM{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UejuGEfB8hh5JmKM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UejuGEfB8hh5JmKM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UejuGEfB8hh5JmKM .error-icon{fill:#552222;}#mermaid-svg-UejuGEfB8hh5JmKM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UejuGEfB8hh5JmKM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UejuGEfB8hh5JmKM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UejuGEfB8hh5JmKM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UejuGEfB8hh5JmKM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UejuGEfB8hh5JmKM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UejuGEfB8hh5JmKM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UejuGEfB8hh5JmKM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UejuGEfB8hh5JmKM .marker.cross{stroke:#333333;}#mermaid-svg-UejuGEfB8hh5JmKM svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UejuGEfB8hh5JmKM p{margin:0;}#mermaid-svg-UejuGEfB8hh5JmKM .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-UejuGEfB8hh5JmKM text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-UejuGEfB8hh5JmKM .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-UejuGEfB8hh5JmKM .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-UejuGEfB8hh5JmKM .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-UejuGEfB8hh5JmKM .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-UejuGEfB8hh5JmKM #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-UejuGEfB8hh5JmKM .sequenceNumber{fill:white;}#mermaid-svg-UejuGEfB8hh5JmKM #sequencenumber{fill:#333;}#mermaid-svg-UejuGEfB8hh5JmKM #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-UejuGEfB8hh5JmKM .messageText{fill:#333;stroke:none;}#mermaid-svg-UejuGEfB8hh5JmKM .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-UejuGEfB8hh5JmKM .labelText,#mermaid-svg-UejuGEfB8hh5JmKM .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-UejuGEfB8hh5JmKM .loopText,#mermaid-svg-UejuGEfB8hh5JmKM .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-UejuGEfB8hh5JmKM .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-UejuGEfB8hh5JmKM .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-UejuGEfB8hh5JmKM .noteText,#mermaid-svg-UejuGEfB8hh5JmKM .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-UejuGEfB8hh5JmKM .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-UejuGEfB8hh5JmKM .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-UejuGEfB8hh5JmKM .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-UejuGEfB8hh5JmKM .actorPopupMenu{position:absolute;}#mermaid-svg-UejuGEfB8hh5JmKM .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-UejuGEfB8hh5JmKM .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-UejuGEfB8hh5JmKM .actor-man circle,#mermaid-svg-UejuGEfB8hh5JmKM line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-UejuGEfB8hh5JmKM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 只在训练集上学习 计算 RMSE MAE R2 创建 LinearRegression 提供 X_train y_train fit 训练集 predict 测试集 输出 y_pred 对比 y_test 与 y_pred
python
model = LinearRegression()
model.fit(X_train, y_train) # 只在训练集上学
y_test_pred = model.predict(X_test) # 对测试集预测
切忌 :fit 时不能传入 X_test / y_test。
4.6 三个评估指标
| 指标 | 全称 | 直觉 | 好坏 |
|---|---|---|---|
| RMSE | 均方根误差 | 预测偏差典型大小,与房价同单位 | 越小越好 |
| MAE | 平均绝对误差 | 绝对误差的平均,对极端值不如 RMSE 敏感 | 越小越好 |
| R2 | 决定系数 | 比「总猜均值」好多少 | 越接近 1 越好 |
R2 通俗理解:
- R2 = 0 → 和猜均值差不多
- R2 = 0.59 → 比猜均值好很多
- R2 = 1 → 完美预测(实际几乎达不到)
4.7 线性回归在做什么?
对每个特征学一个权重(系数) ,再加一个截距:
预测房价 = intercept + c1×MedInc + c2×HouseAge + ... + c8×Longitude
最小二乘 的目标:找一组系数,使所有训练样本的误差平方和最小。
#mermaid-svg-5AtRtJoBtPqpvCu7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-5AtRtJoBtPqpvCu7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5AtRtJoBtPqpvCu7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5AtRtJoBtPqpvCu7 .error-icon{fill:#552222;}#mermaid-svg-5AtRtJoBtPqpvCu7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5AtRtJoBtPqpvCu7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5AtRtJoBtPqpvCu7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5AtRtJoBtPqpvCu7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5AtRtJoBtPqpvCu7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5AtRtJoBtPqpvCu7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5AtRtJoBtPqpvCu7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5AtRtJoBtPqpvCu7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5AtRtJoBtPqpvCu7 .marker.cross{stroke:#333333;}#mermaid-svg-5AtRtJoBtPqpvCu7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5AtRtJoBtPqpvCu7 p{margin:0;}#mermaid-svg-5AtRtJoBtPqpvCu7 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-5AtRtJoBtPqpvCu7 .cluster-label text{fill:#333;}#mermaid-svg-5AtRtJoBtPqpvCu7 .cluster-label span{color:#333;}#mermaid-svg-5AtRtJoBtPqpvCu7 .cluster-label span p{background-color:transparent;}#mermaid-svg-5AtRtJoBtPqpvCu7 .label text,#mermaid-svg-5AtRtJoBtPqpvCu7 span{fill:#333;color:#333;}#mermaid-svg-5AtRtJoBtPqpvCu7 .node rect,#mermaid-svg-5AtRtJoBtPqpvCu7 .node circle,#mermaid-svg-5AtRtJoBtPqpvCu7 .node ellipse,#mermaid-svg-5AtRtJoBtPqpvCu7 .node polygon,#mermaid-svg-5AtRtJoBtPqpvCu7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5AtRtJoBtPqpvCu7 .rough-node .label text,#mermaid-svg-5AtRtJoBtPqpvCu7 .node .label text,#mermaid-svg-5AtRtJoBtPqpvCu7 .image-shape .label,#mermaid-svg-5AtRtJoBtPqpvCu7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-5AtRtJoBtPqpvCu7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5AtRtJoBtPqpvCu7 .rough-node .label,#mermaid-svg-5AtRtJoBtPqpvCu7 .node .label,#mermaid-svg-5AtRtJoBtPqpvCu7 .image-shape .label,#mermaid-svg-5AtRtJoBtPqpvCu7 .icon-shape .label{text-align:center;}#mermaid-svg-5AtRtJoBtPqpvCu7 .node.clickable{cursor:pointer;}#mermaid-svg-5AtRtJoBtPqpvCu7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5AtRtJoBtPqpvCu7 .arrowheadPath{fill:#333333;}#mermaid-svg-5AtRtJoBtPqpvCu7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5AtRtJoBtPqpvCu7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5AtRtJoBtPqpvCu7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5AtRtJoBtPqpvCu7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5AtRtJoBtPqpvCu7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5AtRtJoBtPqpvCu7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5AtRtJoBtPqpvCu7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5AtRtJoBtPqpvCu7 .cluster text{fill:#333;}#mermaid-svg-5AtRtJoBtPqpvCu7 .cluster span{color:#333;}#mermaid-svg-5AtRtJoBtPqpvCu7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-5AtRtJoBtPqpvCu7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5AtRtJoBtPqpvCu7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-5AtRtJoBtPqpvCu7 .icon-shape,#mermaid-svg-5AtRtJoBtPqpvCu7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5AtRtJoBtPqpvCu7 .icon-shape p,#mermaid-svg-5AtRtJoBtPqpvCu7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5AtRtJoBtPqpvCu7 .icon-shape .label rect,#mermaid-svg-5AtRtJoBtPqpvCu7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5AtRtJoBtPqpvCu7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5AtRtJoBtPqpvCu7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5AtRtJoBtPqpvCu7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 线性回归公式
预测房价 y_hat
截距 b
MedInc x w1
HouseAge x w2
共8个特征
通俗理解:模型在找一条(高维空间中的)直线/超平面,让所有训练点的预测值尽量接近真实房价。
4.8 预测效果图
reports/figures/05_baseline_pred_vs_true.png
- 标题:线性回归:真实房价 vs 预测房价(测试集)
- 红色虚线:理想预测线 y = x(点落在线上 = 预测完美)
- 典型现象:点沿对角线分布,但有分散 → 模型抓住了大趋势,仍有误差
#mermaid-svg-xXyvV7A7qTuqbXn0{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xXyvV7A7qTuqbXn0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xXyvV7A7qTuqbXn0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xXyvV7A7qTuqbXn0 .error-icon{fill:#552222;}#mermaid-svg-xXyvV7A7qTuqbXn0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xXyvV7A7qTuqbXn0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xXyvV7A7qTuqbXn0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xXyvV7A7qTuqbXn0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xXyvV7A7qTuqbXn0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xXyvV7A7qTuqbXn0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xXyvV7A7qTuqbXn0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xXyvV7A7qTuqbXn0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xXyvV7A7qTuqbXn0 .marker.cross{stroke:#333333;}#mermaid-svg-xXyvV7A7qTuqbXn0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xXyvV7A7qTuqbXn0 p{margin:0;}#mermaid-svg-xXyvV7A7qTuqbXn0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xXyvV7A7qTuqbXn0 .cluster-label text{fill:#333;}#mermaid-svg-xXyvV7A7qTuqbXn0 .cluster-label span{color:#333;}#mermaid-svg-xXyvV7A7qTuqbXn0 .cluster-label span p{background-color:transparent;}#mermaid-svg-xXyvV7A7qTuqbXn0 .label text,#mermaid-svg-xXyvV7A7qTuqbXn0 span{fill:#333;color:#333;}#mermaid-svg-xXyvV7A7qTuqbXn0 .node rect,#mermaid-svg-xXyvV7A7qTuqbXn0 .node circle,#mermaid-svg-xXyvV7A7qTuqbXn0 .node ellipse,#mermaid-svg-xXyvV7A7qTuqbXn0 .node polygon,#mermaid-svg-xXyvV7A7qTuqbXn0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xXyvV7A7qTuqbXn0 .rough-node .label text,#mermaid-svg-xXyvV7A7qTuqbXn0 .node .label text,#mermaid-svg-xXyvV7A7qTuqbXn0 .image-shape .label,#mermaid-svg-xXyvV7A7qTuqbXn0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-xXyvV7A7qTuqbXn0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xXyvV7A7qTuqbXn0 .rough-node .label,#mermaid-svg-xXyvV7A7qTuqbXn0 .node .label,#mermaid-svg-xXyvV7A7qTuqbXn0 .image-shape .label,#mermaid-svg-xXyvV7A7qTuqbXn0 .icon-shape .label{text-align:center;}#mermaid-svg-xXyvV7A7qTuqbXn0 .node.clickable{cursor:pointer;}#mermaid-svg-xXyvV7A7qTuqbXn0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xXyvV7A7qTuqbXn0 .arrowheadPath{fill:#333333;}#mermaid-svg-xXyvV7A7qTuqbXn0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xXyvV7A7qTuqbXn0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xXyvV7A7qTuqbXn0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xXyvV7A7qTuqbXn0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xXyvV7A7qTuqbXn0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xXyvV7A7qTuqbXn0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xXyvV7A7qTuqbXn0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xXyvV7A7qTuqbXn0 .cluster text{fill:#333;}#mermaid-svg-xXyvV7A7qTuqbXn0 .cluster span{color:#333;}#mermaid-svg-xXyvV7A7qTuqbXn0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xXyvV7A7qTuqbXn0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xXyvV7A7qTuqbXn0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-xXyvV7A7qTuqbXn0 .icon-shape,#mermaid-svg-xXyvV7A7qTuqbXn0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xXyvV7A7qTuqbXn0 .icon-shape p,#mermaid-svg-xXyvV7A7qTuqbXn0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xXyvV7A7qTuqbXn0 .icon-shape .label rect,#mermaid-svg-xXyvV7A7qTuqbXn0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xXyvV7A7qTuqbXn0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xXyvV7A7qTuqbXn0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xXyvV7A7qTuqbXn0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 散点图解读
点靠近红线 y=x
预测较准
点远离红线
预测误差大
4.9 动手任务
任务 A:运行脚本,核对测试集 RMSE ≈ 0.75、R2 ≈ 0.59
任务 B :打开 baseline_linear_regression.txt,记录 Baseline 数字
任务 C:思考------若 RMSE = 0.75(十万美元单位),大约相当于预测偏差多少美元?(答:约 7500 美元)
任务 D :在 README.md 写下你对 R2 的一句话理解
4.10 验收标准
- 能说出
fit/predict各自做什么 - 能解释 RMSE、MAE、R2 的含义
- 知道 Baseline 是后续模型的比较起点
- 能读预测散点图,理解点离对角线越远误差越大
4.11 本步核心概念
4.11 动手任务与验收标准参考答案
以下为教学标准答案,便于自学对照;
README.md学习记录仍建议用自己的话写。
动手任务答案
| 任务 | 参考答案 |
|---|---|
| A | 测试 RMSE≈0.7514,R2≈0.5871。 |
| B | baseline_linear_regression.txt 记录上述数字。 |
| C | 0.75 十万美元 ≈ 7500 美元偏差。 |
| D | R2≈0.59:比永远猜均价多解释约 59% 波动。 |
验收标准答案
| 验收项 | 参考答案 |
|---|---|
| fit/predict | fit 学习;predict 输出预测。 |
| RMSE/MAE/R2 | 误差越小越好;R2 越接近 1 越好。 |
| Baseline | 测试 RMSE 0.7514 为比较起点。 |
| 散点图 | 离 y=x 越远误差越大。 |
| 概念 | 解释 |
|---|---|
| Baseline | 第一个可参考的模型成绩 |
| fit | 用训练数据学习模型参数 |
| predict | 用学到的模型输出预测值 |
| RMSE / MAE | 回归误差指标 |
| R2 | 模型解释力 |
| 最小二乘 | 线性回归的经典训练目标 |
4.12 常见问题
Q:截距 -36.84 很大且为负,正常吗?
A:线性回归的截距要和其他特征系数一起看,单独解读意义有限;未缩放时多个特征尺度不同,截距可能看起来「奇怪」。步骤 5 缩放后会改善解读。
Q:为什么看测试集指标而不是训练集?
A:训练集指标反映「背题」能力,测试集才反映「真考试」能力。
Q:R2 用 R² 还是 R2?
A:数学上常写 R²;本项目中终端打印用 R2 避免 Windows GBK 编码问题,含义相同。
4.13 本步小结
| 要点 | 内容 |
|---|---|
| 模型 | LinearRegression |
| Baseline 测试集 RMSE | 0.7514 |
| Baseline 测试集 R2 | 0.5871 |
| 下一步 | 特征缩放 + Ridge / Lasso |
4.14 学习记录(请你填写)
- 完成日期:
- 动手任务完成情况:任务 A / B / C / D
- 我对 R2 的理解:
- 疑问(如有):
步骤 5:特征缩放与 Ridge / Lasso
状态:✅ 已完成教学(已按详细讲解规范增补名词解释与 Mermaid 图)
5.1 本步目标
- 理解特征标准化为何对线性模型重要
- 学习 Ridge(L2) 与 Lasso(L1) 正则化
- 对比多种线性模型,选出测试集表现最佳者
5.2 这一步在解决什么问题?
步骤 4 的线性回归在未缩放特征上训练。各特征量纲不同(收入、人口、经纬度数值范围差很多),会导致:
- 系数大小不可直接比较
- 正则化惩罚不公平(大数值特征更容易被「冤枉」)
本步通过 StandardScaler 统一尺度,再用 Ridge / Lasso 控制过拟合。
5.2.5 本步在整体流程中的位置
#mermaid-svg-eI8j9IQTHRbjuhxQ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-eI8j9IQTHRbjuhxQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eI8j9IQTHRbjuhxQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eI8j9IQTHRbjuhxQ .error-icon{fill:#552222;}#mermaid-svg-eI8j9IQTHRbjuhxQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eI8j9IQTHRbjuhxQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eI8j9IQTHRbjuhxQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eI8j9IQTHRbjuhxQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eI8j9IQTHRbjuhxQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eI8j9IQTHRbjuhxQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eI8j9IQTHRbjuhxQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eI8j9IQTHRbjuhxQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eI8j9IQTHRbjuhxQ .marker.cross{stroke:#333333;}#mermaid-svg-eI8j9IQTHRbjuhxQ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eI8j9IQTHRbjuhxQ p{margin:0;}#mermaid-svg-eI8j9IQTHRbjuhxQ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eI8j9IQTHRbjuhxQ .cluster-label text{fill:#333;}#mermaid-svg-eI8j9IQTHRbjuhxQ .cluster-label span{color:#333;}#mermaid-svg-eI8j9IQTHRbjuhxQ .cluster-label span p{background-color:transparent;}#mermaid-svg-eI8j9IQTHRbjuhxQ .label text,#mermaid-svg-eI8j9IQTHRbjuhxQ span{fill:#333;color:#333;}#mermaid-svg-eI8j9IQTHRbjuhxQ .node rect,#mermaid-svg-eI8j9IQTHRbjuhxQ .node circle,#mermaid-svg-eI8j9IQTHRbjuhxQ .node ellipse,#mermaid-svg-eI8j9IQTHRbjuhxQ .node polygon,#mermaid-svg-eI8j9IQTHRbjuhxQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eI8j9IQTHRbjuhxQ .rough-node .label text,#mermaid-svg-eI8j9IQTHRbjuhxQ .node .label text,#mermaid-svg-eI8j9IQTHRbjuhxQ .image-shape .label,#mermaid-svg-eI8j9IQTHRbjuhxQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-eI8j9IQTHRbjuhxQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-eI8j9IQTHRbjuhxQ .rough-node .label,#mermaid-svg-eI8j9IQTHRbjuhxQ .node .label,#mermaid-svg-eI8j9IQTHRbjuhxQ .image-shape .label,#mermaid-svg-eI8j9IQTHRbjuhxQ .icon-shape .label{text-align:center;}#mermaid-svg-eI8j9IQTHRbjuhxQ .node.clickable{cursor:pointer;}#mermaid-svg-eI8j9IQTHRbjuhxQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-eI8j9IQTHRbjuhxQ .arrowheadPath{fill:#333333;}#mermaid-svg-eI8j9IQTHRbjuhxQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eI8j9IQTHRbjuhxQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eI8j9IQTHRbjuhxQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eI8j9IQTHRbjuhxQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-eI8j9IQTHRbjuhxQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eI8j9IQTHRbjuhxQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-eI8j9IQTHRbjuhxQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eI8j9IQTHRbjuhxQ .cluster text{fill:#333;}#mermaid-svg-eI8j9IQTHRbjuhxQ .cluster span{color:#333;}#mermaid-svg-eI8j9IQTHRbjuhxQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-eI8j9IQTHRbjuhxQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-eI8j9IQTHRbjuhxQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-eI8j9IQTHRbjuhxQ .icon-shape,#mermaid-svg-eI8j9IQTHRbjuhxQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eI8j9IQTHRbjuhxQ .icon-shape p,#mermaid-svg-eI8j9IQTHRbjuhxQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-eI8j9IQTHRbjuhxQ .icon-shape .label rect,#mermaid-svg-eI8j9IQTHRbjuhxQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eI8j9IQTHRbjuhxQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-eI8j9IQTHRbjuhxQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-eI8j9IQTHRbjuhxQ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
步骤4 Baseline RMSE=0.7514
步骤5 标准化特征
训练 Ridge/Lasso 多组 alpha
对比测试 RMSE
是否优于 Baseline?
记录最佳线性模型
仍保留结论供树模型对比
步骤6 树模型 不需缩放
5.2.6 名词解释(本步首次出现)
| 名词 | 是什么 | 为什么需要 | 在本项目中 | 易混淆 |
|---|---|---|---|---|
| StandardScaler | 标准化工具:减均值、除标准差 | 统一特征量纲,线性模型与正则化更公平 | 只在 X_train fit | 不是 MinMaxScaler |
| Z-score 标准化 | 变换后均值≈0、标准差≈1 | 消除「人口几万 vs 纬度30多」的量纲差 | 缩放后各列 mean≈0 std≈1 | 不改变样本行数 |
| fit_transform | 先 fit 再 transform,用于训练集 | 学习均值/标准差并变换 | scaler.fit_transform(X_train) |
不能用于测试集 fit |
| transform | 用已学到的参数变换新数据 | 测试集必须用训练集的统计量 | scaler.transform(X_test) |
不是 fit |
| 正则化 | 在损失函数中加惩罚,限制系数过大 | 缓解过拟合、稳定求解 | Ridge/Lasso 的核心 | 不是特征选择同义词 |
| Ridge(L2) | 惩罚系数平方和 | 系数整体变小,保留全部特征 | alpha 大时变化明显 | 不做稀疏化 |
| Lasso(L1) | 惩罚系数绝对值之和 | 可把部分系数压到 0 | alpha=0.01 最佳 | 不是 Ridge |
| alpha | 正则化强度超参数 | 控制「简单 vs 复杂」 | 0.01 好,0.1 欠拟合 | 不是学习率 |
| 欠拟合 | 模型过于简单,训练/测试都差 | alpha 过大时出现 | Lasso 0.1 RMSE=0.8337 | 不是过拟合 |
| 过拟合 | 训练好、测试差 | 本数据线性回归未严重过拟合 | Ridge 改善很小 | 步骤4 轻微差距正常 |
5.3 任务清单
-
StandardScaler只在X_train上fit - 训练 Ridge(4 组 alpha)、Lasso(4 组 alpha)
- 对比线性回归、Ridge、Lasso 的测试集 RMSE
- 保存对比报告与中文 RMSE 条形图
5.4 运行本步
powershell
cd "d:\JavaCode\机器学习\project_01_housing"
python src/train.py
5.5 实验结果(你的环境)
| 模型 | 测试 RMSE | 测试 R2 |
|---|---|---|
| 线性回归(标准化) | 0.7514 | 0.5871 |
| Ridge(alpha=0.01~1.0) | ≈0.7514 | ≈0.5871 |
| Ridge(alpha=10.0) | 0.7512 | 0.5874 |
| Lasso(alpha=0.001) | 0.7505 | 0.5881 |
| Lasso(alpha=0.01) | 0.7472 | 0.5917 |
| Lasso(alpha=0.1) | 0.8337 | 0.4917 |
最佳模型 :Lasso(alpha=0.01),测试 RMSE 0.7472
相对步骤 4 Baseline(0.7514)降低 0.0042,略有改善。
重要观察:
- alpha 太小 → 接近普通线性回归,改善有限
- alpha 太大(如 Lasso 0.1)→ 欠拟合,RMSE 飙升到 0.8337
- Ridge 在本数据集上变化很小 → 说明步骤 4 的线性回归并未严重过拟合
5.6 核心代码解读
(1)标准化 ------ 防止数据泄露
python
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # 只在训练集 fit
X_test_scaled = scaler.transform(X_test) # 测试集只 transform
| 步骤 | 做什么 |
|---|---|
fit_transform(X_train) |
用训练集算均值/标准差,并变换训练集 |
transform(X_test) |
用训练集的均值/标准差变换测试集 |
切忌 :对 X_test 单独 fit,会把测试集信息泄露到预处理中。
缩放后训练集各列均值 ≈ 0,标准差 ≈ 1。
#mermaid-svg-Re0TpIICdDMfea0z{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Re0TpIICdDMfea0z .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Re0TpIICdDMfea0z .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Re0TpIICdDMfea0z .error-icon{fill:#552222;}#mermaid-svg-Re0TpIICdDMfea0z .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Re0TpIICdDMfea0z .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Re0TpIICdDMfea0z .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Re0TpIICdDMfea0z .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Re0TpIICdDMfea0z .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Re0TpIICdDMfea0z .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Re0TpIICdDMfea0z .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Re0TpIICdDMfea0z .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Re0TpIICdDMfea0z .marker.cross{stroke:#333333;}#mermaid-svg-Re0TpIICdDMfea0z svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Re0TpIICdDMfea0z p{margin:0;}#mermaid-svg-Re0TpIICdDMfea0z .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Re0TpIICdDMfea0z .cluster-label text{fill:#333;}#mermaid-svg-Re0TpIICdDMfea0z .cluster-label span{color:#333;}#mermaid-svg-Re0TpIICdDMfea0z .cluster-label span p{background-color:transparent;}#mermaid-svg-Re0TpIICdDMfea0z .label text,#mermaid-svg-Re0TpIICdDMfea0z span{fill:#333;color:#333;}#mermaid-svg-Re0TpIICdDMfea0z .node rect,#mermaid-svg-Re0TpIICdDMfea0z .node circle,#mermaid-svg-Re0TpIICdDMfea0z .node ellipse,#mermaid-svg-Re0TpIICdDMfea0z .node polygon,#mermaid-svg-Re0TpIICdDMfea0z .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Re0TpIICdDMfea0z .rough-node .label text,#mermaid-svg-Re0TpIICdDMfea0z .node .label text,#mermaid-svg-Re0TpIICdDMfea0z .image-shape .label,#mermaid-svg-Re0TpIICdDMfea0z .icon-shape .label{text-anchor:middle;}#mermaid-svg-Re0TpIICdDMfea0z .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Re0TpIICdDMfea0z .rough-node .label,#mermaid-svg-Re0TpIICdDMfea0z .node .label,#mermaid-svg-Re0TpIICdDMfea0z .image-shape .label,#mermaid-svg-Re0TpIICdDMfea0z .icon-shape .label{text-align:center;}#mermaid-svg-Re0TpIICdDMfea0z .node.clickable{cursor:pointer;}#mermaid-svg-Re0TpIICdDMfea0z .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Re0TpIICdDMfea0z .arrowheadPath{fill:#333333;}#mermaid-svg-Re0TpIICdDMfea0z .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Re0TpIICdDMfea0z .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Re0TpIICdDMfea0z .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Re0TpIICdDMfea0z .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Re0TpIICdDMfea0z .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Re0TpIICdDMfea0z .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Re0TpIICdDMfea0z .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Re0TpIICdDMfea0z .cluster text{fill:#333;}#mermaid-svg-Re0TpIICdDMfea0z .cluster span{color:#333;}#mermaid-svg-Re0TpIICdDMfea0z div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Re0TpIICdDMfea0z .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Re0TpIICdDMfea0z rect.text{fill:none;stroke-width:0;}#mermaid-svg-Re0TpIICdDMfea0z .icon-shape,#mermaid-svg-Re0TpIICdDMfea0z .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Re0TpIICdDMfea0z .icon-shape p,#mermaid-svg-Re0TpIICdDMfea0z .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Re0TpIICdDMfea0z .icon-shape .label rect,#mermaid-svg-Re0TpIICdDMfea0z .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Re0TpIICdDMfea0z .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Re0TpIICdDMfea0z .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Re0TpIICdDMfea0z :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 禁止
X_train
scaler.fit_transform
X_train_scaled
X_test
scaler.transform 只用训练集参数
X_test_scaled
对 X_test fit 会泄露
(2)Ridge 与 Lasso
| 模型 | 正则类型 | 效果 |
|---|---|---|
| Ridge | L2(系数平方和) | 把系数整体压小,保留全部特征 |
| Lasso | L1(系数绝对值之和) | 可把部分系数压到 0,做特征选择 |
alpha 越大 → 正则越强 → 模型越「简单」→ 过大则欠拟合。
#mermaid-svg-JbviTqlNKCSembJf{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-JbviTqlNKCSembJf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JbviTqlNKCSembJf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JbviTqlNKCSembJf .error-icon{fill:#552222;}#mermaid-svg-JbviTqlNKCSembJf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JbviTqlNKCSembJf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JbviTqlNKCSembJf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JbviTqlNKCSembJf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JbviTqlNKCSembJf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JbviTqlNKCSembJf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JbviTqlNKCSembJf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JbviTqlNKCSembJf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JbviTqlNKCSembJf .marker.cross{stroke:#333333;}#mermaid-svg-JbviTqlNKCSembJf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JbviTqlNKCSembJf p{margin:0;}#mermaid-svg-JbviTqlNKCSembJf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-JbviTqlNKCSembJf .cluster-label text{fill:#333;}#mermaid-svg-JbviTqlNKCSembJf .cluster-label span{color:#333;}#mermaid-svg-JbviTqlNKCSembJf .cluster-label span p{background-color:transparent;}#mermaid-svg-JbviTqlNKCSembJf .label text,#mermaid-svg-JbviTqlNKCSembJf span{fill:#333;color:#333;}#mermaid-svg-JbviTqlNKCSembJf .node rect,#mermaid-svg-JbviTqlNKCSembJf .node circle,#mermaid-svg-JbviTqlNKCSembJf .node ellipse,#mermaid-svg-JbviTqlNKCSembJf .node polygon,#mermaid-svg-JbviTqlNKCSembJf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JbviTqlNKCSembJf .rough-node .label text,#mermaid-svg-JbviTqlNKCSembJf .node .label text,#mermaid-svg-JbviTqlNKCSembJf .image-shape .label,#mermaid-svg-JbviTqlNKCSembJf .icon-shape .label{text-anchor:middle;}#mermaid-svg-JbviTqlNKCSembJf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-JbviTqlNKCSembJf .rough-node .label,#mermaid-svg-JbviTqlNKCSembJf .node .label,#mermaid-svg-JbviTqlNKCSembJf .image-shape .label,#mermaid-svg-JbviTqlNKCSembJf .icon-shape .label{text-align:center;}#mermaid-svg-JbviTqlNKCSembJf .node.clickable{cursor:pointer;}#mermaid-svg-JbviTqlNKCSembJf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-JbviTqlNKCSembJf .arrowheadPath{fill:#333333;}#mermaid-svg-JbviTqlNKCSembJf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-JbviTqlNKCSembJf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-JbviTqlNKCSembJf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JbviTqlNKCSembJf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-JbviTqlNKCSembJf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JbviTqlNKCSembJf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-JbviTqlNKCSembJf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-JbviTqlNKCSembJf .cluster text{fill:#333;}#mermaid-svg-JbviTqlNKCSembJf .cluster span{color:#333;}#mermaid-svg-JbviTqlNKCSembJf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-JbviTqlNKCSembJf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JbviTqlNKCSembJf rect.text{fill:none;stroke-width:0;}#mermaid-svg-JbviTqlNKCSembJf .icon-shape,#mermaid-svg-JbviTqlNKCSembJf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JbviTqlNKCSembJf .icon-shape p,#mermaid-svg-JbviTqlNKCSembJf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-JbviTqlNKCSembJf .icon-shape .label rect,#mermaid-svg-JbviTqlNKCSembJf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JbviTqlNKCSembJf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JbviTqlNKCSembJf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JbviTqlNKCSembJf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} alpha 对模型的影响
alpha很小
接近线性回归
alpha适中
可能略改善
alpha很大
欠拟合 RMSE升高
(3)对比实验流程
#mermaid-svg-PNzC5GecHpkl8DmI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PNzC5GecHpkl8DmI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PNzC5GecHpkl8DmI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PNzC5GecHpkl8DmI .error-icon{fill:#552222;}#mermaid-svg-PNzC5GecHpkl8DmI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PNzC5GecHpkl8DmI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PNzC5GecHpkl8DmI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PNzC5GecHpkl8DmI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PNzC5GecHpkl8DmI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PNzC5GecHpkl8DmI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PNzC5GecHpkl8DmI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PNzC5GecHpkl8DmI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PNzC5GecHpkl8DmI .marker.cross{stroke:#333333;}#mermaid-svg-PNzC5GecHpkl8DmI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PNzC5GecHpkl8DmI p{margin:0;}#mermaid-svg-PNzC5GecHpkl8DmI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-PNzC5GecHpkl8DmI .cluster-label text{fill:#333;}#mermaid-svg-PNzC5GecHpkl8DmI .cluster-label span{color:#333;}#mermaid-svg-PNzC5GecHpkl8DmI .cluster-label span p{background-color:transparent;}#mermaid-svg-PNzC5GecHpkl8DmI .label text,#mermaid-svg-PNzC5GecHpkl8DmI span{fill:#333;color:#333;}#mermaid-svg-PNzC5GecHpkl8DmI .node rect,#mermaid-svg-PNzC5GecHpkl8DmI .node circle,#mermaid-svg-PNzC5GecHpkl8DmI .node ellipse,#mermaid-svg-PNzC5GecHpkl8DmI .node polygon,#mermaid-svg-PNzC5GecHpkl8DmI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PNzC5GecHpkl8DmI .rough-node .label text,#mermaid-svg-PNzC5GecHpkl8DmI .node .label text,#mermaid-svg-PNzC5GecHpkl8DmI .image-shape .label,#mermaid-svg-PNzC5GecHpkl8DmI .icon-shape .label{text-anchor:middle;}#mermaid-svg-PNzC5GecHpkl8DmI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PNzC5GecHpkl8DmI .rough-node .label,#mermaid-svg-PNzC5GecHpkl8DmI .node .label,#mermaid-svg-PNzC5GecHpkl8DmI .image-shape .label,#mermaid-svg-PNzC5GecHpkl8DmI .icon-shape .label{text-align:center;}#mermaid-svg-PNzC5GecHpkl8DmI .node.clickable{cursor:pointer;}#mermaid-svg-PNzC5GecHpkl8DmI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PNzC5GecHpkl8DmI .arrowheadPath{fill:#333333;}#mermaid-svg-PNzC5GecHpkl8DmI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PNzC5GecHpkl8DmI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PNzC5GecHpkl8DmI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PNzC5GecHpkl8DmI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PNzC5GecHpkl8DmI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PNzC5GecHpkl8DmI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PNzC5GecHpkl8DmI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PNzC5GecHpkl8DmI .cluster text{fill:#333;}#mermaid-svg-PNzC5GecHpkl8DmI .cluster span{color:#333;}#mermaid-svg-PNzC5GecHpkl8DmI div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PNzC5GecHpkl8DmI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PNzC5GecHpkl8DmI rect.text{fill:none;stroke-width:0;}#mermaid-svg-PNzC5GecHpkl8DmI .icon-shape,#mermaid-svg-PNzC5GecHpkl8DmI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PNzC5GecHpkl8DmI .icon-shape p,#mermaid-svg-PNzC5GecHpkl8DmI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PNzC5GecHpkl8DmI .icon-shape .label rect,#mermaid-svg-PNzC5GecHpkl8DmI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PNzC5GecHpkl8DmI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PNzC5GecHpkl8DmI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PNzC5GecHpkl8DmI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} StandardScaler
线性回归
Ridge 多组alpha
Lasso 多组alpha
对比测试集 RMSE
选 RMSE 最小者
5.7 可视化
reports/figures/06_scaled_models_rmse.png
- 标题:标准化后各线性模型测试集 RMSE 对比(越小越好)
- 绿色条:RMSE 最低的模型(本步为 Lasso alpha=0.01)
#mermaid-svg-LSyuAwHEnJ0YZaBe{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LSyuAwHEnJ0YZaBe .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LSyuAwHEnJ0YZaBe .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LSyuAwHEnJ0YZaBe .error-icon{fill:#552222;}#mermaid-svg-LSyuAwHEnJ0YZaBe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LSyuAwHEnJ0YZaBe .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LSyuAwHEnJ0YZaBe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LSyuAwHEnJ0YZaBe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LSyuAwHEnJ0YZaBe .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LSyuAwHEnJ0YZaBe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LSyuAwHEnJ0YZaBe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LSyuAwHEnJ0YZaBe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LSyuAwHEnJ0YZaBe .marker.cross{stroke:#333333;}#mermaid-svg-LSyuAwHEnJ0YZaBe svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LSyuAwHEnJ0YZaBe p{margin:0;}#mermaid-svg-LSyuAwHEnJ0YZaBe .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LSyuAwHEnJ0YZaBe .cluster-label text{fill:#333;}#mermaid-svg-LSyuAwHEnJ0YZaBe .cluster-label span{color:#333;}#mermaid-svg-LSyuAwHEnJ0YZaBe .cluster-label span p{background-color:transparent;}#mermaid-svg-LSyuAwHEnJ0YZaBe .label text,#mermaid-svg-LSyuAwHEnJ0YZaBe span{fill:#333;color:#333;}#mermaid-svg-LSyuAwHEnJ0YZaBe .node rect,#mermaid-svg-LSyuAwHEnJ0YZaBe .node circle,#mermaid-svg-LSyuAwHEnJ0YZaBe .node ellipse,#mermaid-svg-LSyuAwHEnJ0YZaBe .node polygon,#mermaid-svg-LSyuAwHEnJ0YZaBe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LSyuAwHEnJ0YZaBe .rough-node .label text,#mermaid-svg-LSyuAwHEnJ0YZaBe .node .label text,#mermaid-svg-LSyuAwHEnJ0YZaBe .image-shape .label,#mermaid-svg-LSyuAwHEnJ0YZaBe .icon-shape .label{text-anchor:middle;}#mermaid-svg-LSyuAwHEnJ0YZaBe .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LSyuAwHEnJ0YZaBe .rough-node .label,#mermaid-svg-LSyuAwHEnJ0YZaBe .node .label,#mermaid-svg-LSyuAwHEnJ0YZaBe .image-shape .label,#mermaid-svg-LSyuAwHEnJ0YZaBe .icon-shape .label{text-align:center;}#mermaid-svg-LSyuAwHEnJ0YZaBe .node.clickable{cursor:pointer;}#mermaid-svg-LSyuAwHEnJ0YZaBe .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LSyuAwHEnJ0YZaBe .arrowheadPath{fill:#333333;}#mermaid-svg-LSyuAwHEnJ0YZaBe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LSyuAwHEnJ0YZaBe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LSyuAwHEnJ0YZaBe .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LSyuAwHEnJ0YZaBe .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LSyuAwHEnJ0YZaBe .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LSyuAwHEnJ0YZaBe .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LSyuAwHEnJ0YZaBe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LSyuAwHEnJ0YZaBe .cluster text{fill:#333;}#mermaid-svg-LSyuAwHEnJ0YZaBe .cluster span{color:#333;}#mermaid-svg-LSyuAwHEnJ0YZaBe div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LSyuAwHEnJ0YZaBe .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LSyuAwHEnJ0YZaBe rect.text{fill:none;stroke-width:0;}#mermaid-svg-LSyuAwHEnJ0YZaBe .icon-shape,#mermaid-svg-LSyuAwHEnJ0YZaBe .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LSyuAwHEnJ0YZaBe .icon-shape p,#mermaid-svg-LSyuAwHEnJ0YZaBe .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LSyuAwHEnJ0YZaBe .icon-shape .label rect,#mermaid-svg-LSyuAwHEnJ0YZaBe .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LSyuAwHEnJ0YZaBe .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LSyuAwHEnJ0YZaBe .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LSyuAwHEnJ0YZaBe :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 本步实验结论
Baseline 0.7514
Lasso0.01 最佳 0.7472
Lasso0.1 欠拟合 0.8337
5.8 动手任务
任务 A:运行脚本,确认最佳模型为 Lasso(alpha=0.01)
任务 B:观察 Lasso(alpha=0.1)RMSE 为何变差?(答:正则过强,欠拟合)
任务 C:思考------为何 Ridge 几乎没变化?(答:本数据线性回归未严重过拟合,L2 惩罚带来的变化很小)
任务 D:在 README 写一句话:StandardScaler 为何只能 fit 训练集?
5.9 验收标准
- 能解释 fit vs transform 的区别
- 能说明 Ridge 与 Lasso 的差异
- 能解释 alpha 过大/过小的影响
- 能读 RMSE 对比图并指出最佳模型
5.10 本步核心概念
5.10 动手任务与验收标准参考答案
以下为教学标准答案,便于自学对照;
README.md学习记录仍建议用自己的话写。
动手任务答案
| 任务 | 参考答案 |
|---|---|
| A | 最佳 Lasso alpha=0.01,RMSE 0.7472。 |
| B | alpha=0.1 欠拟合,RMSE 0.8337。 |
| C | 线性回归未严重过拟合,Ridge 变化小。 |
| D | Scaler 只能 fit 训练集,否则泄露测试集统计量。 |
验收标准答案
| 验收项 | 参考答案 |
|---|---|
| fit vs transform | fit 学参数;transform 应用;测试集只 transform。 |
| Ridge vs Lasso | L2 缩小系数;L1 可稀疏化。 |
| alpha | 过小接近回归;过大欠拟合。 |
| 最佳模型 | Lasso 0.01,RMSE 0.7472。 |
| 概念 | 解释 |
|---|---|
| 标准化(Z-score) | 减均值、除标准差,统一到可比尺度 |
| 正则化 | 在损失函数中加惩罚,限制模型复杂度 |
| L1 / L2 | Lasso 用 L1,Ridge 用 L2 |
| alpha | 正则化强度超参数 |
| 欠拟合 | 模型过于简单,训练/测试都差(如 Lasso alpha=0.1) |
5.11 常见问题
Q:标准化后线性回归 RMSE 与步骤 4 一样?
A:线性回归在数学上对特征缩放不敏感(预测值不变),所以 RMSE 相同是正常的。
Q:下一步树模型还需要缩放吗?
A:步骤 6 会讲------树模型不需要缩放,这是线性与树模型的重要区别。
5.12 本步小结
| 要点 | 内容 |
|---|---|
| 最佳模型 | Lasso(alpha=0.01) |
| 最佳测试 RMSE | 0.7472 |
| 关键教训 | alpha 需要调;过大正则会欠拟合 |
| 下一步 | 随机森林与梯度提升(树模型) |
5.13 学习记录(请你填写)
- 完成日期:
- 动手任务完成情况:任务 A / B / C / D
- 我对 StandardScaler 的理解:
- 疑问(如有):
步骤 6:树模型 ------ 随机森林与梯度提升
状态 :✅ 已完成教学(报告见
reports/tree_models_summary.txt,图表见07_、08_系列 PNG)
6.1 本步目标
- 引入非线性模型:随机森林、梯度提升
- 理解树模型不需要特征缩放(与步骤 5 对比)
- 学会看特征重要性,并汇总步骤 4~6 模型表现
6.2 这一步在解决什么问题?
步骤 4~5 的线性模型假设:「特征与房价是直线关系」。但真实数据里可能是:
- 收入很低时,房价随收入涨得快;很高时变缓(非线性)
- 经纬度组合体现地理位置(分区效应)
决策树 通过「如果收入 > 3.5 则走左边,否则走右边」这种方式切分数据,能拟合非线性。
本步用两种集成方法把多棵树组合起来:
| 方法 | 代表模型 | 核心思想 |
|---|---|---|
| Bagging | 随机森林 | 多棵树并行训练,结果平均 |
| Boosting | 梯度提升 | 多棵树串行训练,后一棵修正前一棵错误 |
6.2.5 本步在整体流程中的位置
#mermaid-svg-Sv1fvlukyYW8HdqT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Sv1fvlukyYW8HdqT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Sv1fvlukyYW8HdqT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Sv1fvlukyYW8HdqT .error-icon{fill:#552222;}#mermaid-svg-Sv1fvlukyYW8HdqT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Sv1fvlukyYW8HdqT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Sv1fvlukyYW8HdqT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Sv1fvlukyYW8HdqT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Sv1fvlukyYW8HdqT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Sv1fvlukyYW8HdqT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Sv1fvlukyYW8HdqT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Sv1fvlukyYW8HdqT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Sv1fvlukyYW8HdqT .marker.cross{stroke:#333333;}#mermaid-svg-Sv1fvlukyYW8HdqT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Sv1fvlukyYW8HdqT p{margin:0;}#mermaid-svg-Sv1fvlukyYW8HdqT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Sv1fvlukyYW8HdqT .cluster-label text{fill:#333;}#mermaid-svg-Sv1fvlukyYW8HdqT .cluster-label span{color:#333;}#mermaid-svg-Sv1fvlukyYW8HdqT .cluster-label span p{background-color:transparent;}#mermaid-svg-Sv1fvlukyYW8HdqT .label text,#mermaid-svg-Sv1fvlukyYW8HdqT span{fill:#333;color:#333;}#mermaid-svg-Sv1fvlukyYW8HdqT .node rect,#mermaid-svg-Sv1fvlukyYW8HdqT .node circle,#mermaid-svg-Sv1fvlukyYW8HdqT .node ellipse,#mermaid-svg-Sv1fvlukyYW8HdqT .node polygon,#mermaid-svg-Sv1fvlukyYW8HdqT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Sv1fvlukyYW8HdqT .rough-node .label text,#mermaid-svg-Sv1fvlukyYW8HdqT .node .label text,#mermaid-svg-Sv1fvlukyYW8HdqT .image-shape .label,#mermaid-svg-Sv1fvlukyYW8HdqT .icon-shape .label{text-anchor:middle;}#mermaid-svg-Sv1fvlukyYW8HdqT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Sv1fvlukyYW8HdqT .rough-node .label,#mermaid-svg-Sv1fvlukyYW8HdqT .node .label,#mermaid-svg-Sv1fvlukyYW8HdqT .image-shape .label,#mermaid-svg-Sv1fvlukyYW8HdqT .icon-shape .label{text-align:center;}#mermaid-svg-Sv1fvlukyYW8HdqT .node.clickable{cursor:pointer;}#mermaid-svg-Sv1fvlukyYW8HdqT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Sv1fvlukyYW8HdqT .arrowheadPath{fill:#333333;}#mermaid-svg-Sv1fvlukyYW8HdqT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Sv1fvlukyYW8HdqT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Sv1fvlukyYW8HdqT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Sv1fvlukyYW8HdqT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Sv1fvlukyYW8HdqT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Sv1fvlukyYW8HdqT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Sv1fvlukyYW8HdqT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Sv1fvlukyYW8HdqT .cluster text{fill:#333;}#mermaid-svg-Sv1fvlukyYW8HdqT .cluster span{color:#333;}#mermaid-svg-Sv1fvlukyYW8HdqT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Sv1fvlukyYW8HdqT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Sv1fvlukyYW8HdqT rect.text{fill:none;stroke-width:0;}#mermaid-svg-Sv1fvlukyYW8HdqT .icon-shape,#mermaid-svg-Sv1fvlukyYW8HdqT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Sv1fvlukyYW8HdqT .icon-shape p,#mermaid-svg-Sv1fvlukyYW8HdqT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Sv1fvlukyYW8HdqT .icon-shape .label rect,#mermaid-svg-Sv1fvlukyYW8HdqT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Sv1fvlukyYW8HdqT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Sv1fvlukyYW8HdqT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Sv1fvlukyYW8HdqT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 步骤4 线性Baseline 0.75
步骤5 Lasso 0.75
步骤6 树模型
随机森林 0.52
梯度提升 0.48
步骤7 特征工程
6.2.6 名词解释(本步首次出现)
| 名词 | 是什么 | 为什么需要 | 在本项目中 | 易混淆 |
|---|---|---|---|---|
| 决策树 | 按特征阈值逐层分裂的树形规则 | 能表达非线性、分区关系 | RF 和 GBR 的基础单元 | 不是流程图 |
| 随机森林 RF | 多棵决策树 Bagging 集成 | 降低单棵树过拟合 | RandomForestRegressor |
不是一棵大树 |
| 梯度提升 GBR | 多棵树 Boosting 串行叠加 | 往往比单树/RF 更准 | HistGradientBoostingRegressor |
不是随机森林 |
| Bagging | 自助采样训练多模型再平均 | 降方差、更稳定 | 随机森林的核心 | 不是 Boosting |
| Boosting | 后续模型拟合前面模型的残差 | 逐步减少误差 | 梯度提升的核心 | 不是 Bagging |
| n_estimators | 树的数量或提升轮数 | 影响模型容量与训练时间 | 本步设为 100 | 不是深度 |
| 特征重要性 | 某特征在所有分裂中的贡献度 | 解释模型认为什么因素关键 | MedInc 约 52% | 不是因果 |
| 非线性 | 关系不是直线 | 房价问题存在分区/阈值效应 | 树模型 RMSE 明显低于线性 | 不是无关 |
6.2.7 线性模型 vs 树模型(Mermaid)
#mermaid-svg-5gi3N2qd61HeAhI9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-5gi3N2qd61HeAhI9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5gi3N2qd61HeAhI9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5gi3N2qd61HeAhI9 .error-icon{fill:#552222;}#mermaid-svg-5gi3N2qd61HeAhI9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5gi3N2qd61HeAhI9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5gi3N2qd61HeAhI9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5gi3N2qd61HeAhI9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5gi3N2qd61HeAhI9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5gi3N2qd61HeAhI9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5gi3N2qd61HeAhI9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5gi3N2qd61HeAhI9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5gi3N2qd61HeAhI9 .marker.cross{stroke:#333333;}#mermaid-svg-5gi3N2qd61HeAhI9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5gi3N2qd61HeAhI9 p{margin:0;}#mermaid-svg-5gi3N2qd61HeAhI9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-5gi3N2qd61HeAhI9 .cluster-label text{fill:#333;}#mermaid-svg-5gi3N2qd61HeAhI9 .cluster-label span{color:#333;}#mermaid-svg-5gi3N2qd61HeAhI9 .cluster-label span p{background-color:transparent;}#mermaid-svg-5gi3N2qd61HeAhI9 .label text,#mermaid-svg-5gi3N2qd61HeAhI9 span{fill:#333;color:#333;}#mermaid-svg-5gi3N2qd61HeAhI9 .node rect,#mermaid-svg-5gi3N2qd61HeAhI9 .node circle,#mermaid-svg-5gi3N2qd61HeAhI9 .node ellipse,#mermaid-svg-5gi3N2qd61HeAhI9 .node polygon,#mermaid-svg-5gi3N2qd61HeAhI9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5gi3N2qd61HeAhI9 .rough-node .label text,#mermaid-svg-5gi3N2qd61HeAhI9 .node .label text,#mermaid-svg-5gi3N2qd61HeAhI9 .image-shape .label,#mermaid-svg-5gi3N2qd61HeAhI9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-5gi3N2qd61HeAhI9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5gi3N2qd61HeAhI9 .rough-node .label,#mermaid-svg-5gi3N2qd61HeAhI9 .node .label,#mermaid-svg-5gi3N2qd61HeAhI9 .image-shape .label,#mermaid-svg-5gi3N2qd61HeAhI9 .icon-shape .label{text-align:center;}#mermaid-svg-5gi3N2qd61HeAhI9 .node.clickable{cursor:pointer;}#mermaid-svg-5gi3N2qd61HeAhI9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5gi3N2qd61HeAhI9 .arrowheadPath{fill:#333333;}#mermaid-svg-5gi3N2qd61HeAhI9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5gi3N2qd61HeAhI9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5gi3N2qd61HeAhI9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5gi3N2qd61HeAhI9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5gi3N2qd61HeAhI9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5gi3N2qd61HeAhI9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5gi3N2qd61HeAhI9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5gi3N2qd61HeAhI9 .cluster text{fill:#333;}#mermaid-svg-5gi3N2qd61HeAhI9 .cluster span{color:#333;}#mermaid-svg-5gi3N2qd61HeAhI9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-5gi3N2qd61HeAhI9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5gi3N2qd61HeAhI9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-5gi3N2qd61HeAhI9 .icon-shape,#mermaid-svg-5gi3N2qd61HeAhI9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5gi3N2qd61HeAhI9 .icon-shape p,#mermaid-svg-5gi3N2qd61HeAhI9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5gi3N2qd61HeAhI9 .icon-shape .label rect,#mermaid-svg-5gi3N2qd61HeAhI9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5gi3N2qd61HeAhI9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5gi3N2qd61HeAhI9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5gi3N2qd61HeAhI9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 树模型 步骤6
分区切分 可非线性
用原始特征即可
RMSE约0.48
线性模型 步骤4-5
假设直线关系
需要StandardScaler
RMSE约0.75
6.3 任务清单
- 训练
RandomForestRegressor(100 棵树) - 训练
HistGradientBoostingRegressor(100 轮) - 使用未缩放原始特征
- 绘制随机森林特征重要性图
- 汇总步骤 4~6 模型 RMSE 对比
6.4 运行本步
powershell
cd "d:\JavaCode\机器学习\project_01_housing"
python src/train.py
6.5 实验结果(你的环境)
步骤 6 树模型:
| 模型 | 测试 RMSE | 测试 R2 |
|---|---|---|
| 随机森林 | 0.5190 | 0.8030 |
| 梯度提升 HistGBR | 0.4763 | 0.8341 |
步骤 4~6 汇总:
| 模型 | 测试 RMSE | 相对 Baseline |
|---|---|---|
| 步骤4 线性回归 Baseline | 0.7514 | --- |
| 步骤5 Lasso alpha=0.01 | 0.7472 | 略好 |
| 步骤6 随机森林 | 0.5190 | 大幅降低 |
| 步骤6 梯度提升 | 0.4763 | 最佳 |
关键发现:
- 树模型 RMSE 从 0.75 → 0.48 ,R2 从 0.59 → 0.83,提升巨大
- 说明房价与特征之间存在明显非线性,线性模型不够用
- 随机森林特征重要性 Top3:收入 MedInc(52%)、平均入住人数、纬度
6.6 决策树如何工作(直觉)
#mermaid-svg-X4b4lqkIpdLPnNIJ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-X4b4lqkIpdLPnNIJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-X4b4lqkIpdLPnNIJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-X4b4lqkIpdLPnNIJ .error-icon{fill:#552222;}#mermaid-svg-X4b4lqkIpdLPnNIJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-X4b4lqkIpdLPnNIJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-X4b4lqkIpdLPnNIJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-X4b4lqkIpdLPnNIJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-X4b4lqkIpdLPnNIJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-X4b4lqkIpdLPnNIJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-X4b4lqkIpdLPnNIJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-X4b4lqkIpdLPnNIJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-X4b4lqkIpdLPnNIJ .marker.cross{stroke:#333333;}#mermaid-svg-X4b4lqkIpdLPnNIJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-X4b4lqkIpdLPnNIJ p{margin:0;}#mermaid-svg-X4b4lqkIpdLPnNIJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-X4b4lqkIpdLPnNIJ .cluster-label text{fill:#333;}#mermaid-svg-X4b4lqkIpdLPnNIJ .cluster-label span{color:#333;}#mermaid-svg-X4b4lqkIpdLPnNIJ .cluster-label span p{background-color:transparent;}#mermaid-svg-X4b4lqkIpdLPnNIJ .label text,#mermaid-svg-X4b4lqkIpdLPnNIJ span{fill:#333;color:#333;}#mermaid-svg-X4b4lqkIpdLPnNIJ .node rect,#mermaid-svg-X4b4lqkIpdLPnNIJ .node circle,#mermaid-svg-X4b4lqkIpdLPnNIJ .node ellipse,#mermaid-svg-X4b4lqkIpdLPnNIJ .node polygon,#mermaid-svg-X4b4lqkIpdLPnNIJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-X4b4lqkIpdLPnNIJ .rough-node .label text,#mermaid-svg-X4b4lqkIpdLPnNIJ .node .label text,#mermaid-svg-X4b4lqkIpdLPnNIJ .image-shape .label,#mermaid-svg-X4b4lqkIpdLPnNIJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-X4b4lqkIpdLPnNIJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-X4b4lqkIpdLPnNIJ .rough-node .label,#mermaid-svg-X4b4lqkIpdLPnNIJ .node .label,#mermaid-svg-X4b4lqkIpdLPnNIJ .image-shape .label,#mermaid-svg-X4b4lqkIpdLPnNIJ .icon-shape .label{text-align:center;}#mermaid-svg-X4b4lqkIpdLPnNIJ .node.clickable{cursor:pointer;}#mermaid-svg-X4b4lqkIpdLPnNIJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-X4b4lqkIpdLPnNIJ .arrowheadPath{fill:#333333;}#mermaid-svg-X4b4lqkIpdLPnNIJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-X4b4lqkIpdLPnNIJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-X4b4lqkIpdLPnNIJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-X4b4lqkIpdLPnNIJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-X4b4lqkIpdLPnNIJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-X4b4lqkIpdLPnNIJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-X4b4lqkIpdLPnNIJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-X4b4lqkIpdLPnNIJ .cluster text{fill:#333;}#mermaid-svg-X4b4lqkIpdLPnNIJ .cluster span{color:#333;}#mermaid-svg-X4b4lqkIpdLPnNIJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-X4b4lqkIpdLPnNIJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-X4b4lqkIpdLPnNIJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-X4b4lqkIpdLPnNIJ .icon-shape,#mermaid-svg-X4b4lqkIpdLPnNIJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-X4b4lqkIpdLPnNIJ .icon-shape p,#mermaid-svg-X4b4lqkIpdLPnNIJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-X4b4lqkIpdLPnNIJ .icon-shape .label rect,#mermaid-svg-X4b4lqkIpdLPnNIJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-X4b4lqkIpdLPnNIJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-X4b4lqkIpdLPnNIJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-X4b4lqkIpdLPnNIJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
根节点 全部样本
MedInc <= 3.5?
左子树 低价区
右子树 高价区
预测较低房价
预测较高房价
单棵树容易过拟合 (背训练集)。随机森林训练 100 棵不同的树再平均预测,更稳定。
6.7 Bagging vs Boosting(Mermaid)
#mermaid-svg-27Z3UCGmDNIfYGQR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-27Z3UCGmDNIfYGQR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-27Z3UCGmDNIfYGQR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-27Z3UCGmDNIfYGQR .error-icon{fill:#552222;}#mermaid-svg-27Z3UCGmDNIfYGQR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-27Z3UCGmDNIfYGQR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-27Z3UCGmDNIfYGQR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-27Z3UCGmDNIfYGQR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-27Z3UCGmDNIfYGQR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-27Z3UCGmDNIfYGQR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-27Z3UCGmDNIfYGQR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-27Z3UCGmDNIfYGQR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-27Z3UCGmDNIfYGQR .marker.cross{stroke:#333333;}#mermaid-svg-27Z3UCGmDNIfYGQR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-27Z3UCGmDNIfYGQR p{margin:0;}#mermaid-svg-27Z3UCGmDNIfYGQR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-27Z3UCGmDNIfYGQR .cluster-label text{fill:#333;}#mermaid-svg-27Z3UCGmDNIfYGQR .cluster-label span{color:#333;}#mermaid-svg-27Z3UCGmDNIfYGQR .cluster-label span p{background-color:transparent;}#mermaid-svg-27Z3UCGmDNIfYGQR .label text,#mermaid-svg-27Z3UCGmDNIfYGQR span{fill:#333;color:#333;}#mermaid-svg-27Z3UCGmDNIfYGQR .node rect,#mermaid-svg-27Z3UCGmDNIfYGQR .node circle,#mermaid-svg-27Z3UCGmDNIfYGQR .node ellipse,#mermaid-svg-27Z3UCGmDNIfYGQR .node polygon,#mermaid-svg-27Z3UCGmDNIfYGQR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-27Z3UCGmDNIfYGQR .rough-node .label text,#mermaid-svg-27Z3UCGmDNIfYGQR .node .label text,#mermaid-svg-27Z3UCGmDNIfYGQR .image-shape .label,#mermaid-svg-27Z3UCGmDNIfYGQR .icon-shape .label{text-anchor:middle;}#mermaid-svg-27Z3UCGmDNIfYGQR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-27Z3UCGmDNIfYGQR .rough-node .label,#mermaid-svg-27Z3UCGmDNIfYGQR .node .label,#mermaid-svg-27Z3UCGmDNIfYGQR .image-shape .label,#mermaid-svg-27Z3UCGmDNIfYGQR .icon-shape .label{text-align:center;}#mermaid-svg-27Z3UCGmDNIfYGQR .node.clickable{cursor:pointer;}#mermaid-svg-27Z3UCGmDNIfYGQR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-27Z3UCGmDNIfYGQR .arrowheadPath{fill:#333333;}#mermaid-svg-27Z3UCGmDNIfYGQR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-27Z3UCGmDNIfYGQR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-27Z3UCGmDNIfYGQR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-27Z3UCGmDNIfYGQR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-27Z3UCGmDNIfYGQR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-27Z3UCGmDNIfYGQR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-27Z3UCGmDNIfYGQR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-27Z3UCGmDNIfYGQR .cluster text{fill:#333;}#mermaid-svg-27Z3UCGmDNIfYGQR .cluster span{color:#333;}#mermaid-svg-27Z3UCGmDNIfYGQR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-27Z3UCGmDNIfYGQR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-27Z3UCGmDNIfYGQR rect.text{fill:none;stroke-width:0;}#mermaid-svg-27Z3UCGmDNIfYGQR .icon-shape,#mermaid-svg-27Z3UCGmDNIfYGQR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-27Z3UCGmDNIfYGQR .icon-shape p,#mermaid-svg-27Z3UCGmDNIfYGQR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-27Z3UCGmDNIfYGQR .icon-shape .label rect,#mermaid-svg-27Z3UCGmDNIfYGQR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-27Z3UCGmDNIfYGQR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-27Z3UCGmDNIfYGQR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-27Z3UCGmDNIfYGQR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Boosting 梯度提升
树1 初步预测
树2 拟合残差
树3 继续修正
累加得到最终预测
Bagging 随机森林
树1
平均预测
树2
树100
6.8 核心代码解读
(1)随机森林 ------ 未缩放特征
python
rf = RandomForestRegressor(n_estimators=100, random_state=42, n_jobs=-1)
rf.fit(X_train, y_train) # X_train 是原始特征,未 StandardScaler
| 参数 | 含义 |
|---|---|
n_estimators=100 |
100 棵决策树 |
n_jobs=-1 |
并行用全部 CPU |
random_state=42 |
可复现 |
(2)为何树模型不需要缩放?
树的分裂只看「谁大谁小」,不看绝对数值大小:
- 收入 3.0 vs 3.5 的分裂点,缩放前后排序不变
- 线性模型系数会受量纲影响,树不会
(3)特征重要性
python
model.feature_importances_ # 随机森林有,HistGBR 无此属性
本步以随机森林 的特征重要性图为主(07_random_forest_feature_importance.png)。
6.9 输出文件
| 文件 | 说明 |
|---|---|
reports/tree_models_summary.txt |
树模型 + 汇总报告 |
reports/figures/07_random_forest_feature_importance.png |
特征重要性(中文) |
reports/figures/08_steps_4_to_6_rmse.png |
步骤 4~6 RMSE 对比 |
6.10 动手任务
任务 A:运行脚本,确认梯度提升 RMSE ≈ 0.48
任务 B:打开特征重要性图,确认 MedInc 排第一
任务 C :对比 08_steps_4_to_6_rmse.png,用一句话说树模型为何比线性好
任务 D:在 README 写:Bagging 和 Boosting 的区别
6.11 验收标准
- 能解释树模型为何不需要 StandardScaler
- 能区分 Bagging 与 Boosting
- 能说出步骤 4~6 当前最佳模型及 RMSE
- 能读特征重要性图并指出 Top 特征
6.12 动手任务与验收标准参考答案
以下为教学标准答案,便于自学对照;
README.md学习记录仍建议用自己的话写。
动手任务答案
| 任务 | 参考答案 |
|---|---|
| A | 梯度提升 HistGBR 测试 RMSE≈0.4763。 |
| B | 特征重要性图 MedInc(收入) 排第一。 |
| C | 树模型能切分非线性边界,收入/地理位置等与房价不是简单直线关系,RMSE 从 0.75 降到 0.48。 |
| D | Bagging (随机森林):多棵树并行 训练后投票/平均;Boosting (梯度提升):多棵树串行训练,后一棵修正前一棵错误。 |
验收标准答案
| 验收项 | 参考答案 |
|---|---|
| 树模型不需缩放 | 树按特征值大小做分裂,只关心排序,StandardScaler 不改变分裂结果。 |
| Bagging vs Boosting | Bagging 降方差(并行集成);Boosting 降偏差(串行纠错)。 |
| 步骤 4~6 最佳 | 步骤 6 HistGBR ,测试 RMSE 0.4763。 |
| Top 特征 | MedInc 收入中位数最重要。 |
6.13 常见问题
Q:RMSE 从 0.75 跳到 0.48,正常吗?
A:正常。树模型能拟合非线性,在这类表格数据上常显著优于线性回归。
Q:HistGBR 为何没有 feature_importances_?
A:sklearn 的 HistGradientBoosting 实现不同。进阶可用 permutation_importance 分析。
Q:随机森林和梯度提升选哪个?
A:本步数据上 HistGBR 更好(0.4763 vs 0.5190)。实际项目应都试,用验证集/测试集选。
Q:100 棵树够吗?
A:学习阶段够用。生产环境可配合交叉验证调 n_estimators 和深度。
6.14 本步小结
| 要点 | 内容 |
|---|---|
| 最佳树模型 | 梯度提升 HistGBR |
| 最佳测试 RMSE | 0.4763 |
| 最重要特征 | 收入 MedInc |
| 关键教训 | 非线性问题要用非线性模型 |
| 下一步 | 简单特征工程 |
6.15 学习记录(请你填写)
- 完成日期:
- 动手任务完成情况:任务 A / B / C / D
- 我对 Bagging 与 Boosting 的理解:
- 疑问(如有):
步骤 7:简单特征工程
状态 :✅ 已完成教学(报告见
reports/feature_engineering_report.txt,图表见09_feature_engineering_rmse.png)
7.1 本步目标
- 理解特征工程:用业务知识把原始列组合成更有意义的输入
- 构造 2 个新特征,在同一模型(HistGBR)上对比工程前后指标
- 学会如实记录结论------没有提升也是有效实验结果
7.2 这一步在解决什么问题?
步骤 6 的 HistGBR 已经很强(RMSE 0.4763),但原始 8 列是「统计块级」指标,例如:
AveRooms:平均房间数AveBedrms:平均卧室数AveOccup:平均入住人数
模型虽然能自动学非线性,但不一定 能高效利用「卧室占房间比例」「人均房间数」这类比例关系 。
特征工程就是:我们根据对住房的理解,显式造出这些组合特征,看能否再挤一点性能。
7.3 本步在整体流程中的位置
#mermaid-svg-rINv2ABVmCn4wXqr{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rINv2ABVmCn4wXqr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rINv2ABVmCn4wXqr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rINv2ABVmCn4wXqr .error-icon{fill:#552222;}#mermaid-svg-rINv2ABVmCn4wXqr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rINv2ABVmCn4wXqr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rINv2ABVmCn4wXqr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rINv2ABVmCn4wXqr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rINv2ABVmCn4wXqr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rINv2ABVmCn4wXqr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rINv2ABVmCn4wXqr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rINv2ABVmCn4wXqr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rINv2ABVmCn4wXqr .marker.cross{stroke:#333333;}#mermaid-svg-rINv2ABVmCn4wXqr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rINv2ABVmCn4wXqr p{margin:0;}#mermaid-svg-rINv2ABVmCn4wXqr .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rINv2ABVmCn4wXqr .cluster-label text{fill:#333;}#mermaid-svg-rINv2ABVmCn4wXqr .cluster-label span{color:#333;}#mermaid-svg-rINv2ABVmCn4wXqr .cluster-label span p{background-color:transparent;}#mermaid-svg-rINv2ABVmCn4wXqr .label text,#mermaid-svg-rINv2ABVmCn4wXqr span{fill:#333;color:#333;}#mermaid-svg-rINv2ABVmCn4wXqr .node rect,#mermaid-svg-rINv2ABVmCn4wXqr .node circle,#mermaid-svg-rINv2ABVmCn4wXqr .node ellipse,#mermaid-svg-rINv2ABVmCn4wXqr .node polygon,#mermaid-svg-rINv2ABVmCn4wXqr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rINv2ABVmCn4wXqr .rough-node .label text,#mermaid-svg-rINv2ABVmCn4wXqr .node .label text,#mermaid-svg-rINv2ABVmCn4wXqr .image-shape .label,#mermaid-svg-rINv2ABVmCn4wXqr .icon-shape .label{text-anchor:middle;}#mermaid-svg-rINv2ABVmCn4wXqr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rINv2ABVmCn4wXqr .rough-node .label,#mermaid-svg-rINv2ABVmCn4wXqr .node .label,#mermaid-svg-rINv2ABVmCn4wXqr .image-shape .label,#mermaid-svg-rINv2ABVmCn4wXqr .icon-shape .label{text-align:center;}#mermaid-svg-rINv2ABVmCn4wXqr .node.clickable{cursor:pointer;}#mermaid-svg-rINv2ABVmCn4wXqr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rINv2ABVmCn4wXqr .arrowheadPath{fill:#333333;}#mermaid-svg-rINv2ABVmCn4wXqr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rINv2ABVmCn4wXqr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rINv2ABVmCn4wXqr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rINv2ABVmCn4wXqr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rINv2ABVmCn4wXqr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rINv2ABVmCn4wXqr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rINv2ABVmCn4wXqr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rINv2ABVmCn4wXqr .cluster text{fill:#333;}#mermaid-svg-rINv2ABVmCn4wXqr .cluster span{color:#333;}#mermaid-svg-rINv2ABVmCn4wXqr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rINv2ABVmCn4wXqr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rINv2ABVmCn4wXqr rect.text{fill:none;stroke-width:0;}#mermaid-svg-rINv2ABVmCn4wXqr .icon-shape,#mermaid-svg-rINv2ABVmCn4wXqr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rINv2ABVmCn4wXqr .icon-shape p,#mermaid-svg-rINv2ABVmCn4wXqr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rINv2ABVmCn4wXqr .icon-shape .label rect,#mermaid-svg-rINv2ABVmCn4wXqr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rINv2ABVmCn4wXqr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rINv2ABVmCn4wXqr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rINv2ABVmCn4wXqr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 步骤6 HistGBR 0.4763
步骤7 特征工程
工程前 8 特征
工程后 10 特征
RMSE 0.4763
RMSE 0.4745
步骤8 总结与选模
7.4 名词解释(本步首次出现)
| 名词 | 是什么 | 为什么需要 | 在本项目中 | 易混淆 |
|---|---|---|---|---|
| 特征工程 | 对原始特征做变换、组合、构造新列 | 让模型更容易学到有用模式 | 新增 2 列比例特征 | 不是调参 |
| 领域知识 | 对问题背景的专业理解 | 指导「造什么特征有意义」 | 房间结构、人均空间与房价相关 | 不是随便加减 |
| 比例特征 | 两列相除得到的新变量 | 消除量纲、表达结构关系 | BedroomsRatio、RoomsPerHousehold | 不是原始计数 |
| 信息泄露 | 用测试集或未来信息参与训练 | 会导致虚高指标、上线失效 | 本步只用行内四则运算,不用全局统计 | 不是过拟合 |
| 边际收益 | 再增加一步后带来的额外提升 | 判断特征工程是否值得继续 | 本步 RMSE 仅降 0.0018 | 不是总收益 |
7.5 新增的两个特征
| 新特征 | 公式 | 业务含义 | 直觉 |
|---|---|---|---|
| BedroomsRatio | AveBedrms / AveRooms |
卧室占全部房间的比例 | 比例高可能偏紧凑;比例低可能客厅/其他空间大 |
| RoomsPerHousehold | AveRooms / AveOccup |
人均可用房间数 | 人均房间多,空间更充裕,可能与房价正相关 |
训练集上新特征统计(describe()):
| 统计量 | BedroomsRatio | RoomsPerHousehold |
|---|---|---|
| mean | 0.2131 | 1.9754 |
| std | 0.0578 | 1.1118 |
| min | 0.1000 | 0.0025 |
| max | 1.0000 | 52.0333 |
RoomsPerHousehold最大值 52 说明存在极端块(入住人数极少但房间多),树模型可以处理这类离群,但实战中可进一步做截断或分箱。
7.6 特征工程流程(Mermaid)
#mermaid-svg-6RtN94wAZfIjeVOM{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6RtN94wAZfIjeVOM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6RtN94wAZfIjeVOM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6RtN94wAZfIjeVOM .error-icon{fill:#552222;}#mermaid-svg-6RtN94wAZfIjeVOM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6RtN94wAZfIjeVOM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6RtN94wAZfIjeVOM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6RtN94wAZfIjeVOM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6RtN94wAZfIjeVOM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6RtN94wAZfIjeVOM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6RtN94wAZfIjeVOM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6RtN94wAZfIjeVOM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6RtN94wAZfIjeVOM .marker.cross{stroke:#333333;}#mermaid-svg-6RtN94wAZfIjeVOM svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6RtN94wAZfIjeVOM p{margin:0;}#mermaid-svg-6RtN94wAZfIjeVOM .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6RtN94wAZfIjeVOM .cluster-label text{fill:#333;}#mermaid-svg-6RtN94wAZfIjeVOM .cluster-label span{color:#333;}#mermaid-svg-6RtN94wAZfIjeVOM .cluster-label span p{background-color:transparent;}#mermaid-svg-6RtN94wAZfIjeVOM .label text,#mermaid-svg-6RtN94wAZfIjeVOM span{fill:#333;color:#333;}#mermaid-svg-6RtN94wAZfIjeVOM .node rect,#mermaid-svg-6RtN94wAZfIjeVOM .node circle,#mermaid-svg-6RtN94wAZfIjeVOM .node ellipse,#mermaid-svg-6RtN94wAZfIjeVOM .node polygon,#mermaid-svg-6RtN94wAZfIjeVOM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6RtN94wAZfIjeVOM .rough-node .label text,#mermaid-svg-6RtN94wAZfIjeVOM .node .label text,#mermaid-svg-6RtN94wAZfIjeVOM .image-shape .label,#mermaid-svg-6RtN94wAZfIjeVOM .icon-shape .label{text-anchor:middle;}#mermaid-svg-6RtN94wAZfIjeVOM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6RtN94wAZfIjeVOM .rough-node .label,#mermaid-svg-6RtN94wAZfIjeVOM .node .label,#mermaid-svg-6RtN94wAZfIjeVOM .image-shape .label,#mermaid-svg-6RtN94wAZfIjeVOM .icon-shape .label{text-align:center;}#mermaid-svg-6RtN94wAZfIjeVOM .node.clickable{cursor:pointer;}#mermaid-svg-6RtN94wAZfIjeVOM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6RtN94wAZfIjeVOM .arrowheadPath{fill:#333333;}#mermaid-svg-6RtN94wAZfIjeVOM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6RtN94wAZfIjeVOM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6RtN94wAZfIjeVOM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6RtN94wAZfIjeVOM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6RtN94wAZfIjeVOM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6RtN94wAZfIjeVOM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6RtN94wAZfIjeVOM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6RtN94wAZfIjeVOM .cluster text{fill:#333;}#mermaid-svg-6RtN94wAZfIjeVOM .cluster span{color:#333;}#mermaid-svg-6RtN94wAZfIjeVOM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-6RtN94wAZfIjeVOM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6RtN94wAZfIjeVOM rect.text{fill:none;stroke-width:0;}#mermaid-svg-6RtN94wAZfIjeVOM .icon-shape,#mermaid-svg-6RtN94wAZfIjeVOM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6RtN94wAZfIjeVOM .icon-shape p,#mermaid-svg-6RtN94wAZfIjeVOM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6RtN94wAZfIjeVOM .icon-shape .label rect,#mermaid-svg-6RtN94wAZfIjeVOM .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6RtN94wAZfIjeVOM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6RtN94wAZfIjeVOM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6RtN94wAZfIjeVOM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输出 10 列
engineer_features
原始 8 列
MedInc
AveRooms
AveBedrms
AveOccup
其他...
BedroomsRatio = AveBedrms / AveRooms
RoomsPerHousehold = AveRooms / AveOccup
原 8 列保留
- 2 个新列
重要原则:
- 训练集、测试集分别 调用同一个
engineer_features(),保证变换规则一致 - 除法用
.replace(0, np.nan)防除零,再fillna(0)处理无效值 - 不用训练集均值/方差去变换测试集(本步无此类全局统计,无泄露)
7.7 任务清单
- 实现
engineer_features(),新增BedroomsRatio、RoomsPerHousehold - 用 HistGBR(与步骤 6 相同参数)分别训练工程前/后
- 对比 RMSE、R2,保存报告与对比图
- 如实解读:小幅改善也是结论
7.8 运行本步
powershell
cd "d:\JavaCode\机器学习\project_01_housing"
python src/train.py
7.9 实验结果(你的环境)
| 阶段 | 特征数 | 测试 RMSE | 测试 R2 |
|---|---|---|---|
| 工程前 HistGBR | 8 | 0.4763 | 0.8341 |
| 工程后 HistGBR | 10 | 0.4745 | 0.8354 |
| 变化 | +2 | -0.0018 | +0.0013 |
关键发现:
- 新特征带来小幅 改善:RMSE 从 0.4763 → 0.4745(约 0.38% 相对降幅)
- R2 从 0.8341 → 0.8354,方向一致但幅度很小
- 说明:HistGBR 可能已隐式 从
AveRooms、AveBedrms、AveOccup学到类似交互;显式比例特征仍有一点边际收益 - 有效结论:不是「特征越多越好」------2 个精心设计的特征略好,但远不及步骤 6 换模型带来的跃升(0.75 → 0.48)
7.10 核心代码解读
(1)engineer_features ------ 行内构造,无泄露
python
X_new = X.copy()
X_new["BedroomsRatio"] = X["AveBedrms"] / X["AveRooms"].replace(0, np.nan)
X_new["RoomsPerHousehold"] = X["AveRooms"] / X["AveOccup"].replace(0, np.nan)
X_new = X_new.replace([np.inf, -np.inf], np.nan).fillna(0)
| 要点 | 说明 |
|---|---|
X.copy() |
不修改传入的原始 DataFrame |
.replace(0, np.nan) |
除数为 0 时先变 NaN,避免 inf |
fillna(0) |
极少数无效行填 0(本数据集几乎遇不到) |
无 fit 步骤 |
不依赖训练集统计量,测试集可同样应用 |
(2)train_best_tree_model ------ 公平对比
工程前、工程后使用相同 的 HistGradientBoostingRegressor(max_iter=100, random_state=42),唯一变量是特征矩阵列数。这样 RMSE 差异才可归因于特征工程。
(3)对比解读阈值
python
if rmse_diff < -0.001:
print("结论:新特征带来小幅改善。")
差值 0.0018 略大于 0.001,脚本判定为「小幅改善」。若差值在 ±0.001 内,应视为基本持平------这在强树模型上很常见。
7.11 输出文件
| 文件 | 说明 |
|---|---|
reports/feature_engineering_report.txt |
工程前后 RMSE/R2 文本报告 |
reports/figures/09_feature_engineering_rmse.png |
工程前后 RMSE 条形对比图(中文) |
7.12 动手任务
任务 A :运行脚本,确认工程后 RMSE ≈ 0.4745
任务 B :打开 09_feature_engineering_rmse.png,对比两根柱子高度
任务 C :用自己的话解释 BedroomsRatio 和 RoomsPerHousehold 分别代表什么
任务 D:在 README 写:为什么本步提升很小?树模型已经很强时特征工程还值得做吗?
7.13 验收标准
- 能写出两个新特征的公式与业务含义
- 能说明为何本步用「同一模型、不同特征」做对比
- 能解释「无提升或小幅提升」也是有效实验结论
- 能区分「换模型(步骤 6)」与「造特征(步骤 7)」对指标的影响量级
7.14 动手任务与验收标准参考答案
以下为教学标准答案,便于自学对照;
README.md学习记录仍建议用自己的话写。
动手任务答案
| 任务 | 参考答案 |
|---|---|
| A | 工程后 HistGBR 测试 RMSE≈0.4745。 |
| B | 工程后柱略低于工程前(0.4763→0.4745),改善很小但方向一致。 |
| C | BedroomsRatio = 卧室数/总房间数,反映卧室占比;RoomsPerHousehold = 总房间数/入住人数,反映人均可用房间数。 |
| D | 提升很小因为 HistGBR 已从原始列隐式学到类似关系;仍值得建立可复现对比流程;换模型(0.75→0.48)收益远大于造 2 个特征(0.4763→0.4745)。 |
验收标准答案
| 验收项 | 参考答案 |
|---|---|
| 两个新特征 | BedroomsRatio=AveBedrms/AveRooms;RoomsPerHousehold=AveRooms/AveOccup。 |
| 同一模型对比 | 唯一变量是特征列,RMSE 差异才可归因于特征工程。 |
| 小幅提升也有效 | 没涨分也是结论,说明树已够用或特征冗余。 |
| 影响量级 | 换模型 RMSE 降约 0.27;造特征降约 0.002。 |
7.15 常见问题
Q:只降 0.0018 RMSE,算成功吗?
A:算。真实项目里,在已经很强的模型上,特征工程常常是「抠细节」。重要的是你建立了可复现的对比流程,而不是每次都必须大涨。
Q:为什么不造 10 个、20 个特征?
A:特征越多,噪声和过拟合风险越高,且难维护。本步刻意只加 2 个有业务含义的特征,练习「少而精」。
Q:工程后要不要对 10 列做 StandardScaler?
A:HistGBR 是树模型,与步骤 6 一样不需要缩放。若换回线性模型,才需重新考虑缩放。
Q:能否在划分 train/test 之前做特征工程?
A:本步的行内四则运算,先工程再划分与先划分再工程,结果等价。但若特征用到全局统计 (如全表均值),必须先划分再在训练集上 fit,否则会泄露。
7.16 本步小结
| 要点 | 内容 |
|---|---|
| 新增特征 | BedroomsRatio、RoomsPerHousehold |
| 对比模型 | HistGBR(与步骤 6 相同) |
| 工程前 RMSE | 0.4763 |
| 工程后 RMSE | 0.4745(当前项目最佳) |
| 关键教训 | 特征工程是「挤水分」;强模型下边际收益有限 |
| 下一步 | 总结全部实验、选最终模型、joblib 保存 |
7.17 学习记录(请你填写)
- 完成日期:
- 动手任务完成情况:任务 A / B / C / D
- 我对特征工程的理解:
- 疑问(如有):
步骤 8:总结与模型选择
状态 :✅ 已完成教学(报告见
reports/final_project_summary.txt,图表见10_final_all_models_rmse.png,模型见models/housing_best.pkl)
8.1 本步目标
- 汇总步骤 4~7 全部代表模型的测试集指标
- 按测试集 RMSE 最低选出项目一最终模型
- 写 3~5 句项目结论(最佳模型、关键特征、过拟合、改进方向)
- 用
joblib.dump保存模型,保证可复现、可部署
8.2 这一步在解决什么问题?
前面 7 步分别做了 Baseline、正则化、树模型、特征工程------每一步都有结论,但缺少一张总表回答:
- 项目一到底哪个模型最好?
- 相对 Baseline 提升了多少?
- 最终模型有没有过拟合?
- 训练好的模型如何保存、下次怎么用?
步骤 8 就是机器学习项目的收尾:实验汇总 → 模型选择 → 持久化 → 复盘。
8.3 本步在整体流程中的位置
#mermaid-svg-YVnU2V6lxhSsso9S{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YVnU2V6lxhSsso9S .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YVnU2V6lxhSsso9S .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YVnU2V6lxhSsso9S .error-icon{fill:#552222;}#mermaid-svg-YVnU2V6lxhSsso9S .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YVnU2V6lxhSsso9S .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YVnU2V6lxhSsso9S .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YVnU2V6lxhSsso9S .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YVnU2V6lxhSsso9S .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YVnU2V6lxhSsso9S .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YVnU2V6lxhSsso9S .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YVnU2V6lxhSsso9S .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YVnU2V6lxhSsso9S .marker.cross{stroke:#333333;}#mermaid-svg-YVnU2V6lxhSsso9S svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YVnU2V6lxhSsso9S p{margin:0;}#mermaid-svg-YVnU2V6lxhSsso9S .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-YVnU2V6lxhSsso9S .cluster-label text{fill:#333;}#mermaid-svg-YVnU2V6lxhSsso9S .cluster-label span{color:#333;}#mermaid-svg-YVnU2V6lxhSsso9S .cluster-label span p{background-color:transparent;}#mermaid-svg-YVnU2V6lxhSsso9S .label text,#mermaid-svg-YVnU2V6lxhSsso9S span{fill:#333;color:#333;}#mermaid-svg-YVnU2V6lxhSsso9S .node rect,#mermaid-svg-YVnU2V6lxhSsso9S .node circle,#mermaid-svg-YVnU2V6lxhSsso9S .node ellipse,#mermaid-svg-YVnU2V6lxhSsso9S .node polygon,#mermaid-svg-YVnU2V6lxhSsso9S .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YVnU2V6lxhSsso9S .rough-node .label text,#mermaid-svg-YVnU2V6lxhSsso9S .node .label text,#mermaid-svg-YVnU2V6lxhSsso9S .image-shape .label,#mermaid-svg-YVnU2V6lxhSsso9S .icon-shape .label{text-anchor:middle;}#mermaid-svg-YVnU2V6lxhSsso9S .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YVnU2V6lxhSsso9S .rough-node .label,#mermaid-svg-YVnU2V6lxhSsso9S .node .label,#mermaid-svg-YVnU2V6lxhSsso9S .image-shape .label,#mermaid-svg-YVnU2V6lxhSsso9S .icon-shape .label{text-align:center;}#mermaid-svg-YVnU2V6lxhSsso9S .node.clickable{cursor:pointer;}#mermaid-svg-YVnU2V6lxhSsso9S .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YVnU2V6lxhSsso9S .arrowheadPath{fill:#333333;}#mermaid-svg-YVnU2V6lxhSsso9S .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YVnU2V6lxhSsso9S .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YVnU2V6lxhSsso9S .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YVnU2V6lxhSsso9S .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YVnU2V6lxhSsso9S .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YVnU2V6lxhSsso9S .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YVnU2V6lxhSsso9S .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YVnU2V6lxhSsso9S .cluster text{fill:#333;}#mermaid-svg-YVnU2V6lxhSsso9S .cluster span{color:#333;}#mermaid-svg-YVnU2V6lxhSsso9S div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YVnU2V6lxhSsso9S .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YVnU2V6lxhSsso9S rect.text{fill:none;stroke-width:0;}#mermaid-svg-YVnU2V6lxhSsso9S .icon-shape,#mermaid-svg-YVnU2V6lxhSsso9S .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YVnU2V6lxhSsso9S .icon-shape p,#mermaid-svg-YVnU2V6lxhSsso9S .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YVnU2V6lxhSsso9S .icon-shape .label rect,#mermaid-svg-YVnU2V6lxhSsso9S .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YVnU2V6lxhSsso9S .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YVnU2V6lxhSsso9S .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YVnU2V6lxhSsso9S :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 步骤4 Baseline 0.75
步骤5 Lasso 0.75
步骤6 树模型 0.48
步骤7 特征工程 0.47
步骤8 汇总选模
final_project_summary.txt
housing_best.pkl
10_final_all_models_rmse.png
8.4 名词解释(本步首次出现)
| 名词 | 是什么 | 为什么需要 | 在本项目中 | 易混淆 |
|---|---|---|---|---|
| 模型选择 | 在多个候选模型中选出表现最好者 | 避免凭感觉选模型 | 按测试 RMSE 选 HistGBR+特征工程 | 不是越复杂越好 |
| joblib | Python 序列化库,擅长保存 numpy/sklearn 对象 | 训练一次、多次推理 | models/housing_best.pkl |
不是 pickle 手写 |
| 模型持久化 | 把训练好的模型写入磁盘 | 部署、复现、分享 | bundle 含 model + 元数据 | 不是只存权重 CSV |
| 过拟合 | 模型在训练集上很好、测试集变差 | 选模时要检查泛化 | 训练 RMSE 0.39 vs 测试 0.47 | 不是训练误差大 |
| 可复现性 | 同样代码、同样数据得到同样结果 | 实验可信、便于协作 | random_state=42 固定划分与模型 |
不是只跑一次 |
8.5 模型选择流程(Mermaid)
#mermaid-svg-DKNR65IqQjHKb1Lr{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-DKNR65IqQjHKb1Lr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DKNR65IqQjHKb1Lr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DKNR65IqQjHKb1Lr .error-icon{fill:#552222;}#mermaid-svg-DKNR65IqQjHKb1Lr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DKNR65IqQjHKb1Lr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DKNR65IqQjHKb1Lr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DKNR65IqQjHKb1Lr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DKNR65IqQjHKb1Lr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DKNR65IqQjHKb1Lr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DKNR65IqQjHKb1Lr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DKNR65IqQjHKb1Lr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DKNR65IqQjHKb1Lr .marker.cross{stroke:#333333;}#mermaid-svg-DKNR65IqQjHKb1Lr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DKNR65IqQjHKb1Lr p{margin:0;}#mermaid-svg-DKNR65IqQjHKb1Lr .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-DKNR65IqQjHKb1Lr .cluster-label text{fill:#333;}#mermaid-svg-DKNR65IqQjHKb1Lr .cluster-label span{color:#333;}#mermaid-svg-DKNR65IqQjHKb1Lr .cluster-label span p{background-color:transparent;}#mermaid-svg-DKNR65IqQjHKb1Lr .label text,#mermaid-svg-DKNR65IqQjHKb1Lr span{fill:#333;color:#333;}#mermaid-svg-DKNR65IqQjHKb1Lr .node rect,#mermaid-svg-DKNR65IqQjHKb1Lr .node circle,#mermaid-svg-DKNR65IqQjHKb1Lr .node ellipse,#mermaid-svg-DKNR65IqQjHKb1Lr .node polygon,#mermaid-svg-DKNR65IqQjHKb1Lr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DKNR65IqQjHKb1Lr .rough-node .label text,#mermaid-svg-DKNR65IqQjHKb1Lr .node .label text,#mermaid-svg-DKNR65IqQjHKb1Lr .image-shape .label,#mermaid-svg-DKNR65IqQjHKb1Lr .icon-shape .label{text-anchor:middle;}#mermaid-svg-DKNR65IqQjHKb1Lr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-DKNR65IqQjHKb1Lr .rough-node .label,#mermaid-svg-DKNR65IqQjHKb1Lr .node .label,#mermaid-svg-DKNR65IqQjHKb1Lr .image-shape .label,#mermaid-svg-DKNR65IqQjHKb1Lr .icon-shape .label{text-align:center;}#mermaid-svg-DKNR65IqQjHKb1Lr .node.clickable{cursor:pointer;}#mermaid-svg-DKNR65IqQjHKb1Lr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-DKNR65IqQjHKb1Lr .arrowheadPath{fill:#333333;}#mermaid-svg-DKNR65IqQjHKb1Lr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DKNR65IqQjHKb1Lr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DKNR65IqQjHKb1Lr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DKNR65IqQjHKb1Lr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-DKNR65IqQjHKb1Lr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DKNR65IqQjHKb1Lr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-DKNR65IqQjHKb1Lr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DKNR65IqQjHKb1Lr .cluster text{fill:#333;}#mermaid-svg-DKNR65IqQjHKb1Lr .cluster span{color:#333;}#mermaid-svg-DKNR65IqQjHKb1Lr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-DKNR65IqQjHKb1Lr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DKNR65IqQjHKb1Lr rect.text{fill:none;stroke-width:0;}#mermaid-svg-DKNR65IqQjHKb1Lr .icon-shape,#mermaid-svg-DKNR65IqQjHKb1Lr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DKNR65IqQjHKb1Lr .icon-shape p,#mermaid-svg-DKNR65IqQjHKb1Lr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-DKNR65IqQjHKb1Lr .icon-shape .label rect,#mermaid-svg-DKNR65IqQjHKb1Lr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DKNR65IqQjHKb1Lr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DKNR65IqQjHKb1Lr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DKNR65IqQjHKb1Lr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 保存阶段
选择阶段
训练阶段
各步训练代表模型
在测试集上算 RMSE
find_best_model 取 RMSE 最小
检查 train vs test 差距
joblib.dump bundle
报告 + 对比图
选择原则:
- 本步用同一次 train/test 划分,保证各模型指标可比
- 以测试集 RMSE 为唯一排序标准(回归任务的主指标)
- 若多个模型 RMSE 接近,优先选更简单、更易维护的(本项目中工程后 HistGBR 仍是最优)
8.6 任务清单
- 汇总步骤 4~7 代表模型指标表
- 选出测试 RMSE 最低模型
- 写 3~5 句项目结论
-
joblib.dump保存到models/housing_best.pkl - 生成全部模型 RMSE 对比图
8.7 运行本步
powershell
cd "d:\JavaCode\机器学习\project_01_housing"
python src/train.py
8.8 全部实验汇总(你的环境)
| 步骤 | 模型 | 测试 RMSE | 测试 R2 |
|---|---|---|---|
| 4 | 线性回归 Baseline | 0.7514 | 0.5871 |
| 5 | Lasso alpha=0.01 | 0.7472 | 0.5917 |
| 6 | 随机森林 | 0.5190 | 0.8030 |
| 6 | 梯度提升 HistGBR | 0.4763 | 0.8341 |
| 7 | 工程后 HistGBR | 0.4745 | 0.8354 |
最终选定模型:步骤 7 工程后 HistGBR
| 集合 | RMSE | R2 |
|---|---|---|
| 训练集 | 0.3918 | 0.8840 |
| 测试集 | 0.4745 | 0.8354 |
| 差距 | +0.0826 | --- |
关键发现:
- 相对 Baseline,最终 RMSE 降低约 36.9%(0.7514 → 0.4745)
- 换模型(步骤 6)贡献最大;特征工程(步骤 7)是「挤水分」式小幅优化
- 测试 RMSE 比训练高约 0.08,存在轻度过拟合 ,生产环境可进一步调
max_iter、深度或做交叉验证 - 随机森林特征重要性(步骤 6)表明 MedInc 收入是最重要特征
8.9 项目结论(3~5 句)
- 最终模型为 HistGradientBoostingRegressor + 2 个工程特征 ,测试 RMSE=0.4745 ,R2=0.8354。
- 相对线性 Baseline(RMSE=0.7514),RMSE 降低约 36.9% ,说明房价问题非线性强,树模型远优于线性模型。
- MedInc(收入中位数) 是最重要特征,区域经济实力是房价首要驱动因素。
- 训练/测试 RMSE 有差距,存在轻度过拟合,可通过调参或交叉验证进一步改善。
- 模型已用
joblib保存至models/housing_best.pkl,random_state=42保证可复现。
8.10 核心代码解读
(1)build_full_project_summary ------ 一次跑完全部代表模型
在同一次 train/test 划分上,依次训练 Baseline、Lasso、RF、HistGBR、工程后 HistGBR,保证指标横向可比。
(2)save_best_model_bundle ------ 打包保存
python
bundle = {
"model_name": best_result["name"],
"model": best_result["model"],
"feature_columns": feature_columns, # 10 列名
"uses_feature_engineering": True,
"random_state": RANDOM_STATE,
"test_metrics": best_result["test"],
}
joblib.dump(bundle, MODELS_DIR / "housing_best.pkl")
| 字段 | 作用 |
|---|---|
model |
训练好的 HistGBR,可直接 .predict() |
uses_feature_engineering |
提醒加载后需先 engineer_features |
feature_columns |
推理时校验列名与顺序 |
test_metrics |
记录选型时的测试表现 |
(3)加载与推理示例
python
import joblib
from train import engineer_features # 或复制 engineer_features 函数
bundle = joblib.load("models/housing_best.pkl")
X_raw = ... # 原始 8 列 DataFrame
X_fe = engineer_features(X_raw)
y_pred = bundle["model"].predict(X_fe)
8.11 输出文件
| 文件 | 说明 |
|---|---|
reports/final_project_summary.txt |
全部模型指标 + 项目结论 |
reports/figures/10_final_all_models_rmse.png |
步骤 4~7 RMSE 对比图(中文) |
models/housing_best.pkl |
最终模型 joblib 打包文件 |
8.12 动手任务
任务 A :运行脚本,确认最终 RMSE ≈ 0.4745
任务 B :打开 10_final_all_models_rmse.png,找出绿色柱子(最佳模型)
任务 C :用 Python 加载 housing_best.pkl,打印 bundle.keys() 和 bundle['test_metrics']
任务 D:在 README 填写项目一完整实验记录表和你的 3 句话心得
8.13 验收标准
- 能说出项目一最终模型名称与测试 RMSE
- 能解释为何用测试集 RMSE 选模型
- 能说明
housing_best.pkl里保存了什么 - 能描述 Baseline → 树模型 → 特征工程的提升路径
8.14 动手任务与验收标准参考答案
以下为教学标准答案,便于自学对照;
README.md学习记录仍建议用自己的话写。
动手任务答案
| 任务 | 参考答案 |
|---|---|
| A | 最终测试 RMSE≈0.4745。 |
| B | 绿色(或标注最佳)柱子对应 工程后 HistGBR。 |
| C | 示例:bundle.keys() 含 model_name、test_metrics 等;test_metrics 中 RMSE≈0.4745、R2≈0.8354。 |
| D | 在 README 填写完整实验表;心得示例:① 先 Baseline 再优化 ② 树模型适合非线性 ③ 测试集选模、joblib 便于部署。 |
验收标准答案
| 验收项 | 参考答案 |
|---|---|
| 最终模型与 RMSE | 工程后 HistGradientBoostingRegressor ,测试 RMSE 0.4745。 |
| 用测试集 RMSE 选模 | 测试集未参与训练,反映泛化;训练集 RMSE 会偏向过拟合模型。 |
| pkl 内容 | bundle 含模型对象、特征列名、random_state、test_metrics 等元数据。 |
| 提升路径 | Baseline LR 0.7514 → Lasso 0.7472 → HistGBR 0.4763 → 特征工程 0.4745。 |
8.15 常见问题
Q:为什么不把 StandardScaler 也打进 pkl?
A:最终模型是 HistGBR,不需要缩放。若最终模型是 Lasso,则应同时保存 scaler。
Q:能否用训练集 RMSE 选模型?
A:不能。训练集指标会偏向过拟合模型,必须用未参与训练的测试集。
Q:0.0826 的训练-测试差距严重吗?
A:对本学习项目属轻度过拟合。树模型常见此现象,可通过减小 max_iter、限制深度、早停等缓解。
Q:项目一完成后下一步学什么?
A:见 机器学习实战学习路线.md 项目二:信用卡欺诈检测(不平衡分类)。
8.16 本步小结
| 要点 | 内容 |
|---|---|
| 最终模型 | 步骤 7 工程后 HistGBR |
| 测试 RMSE | 0.4745 |
| 相对 Baseline | 降低约 36.9% |
| 最重要特征 | MedInc 收入 |
| 模型文件 | models/housing_best.pkl |
| 项目状态 | 项目一 8 步全部完成 |
8.17 学习记录(请你填写)
- 完成日期:
- 动手任务完成情况:任务 A / B / C / D
- 我对模型选择与持久化的理解:
- 项目一整体收获:
- 疑问(如有):
附录:推荐学习节奏
| 步骤 | 建议用时 | 难度 |
|---|---|---|
| 步骤 1 | 30 分钟 | ★☆☆ |
| 步骤 2 | 1~2 小时 | ★★☆ |
| 步骤 3 | 30 分钟 | ★☆☆ |
| 步骤 4 | 1 小时 | ★★☆ |
| 步骤 5 | 1~2 小时 | ★★☆ |
| 步骤 6 | 1~2 小时 | ★★★ |
| 步骤 7 | 1 小时 | ★★☆ |
| 步骤 8 | 30 分钟 | ★☆☆ |
文档版本:v1.9 | 最后更新:全步骤动手任务与验收标准参考答案已补充 | 项目一全部完成