Vibe Programming × Python 数据分析
首页
8 周课表
每周实践
DSH 手册
GitHub
首页
8 周课表
每周实践
DSH 手册
GitHub
  • 首页
  • 8 周课表
  • 核心提示词
  • DSH 手册
  • 每周实践教程

    • Week 1:认识 Agent、安全使用 DSH,并完成第一个数据问题
    • Week 2 Python 编程基础
    • Week 3 pandas 基础
    • Week 4 数据可视化
    • Week 5 数据清洗与分组聚合
    • Week 6 第一个预测模型(分类)
    • Week 7 回归模型与业务解释
    • Week 8 结课项目与展示
  • 结课项目

    • 结课项目说明
    • 结课项目评分表

Week 7 回归模型与业务解释

本章导读 时长:3 节课,每节 45 分钟 数据:data/07-modeling/BostonHousing.csv 参考脚本:scripts/07-regression/ 下 4 个文件,与正文代码块一一对应。 你将学到:建立第一个线性回归模型,用 MAE、RMSE、R² 评估误差,解释系数方向、相关性与共线性,最后把结果翻译成能上桌的业务结论和不确定项 本周产出:projects/<姓名>/week7_regression.py、projects/<姓名>/week7_regression.md

本周三节课:

  1. 第 1 节课:线性回归、训练/测试集与 MAE/RMSE/R²;
  2. 第 2 节课:系数方向、相关性与 Ridge 正则化;
  3. 第 3 节课:业务解释与决策边界。

本周围绕同一份波士顿房价数据,按固定流程走:

flowchart LR
    A[数据:506 行<br/>14 列,目标 medv] --> B[选特征]
    B --> C[切分训练集/测试集]
    C --> D[训练线性回归]
    D --> E[MAE / RMSE / R² 评估]
    E --> F[解释系数与业务边界]

使用 DSH 的安全规则:先说清目标和验收标准 → 先审 Agent 计划 → 看不懂就解释或暂停 → 执行最小一步 → 检查输出和文件改动 → 保存代码并写结论。 回归模型不是“算出一个数”,它必须能报出样本量、误差和基线;DSH 说“模型完成”不算完成,必须看到真实指标并能逐项解释。

回归问题一句话说清:目标是连续数值,模型给的是估计值,评估看误差。 本课预测 medv(房价中位数,单位千美元),不是真实成交价,也不代表今天任何具体城市。

1. 第 1 节课 线性回归、训练/测试集与 MAE/RMSE/R²(45 分钟)

1.1 节奏

  • 演示:读数据 → 切分 → 训练 → 输出 MAE/RMSE/R² 和均值基线。
  • 练习:按同样步骤跑通,再换特征、改 random_state 观察指标变化。
  • 复盘:解释三个指标的单位和样本量,完成验收。

1.2 数据与问题

数据:data/07-modeling/BostonHousing.csv,506 行、14 列,目标变量是 medv(自住房价中位数,单位千美元)。

本课用 6 个特征:

字段含义方向预期
crim城镇人均犯罪率犯罪率高,房价预期更低
rm每套住宅平均房间数房间多,房价预期更高
lstat低收入人口比例(%)低收入比例高,房价预期更低
ptratio学生/教师比比值高,房价预期更低
nox一氧化氮浓度污染重,房价预期更低
age1940 年前建成的自住房比例房屋旧,房价预期更低

要回答的问题:用这 6 个特征估计 medv,平均误差是多少,比“永远猜均值”好多少。

安全提醒:这是 1970 年代波士顿历史教学数据,medv 是当时的千美元口径,不代表今天的房价、也不代表任何具体城市。data/ 只读,本课不修改原数据。

1.3 DSH vibe loop

完整循环:

定义问题 → 要求最小版本 → 运行 → 反馈 → 追问 → 验证

第一版发给 DSH 的提示词只做两件事:读数据、跑一个最小回归。不要让它一次做完解释、调参和报告。

