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 节课:线性回归、训练/测试集与 MAE/RMSE/R²;
- 第 2 节课:系数方向、相关性与 Ridge 正则化;
- 第 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 | 一氧化氮浓度 | 污染重,房价预期更低 |
age | 1940 年前建成的自住房比例 | 房屋旧,房价预期更低 |
要回答的问题:用这 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 课堂练习
- 把特征改成
['rm', 'lstat']重新跑,报告样本量、训练/测试 R²、MAE、RMSE,并和 6 特征版本比较哪一组测试集误差更小。 - 解释为什么测试集 R²(0.6226)比训练集 R²(0.6961)低。
- 把
random_state=42改成random_state=7,观察三个指标是否变化;说明正式报告为什么固定random_state=42。 - 用一句话说明:测试集 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,说明这些特征对油耗有预测价值。
练习:
- 去掉
origin重跑,报告测试集 R² 和 RMSE 变化,说明产地信息是否带来额外预测能力。 - 把
model_year从数值列改成字符串再跑,观察 sklearn 报错,解释分类变量为什么不能直接进入线性回归。 - 用
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。本课回答三个问题:
- 哪些特征把估计值往上推、哪些往下推?
- 特征之间是否互相相关,会不会干扰系数解释?
- 这份数据有没有明显过拟合,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 课堂练习
- 用原始系数解释
rm和lstat的方向,并说明为什么比较大小前要先标准化。 - 解释
age的相关系数为负(-0.377)但标准化系数为正(+0.9266),指出可能的共线性来源。 - 把 Ridge 的
alpha改成0.01和10,比较测试 R²/RMSE,写一句“这份数据里正则化改变大不大”。 - 判断下面这句话错在哪:“
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 课堂练习
- 用模型预测
rm=5、lstat=20(其他字段取中位数),写出带 RMSE 的一句结论。参考估计约 12.27 千美元。 - 写一段不超过 100 字的结论,必须包含:样本量、测试集 RMSE、能支持什么、不能支持什么。
- 列出至少 2 个不确定项,例如:数据是 1970 年代历史口径、样本只覆盖波士顿、因果无法证明、特征存在共线性。
- 判断这句话为什么不能写成事实:“把
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. 作业
- 把三节课的代码整理成
projects/<姓名>/week7_regression.py。要求:路径写data/07-modeling/BostonHousing.csv;固定random_state=42;先切分再训练;输出 MAE、RMSE、R² 和均值基线,并打印样本量。 - 写
projects/<姓名>/week7_regression.md,用中文解释:目标变量、6 个特征、训练/测试样本量、MAE/RMSE/R²、均值基线,以及每个标准化系数的方向。 - 写不超过 100 字:这个回归模型“能支持什么决策、不能支持什么决策”,并给出 1 个可执行的业务建议和至少 1 个数据限制。
- 让 DSH 审查
week7_regression.py,重点检查:是否有数据泄漏、是否只用了 pandas 和 scikit-learn、是否把预测写成事实。保留 DSH 的修改记录。
评分要点
| 项目 | 要求 |
|---|---|
| 数据理解 | 能指出 medv 是目标变量、数据 506 行 14 列、6 个特征的含义 |
| 数据拆分 | 先切分、固定 random_state=42,训练 404 条、测试 102 条 |
| 回归评估 | 能解释 MAE、RMSE、R²,并与“永远猜均值”基线比较 |
| 特征解释 | 能说明系数方向、标准化意义和 age 的共线性符号翻转 |
| 正则化 | 能运行 Ridge 对比,并说明本数据中改变很小 |
| 业务边界 | 能区分估计值与事实、相关与因果,写清不确定项 |
| 防泄漏 | 标准化放在拆分后或 Pipeline 里,测试集只用于评估 |
| 表达 | 结论带样本量、单位和误差,不把模型说成因果或保证 |