请读取 data/07-modeling/BostonHousing.csv,不要修改 data/。
只输出:
1. shape、缺失值、medv 的 describe;
2. 用 crim、rm、lstat、ptratio、nox、age 这 6 个特征预测 medv;
3. train_test_split(test_size=0.2, random_state=42);
4. 输出训练集/测试集样本量、MAE、RMSE、R²,以及“永远猜测试集均值”的 MAE/RMSE。
先给计划,不要一次写完整份报告,不要安装新依赖。

执行前检查命令:是否写文件、是否改 data/、随机步骤是否固定 random_state=42。执行后核对样本量和指标。测试集只用于最终评估,不能反过来用于训练。

1.4 核心代码

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

df = pd.read_csv('data/07-modeling/BostonHousing.csv')
features = ['crim', 'rm', 'lstat', 'ptratio', 'nox', 'age']
X = df[features]
y = df['medv']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

model = LinearRegression()
model.fit(X_train, y_train)

train_pred = model.predict(X_train)
test_pred = model.predict(X_test)
baseline_pred = [y_test.mean()] * len(y_test)

print('样本量:全量', len(df), ',训练集', len(X_train), ',测试集', len(X_test))
print('训练集 R2:', round(r2_score(y_train, train_pred), 4))
print('测试集 R2:', round(r2_score(y_test, test_pred), 4))
print('测试集 MAE:', round(mean_absolute_error(y_test, test_pred), 4))
print('测试集 RMSE:', round(mean_squared_error(y_test, test_pred) ** 0.5, 4))
print('基线(猜均值) MAE:', round(mean_absolute_error(y_test, baseline_pred), 4))
print('基线(猜均值) RMSE:', round(mean_squared_error(y_test, baseline_pred) ** 0.5, 4))
print('测试集 medv 均值:', round(y_test.mean(), 4))

脚本:01-boston-linear.py | 数据:BostonHousing.csv

运行建模前,先单独读数据并确认 df.shape 是 (506, 14)、缺失值是 0。

1.5 实际输出

(506, 14)
0
样本量:全量 506 ,训练集 404 ,测试集 102
训练集 R2: 0.6961
测试集 R2: 0.6226
测试集 MAE: 3.3659
测试集 RMSE: 5.2607
基线(猜均值) MAE: 5.9349
基线(猜均值) RMSE: 8.5635
测试集 medv 均值: 21.4882

注意两件事:训练集 404 条、测试集 102 条;模型测试集 MAE 3.37,比“永远猜均值”的 5.93 低,说明这些特征确实带来一些预测能力。

1.6 重点解释

三个指标都要带单位(千美元)和样本量(102 条测试集)解释:

指标含义本例
MAE平均绝对误差,每个预测平均差多少约 3.37 千美元
RMSE先平方再开方,大误差会被放大约 5.26 千美元
R²相对“永远猜均值”的改进比例测试集约 0.62
均值基线永远用测试集平均值当预测MAE 约 5.93,RMSE 约 8.56

解释要点:

  • MAE 3.37:测试集 102 条预测平均偏差约 3.37 千美元,是最直观的“平均差多少”。
  • RMSE 5.26 大于 MAE 3.37:说明存在少数误差很大的样本,平方后把它们放大。
  • R² 0.62:约 62% 的房价波动被这 6 个特征解释,还有约 38% 没被解释。R² 不是“准确率”,更不是“62% 的预测正确”。
  • 基线不能省略:只报 R² 0.62,别人不知道这个数字好不好。和“永远猜均值”比,MAE 从 5.93 降到 3.37,才说明模型有效。
  • 为什么先切分:模型只在 404 条训练集上拟合,102 条测试集模拟“没见过的新数据”。如果先看完全部数据再训练,分数会虚高,这是数据泄漏。

报告一个回归模型,至少要写:样本量、特征数、训练/测试切分、MAE、RMSE、R² 和一个简单基线。 只说“R² 0.62”不够。

1.7 课堂练习

  1. 把特征改成 ['rm', 'lstat'] 重新跑,报告样本量、训练/测试 R²、MAE、RMSE,并和 6 特征版本比较哪一组测试集误差更小。
  2. 解释为什么测试集 R²(0.6226)比训练集 R²(0.6961)低。
  3. 把 random_state=42 改成 random_state=7,观察三个指标是否变化;说明正式报告为什么固定 random_state=42。
  4. 用一句话说明:测试集 MAE 从基线 5.9349 降到模型 3.3659,业务上意味着什么。

1.8 第 1 节课验收

  • [ ] 能说出 medv 是目标变量,数据 506 行、14 列、0 缺失
  • [ ] 训练集 404 条、测试集 102 条,random_state=42,先切分再训练
  • [ ] 能运行线性回归,输出 MAE、RMSE、R² 和均值基线
  • [ ] 能说明 MAE/RMSE 的单位是千美元,R² 不是准确率
  • [ ] 能和“永远猜测试集均值”的基线比较,而不是只看单个指标
  • [ ] 能写出一句“模型预测不等于真实成交价”

1.9 扩展数据练习 mpg 油耗回归

用 data/07-modeling/mpg.csv 换一套数据重复第 1 节流程。目标是 mpg(每加仑英里数),特征包括 horsepower、weight、displacement、model_year 和 origin。origin 是分类字符串,需要先映射成数值。

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

df = pd.read_csv('data/07-modeling/mpg.csv')
df = df.dropna(subset=['horsepower', 'weight', 'displacement', 'model_year', 'origin', 'mpg'])
features = ['horsepower', 'weight', 'displacement', 'model_year', 'origin']
X = df[features].copy()
X['origin'] = X['origin'].map({'usa': 0, 'japan': 1, 'europe': 2})
y = df['mpg']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

model = LinearRegression().fit(X_train, y_train)
test_pred = model.predict(X_test)
baseline_pred = [y_test.mean()] * len(y_test)

print('样本量:全量', len(df), ',训练集', len(X_train), ',测试集', len(X_test))
print('测试集 MAE:', round(mean_absolute_error(y_test, test_pred), 4))
print('测试集 RMSE:', round(mean_squared_error(y_test, test_pred) ** 0.5, 4))
print('测试集 R2:', round(r2_score(y_test, test_pred), 4))
print('基线(猜均值) MAE:', round(mean_absolute_error(y_test, baseline_pred), 4))
print('基线(猜均值) RMSE:', round(mean_squared_error(y_test, baseline_pred) ** 0.5, 4))

脚本:04-mpg-regression.py | 数据:mpg.csv

实际输出:

样本量:全量 392 ,训练集 313 ,测试集 79
测试集 MAE: 2.5767
测试集 RMSE: 3.2832
测试集 R2: 0.7888
基线(猜均值) MAE: 5.8176
基线(猜均值) RMSE: 7.1443

读法:392 个样本去掉 6 个缺失后进入训练。测试集 79 条,模型 MAE 2.58、RMSE 3.28,明显低于猜均值的 5.82 和 7.14,说明这些特征对油耗有预测价值。

练习:

  1. 去掉 origin 重跑,报告测试集 R² 和 RMSE 变化,说明产地信息是否带来额外预测能力。
  2. 把 model_year 从数值列改成字符串再跑,观察 sklearn 报错,解释分类变量为什么不能直接进入线性回归。
  3. 用 df['weight'].corr(df['mpg']) 和 df['horsepower'].corr(df['mpg']) 分别报告两个相关系数,并比较方向。

2. 第 2 节课 系数方向、相关性与 Ridge 正则化(45 分钟)

2.1 节奏

  • 演示:标准化系数、相关系数和 Ridge 对比。
  • 练习:解释每个特征的方向,尝试不同 alpha,说明符号翻转。
  • 复盘:相关不等于因果,系数不等于单个特征的贡献。

2.2 数据与问题

数据仍是 data/07-modeling/BostonHousing.csv,目标变量 medv。本课回答三个问题:

  1. 哪些特征把估计值往上推、哪些往下推?
  2. 特征之间是否互相相关,会不会干扰系数解释?
  3. 这份数据有没有明显过拟合,Ridge 正则化能带来多少改变?

2.3 DSH vibe loop

定义问题 → 要求最小版本 → 运行 → 反馈 → 追问 → 验证

发给 DSH 的提示词限定在“解释”而不是“调参”:

沿用 data/07-modeling/BostonHousing.csv,特征 crim、rm、lstat、ptratio、nox、age,
目标 medv,train_test_split(test_size=0.2, random_state=42)。
不要调参。请输出:
1. StandardScaler + LinearRegression 的标准化系数,按绝对值从大到小排;
2. 每个特征与 medv 的相关系数;
3. rm 与 lstat、nox 与 age 的相关系数;
4. LinearRegression 与 Ridge(alpha=1.0) 在测试集上的 R² 和 RMSE。
逐项解释方向和共线性,不要给因果结论。

执行前检查:是否有 StandardScaler 泄漏(必须放在 make_pipeline 里或拆分后只用训练集 fit)、是否只用了 pandas 和 scikit-learn。

2.4 核心代码

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.metrics import mean_squared_error, r2_score

df = pd.read_csv('data/07-modeling/BostonHousing.csv')
features = ['crim', 'rm', 'lstat', 'ptratio', 'nox', 'age']
X = df[features]
y = df['medv']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# 系数方向:先标准化,让不同量纲的系数可以比较大小
pipe = make_pipeline(StandardScaler(), LinearRegression())
pipe.fit(X_train, y_train)
coef = pipe.named_steps['linearregression'].coef_

print('标准化后的系数(按绝对值从大到小):')
for name, c in sorted(zip(features, coef), key=lambda t: -abs(t[1])):
    print(' ', name, round(c, 4))

print('各特征与 medv 的相关系数:')
for name in features:
    print(' ', name, round(df[name].corr(df['medv']), 4))

print('rm 与 lstat 相关系数:', round(df['rm'].corr(df['lstat']), 4))
print('nox 与 age 相关系数:', round(df['nox'].corr(df['age']), 4))

# Ridge 正则化对比
lin = LinearRegression().fit(X_train, y_train)
ridge = make_pipeline(StandardScaler(), Ridge(alpha=1.0)).fit(X_train, y_train)

print('线性回归 测试 R2:', round(r2_score(y_test, lin.predict(X_test)), 4))
print('Ridge    测试 R2:', round(r2_score(y_test, ridge.predict(X_test)), 4))
print('线性回归 测试 RMSE:', round(mean_squared_error(y_test, lin.predict(X_test)) ** 0.5, 4))
print('Ridge    测试 RMSE:', round(mean_squared_error(y_test, ridge.predict(X_test)) ** 0.5, 4))

脚本:02-boston-coefficients.py | 数据:BostonHousing.csv

2.5 实际输出

标准化后的系数(按绝对值从大到小):
  lstat -3.9774
  rm 3.4184
  ptratio -1.8905
  age 0.9266
  crim -0.7551
  nox -0.5523
各特征与 medv 的相关系数:
  crim -0.3883
  rm 0.6954
  lstat -0.7377
  ptratio -0.5078
  nox -0.4273
  age -0.377
rm 与 lstat 相关系数: -0.6138
nox 与 age 相关系数: 0.7315
线性回归 测试 R2: 0.6226
Ridge    测试 R2: 0.6228
线性回归 测试 RMSE: 5.2607
Ridge    测试 RMSE: 5.2593

2.6 重点解释

  • 标准化系数用来比较相对大小。 原始特征量纲差别很大(crim 约 0-88,rm 约 3-9,nox 约 0.38-0.87),原始系数不能直接比大小;标准化后系数越大,说明该特征在模型里的影响越强。本例 lstat(-3.9774)和 rm(+3.4184)影响最大。
  • 方向要对照业务预期。 rm 为正、lstat 为负、ptratio 为负、crim 为负、nox 为负,都和直觉一致;rm 原始系数约 +4.82,意思是“其他条件不变时,平均房间数每多 1 间,估计房价中位数约高 4.82 千美元”。
  • 相关系数和系数不是一回事。 相关系数是“只看这一个特征”,系数是“控制其他特征后看这一个特征”。age 与 medv 的相关系数是 -0.377,但标准化系数是 +0.9266,符号相反;原因是 age 与 nox 高度相关(0.7315),多元模型里符号被共线性翻转。不能拿单变量相关性的方向代替多元系数。
  • 共线性会让解释变脆。 rm 与 lstat 相关 -0.6138,nox 与 age 相关 0.7315,特征不是互相独立,所以“单独加一间房一定涨 4.82 千美元”这类话要谨慎,它依赖“其他特征不变”这个假设。
  • Ridge 在本数据几乎不改变结果。 线性回归测试 R² 0.6226、RMSE 5.2607;Ridge(alpha=1.0) 测试 R² 0.6228、RMSE 5.2593。差值是小数点后第三位,说明 6 个特征、404 条训练样本下没有明显过拟合。正则化不是“一键变好”的开关;只有当特征很多、共线性很强或样本很少时,它才更可能发挥作用。

2.7 课堂练习

  1. 用原始系数解释 rm 和 lstat 的方向,并说明为什么比较大小前要先标准化。
  2. 解释 age 的相关系数为负(-0.377)但标准化系数为正(+0.9266),指出可能的共线性来源。
  3. 把 Ridge 的 alpha 改成 0.01 和 10,比较测试 R²/RMSE,写一句“这份数据里正则化改变大不大”。
  4. 判断下面这句话错在哪:“rm 与 medv 相关系数 0.6954,所以房间数增加一定会让房价上涨。”

2.8 第 2 节课验收

  • [ ] 能输出标准化系数并解释每个特征的符号方向
  • [ ] 能说清相关系数和多元系数的区别
  • [ ] 能解释 age 相关系数为负但系数为正的共线性原因
  • [ ] 能指出 rm 与 lstat、nox 与 age 的相关强度
  • [ ] 能运行 Ridge 对比,并说明本数据中正则化几乎不改变结果
  • [ ] 不把系数直接说成因果关系

3. 第 3 节课 业务解释与决策边界(45 分钟)

3.1 节奏

  • 演示:两个具体样本的预测,并写成带 RMSE 的结论。
  • 练习:写“能支持什么、不能支持什么”,列出不确定项,互查结论。
  • 复盘:“估计值 + 误差区间”和“因果结论”的边界。

3.2 数据与问题

数据仍是 data/07-modeling/BostonHousing.csv。本课不再换模型,回答业务问题:

如果有人说“这个模型能预测波士顿房价”,它到底能支持什么决策、不能支持什么决策?

3.3 DSH vibe loop

定义问题 → 要求最小版本 → 运行 → 反馈 → 追问 → 验证

让 DSH 先给出“解释草稿”,再让学生审查,而不是让它替学生下结论:

沿用前面的波士顿房价线性回归(6 个特征,random_state=42)。
请基于测试集 RMSE 约 5.26 千美元、样本量 102 条,写一段结论草稿,要求:
1. 明确“估计值”和“真实成交价”的区别;
2. 写出模型能支持什么、不能支持什么;
3. 列出至少 3 个不确定项。
不要给因果结论,不要超出数据范围外推。

学生收到草稿后,逐句检查:每一句是否带样本量、指标、单位;有没有把估计写成事实;有没有偷偷变成因果结论。

3.4 核心代码

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

df = pd.read_csv('data/07-modeling/BostonHousing.csv')
features = ['crim', 'rm', 'lstat', 'ptratio', 'nox', 'age']
X = df[features]
y = df['medv']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

model = LinearRegression().fit(X_train, y_train)
test_pred = model.predict(X_test)
rmse = mean_squared_error(y_test, test_pred) ** 0.5
resid = y_test - test_pred

print('测试集 RMSE:', round(rmse, 4))
print('绝对误差中位数:', round(resid.abs().median(), 4))
print('误差在 ±5 千美元内:', round((resid.abs() <= 5).mean(), 4))
print('误差在 ±10 千美元内:', round((resid.abs() <= 10).mean(), 4))

# 其他字段取全量中位数,只看 rm 和 lstat 变化
row_a = pd.DataFrame([{
    'crim': df['crim'].median(), 'rm': 6.0, 'lstat': 12.0,
    'ptratio': df['ptratio'].median(), 'nox': df['nox'].median(),
    'age': df['age'].median(),
}], columns=features)
row_b = pd.DataFrame([{
    'crim': df['crim'].median(), 'rm': 7.0, 'lstat': 5.0,
    'ptratio': df['ptratio'].median(), 'nox': df['nox'].median(),
    'age': df['age'].median(),
}], columns=features)

print('rm=6、lstat=12 的估计:', round(model.predict(row_a)[0], 4))
print('rm=7、lstat=5 的估计:', round(model.predict(row_b)[0], 4))

脚本:03-boston-business-error.py | 数据:BostonHousing.csv

3.5 实际输出

测试集 RMSE: 5.2607
绝对误差中位数: 2.275
误差在 ±5 千美元内: 0.8137
误差在 ±10 千美元内: 0.9314
rm=6、lstat=12 的估计: 21.5761
rm=7、lstat=5 的估计: 30.3209

3.6 重点解释

  • 单个预测是估计值,不是成交价。 rm=6、lstat=12 的估计约 21.58 千美元,rm=7、lstat=5 的估计约 30.32 千美元。测试集 RMSE 约 5.26 千美元,意味着典型误差在这个量级;本数据中 81.37% 的测试误差落在 ±5 千美元内,93.14% 落在 ±10 千美元内。结论应写成“估计约 30.32 千美元,测试集 RMSE 约 5.26 千美元”,而不是“这套房值 30.32 千美元”。
  • 模型能支持什么: 在相同特征口径下比较相对高低(例如房间多、低收入比例低的样本估计更高),发现哪些特征与 medv 关联更强,作为进一步调查或筛选的线索。
  • 模型不能支持什么: 不能证明因果(不能说“加一间房导致房价涨”),不能外推到数据范围之外(例如把 rm 设成 20),不能给出单个成交价的保证,不能预测未来市场。
  • 决策边界在于“连续估计 + 误差”。 回归输出的是一个带误差的数值,不是“值不值”的是/否判断。要做“是否入手”这类决策,还需要阈值、业务代价和更多现场信息;模型只能提供估计和误差,不能替人做决定。
  • 结论模板:
在当前数据、当前特征、当前切分下,模型测试集 RMSE 约 5.26 千美元,样本 102 条。
它能支持:比较不同特征组合的相对高低,作为进一步核查的线索。
它不能支持:证明因果、给出精确成交价、预测未来市场。

3.7 课堂练习

  1. 用模型预测 rm=5、lstat=20(其他字段取中位数),写出带 RMSE 的一句结论。参考估计约 12.27 千美元。
  2. 写一段不超过 100 字的结论,必须包含:样本量、测试集 RMSE、能支持什么、不能支持什么。
  3. 列出至少 2 个不确定项,例如:数据是 1970 年代历史口径、样本只覆盖波士顿、因果无法证明、特征存在共线性。
  4. 判断这句话为什么不能写成事实:“把 rm 从 6 加到 7 且 lstat 从 12 降到 5,估计从 21.58 升到 30.32,说明改造房子能涨 8.7 千美元。”

3.8 第 3 节课验收

  • [ ] 能把单点预测写成“估计值 + RMSE”,不写成精确成交价
  • [ ] 能说出误差在 ±5 千美元、±10 千美元内的比例及样本量
  • [ ] 能写出模型能支持什么、不能支持什么
  • [ ] 能区分“相关/关联”和“因果”
  • [ ] 结论中列出至少 2 个不确定项
  • [ ] 不把连续估计硬说成“是/否”的业务决定

4. 本周验证清单

  • [ ] 三节课验收全部通过
  • [ ] data/ 只读,原始数据未被修改
  • [ ] 学生代码写入 projects/<姓名>/,路径使用 data/07-modeling/...
  • [ ] 所有建模代码设置 random_state=42,先切分训练/测试集再训练
  • [ ] 回归指标同时包含 MAE、RMSE、R² 和均值基线,并说明样本量
  • [ ] 能解释标准化系数的方向,指出 age 的符号翻转来自共线性
  • [ ] Ridge 对比能说明本数据中正则化几乎不改变结果
  • [ ] 结论区分“估计值”和“事实”,写清不确定项
  • [ ] 每次 DSH 都走完 定义问题 → 要求最小版本 → 运行 → 反馈 → 追问 → 验证
  • [ ] DSH 生成的建模代码能逐行解释每个指标,解释不出来就不算完成

5. 常见错误与坑

现象原因处理
用测试集反复试模型测试集被“训练”了最终指标只做一次,诊断用训练集或重新切分
不设 random_state每次切分结果不同所有随机步骤都固定 random_state=42
先标准化再切分测试集信息进入训练过程先切分;或把 StandardScaler 放进 make_pipeline
把 R² 当成准确率混淆回归和分类指标R² 是解释力,MAE/RMSE 才是误差
只报 R² 不报误差业务不知道实际差多少加 MAE、RMSE、单位和基线
把 MAE 当成每一套房都差这么多MAE 是平均误差结合 RMSE 和测试集误差分布看
用相关系数代替系数下结论忽略其他特征的影响同时看相关系数和标准化系数
把系数直接说成因果相关不等于因果写成“与……相关联”,并写清限制
把单点预测说成精确成交价忽略模型误差写成“估计值 + RMSE”,给出误差范围
把结果外推到数据范围之外模型只在训练数据范围内有效检查特征是否落在原数据区间内
认为 Ridge 一定让模型变好正则化不是万能开关用测试集指标比较,本数据几乎不变
DSH 说“完成”就相信没有验证代码和输出要求逐行解释,并亲自核对运行结果

6. 作业

  1. 把三节课的代码整理成 projects/<姓名>/week7_regression.py。要求:路径写 data/07-modeling/BostonHousing.csv;固定 random_state=42;先切分再训练;输出 MAE、RMSE、R² 和均值基线,并打印样本量。
  2. 写 projects/<姓名>/week7_regression.md,用中文解释:目标变量、6 个特征、训练/测试样本量、MAE/RMSE/R²、均值基线,以及每个标准化系数的方向。
  3. 写不超过 100 字:这个回归模型“能支持什么决策、不能支持什么决策”,并给出 1 个可执行的业务建议和至少 1 个数据限制。
  4. 让 DSH 审查 week7_regression.py,重点检查:是否有数据泄漏、是否只用了 pandas 和 scikit-learn、是否把预测写成事实。保留 DSH 的修改记录。

评分要点

项目要求
数据理解能指出 medv 是目标变量、数据 506 行 14 列、6 个特征的含义
数据拆分先切分、固定 random_state=42,训练 404 条、测试 102 条
回归评估能解释 MAE、RMSE、R²,并与“永远猜均值”基线比较
特征解释能说明系数方向、标准化意义和 age 的共线性符号翻转
正则化能运行 Ridge 对比,并说明本数据中改变很小
业务边界能区分估计值与事实、相关与因果,写清不确定项
防泄漏标准化放在拆分后或 Pipeline 里,测试集只用于评估
表达结论带样本量、单位和误差,不把模型说成因果或保证
Edit this page
最近更新: 2026/9/24 12:03
Contributors: Xianzhong Zhou
Prev
Week 6 第一个预测模型(分类)
Next
Week 8 结课项目与展示