十八套房、两个特征,学出面积系数 1.0489、房龄系数 -2.2789。 训练集 R 方 0.9962,测试集 0.9830,测试 RMSE 3.93 万元。 训练集分数比测试集高是正常的,差得太多才叫过拟合。
这一篇把上一篇的三步走完整跑一遍:划分数据、训练、打分。 数据是自造的十八套房,面积、房龄两个特征,单位分别是平米、年、万元。
一、最小二乘在干什么
它要找一条直线(或平面),让所有点到这条线的竖直距离平方和最小。 「平方」是为了让正负误差不互相抵消,也让大误差罚得更重。 有解析解,直接算出来,不用迭代。这正是它快的原因。
sklearn 里就是 LinearRegression(),一行建好,一行 fit 完。
二、为什么要留一份测试集
十八套房,分十三套训练、五套测试,比例大约七三开。 训练集学规律,测试集考成绩。 拿训练集考自己,等于考前把答案给了学生,考一百分也说明不了什么。
train_test_split 的 random_state=42 是种子。不写的话每次划分都不一样。
不写种子,分数就忽高忽低,两个模型根本没法比。
三、系数怎么读
截距 43.3143,面积系数 1.0489,房龄系数 -2.2789。 面积每多一平米,价格多 1.05 万;房龄每多一年,价格少 2.28 万。 正号同向、负号反向。房龄系数是负的,符合常识。
但两个系数不能直接比大小:一个以平米计、一个以年计,量纲差太远。
四、分数怎么读:R 方和 RMSE
训练集 R 方 0.9962,测试集 0.9830。 R 方是「解释了多少波动」,1 是完美,0 是跟猜平均值一样。 测试集 RMSE 是 3.93 万元,意思是「平均每次预测差三万多」。
两个指标要一起报:R 方是相对值好看,RMSE 是绝对值好懂。 只报 R 方 0.98,读者不知道是差 3 万还是差 30 万。
五、训练分比测试分高,正常吗
这次训练 0.9962,测试 0.9830,差了 0.013。 训练集通常比测试集好看,这不算问题。模型见过训练集,当然考得好。 判断标准不是「差没差」,而是「差多少」。差 0.01 到 0.05 很正常。
差 0.3 就得回头看:要么特征不够,要么样本太少,要么模型太复杂。
六、动手 Demo:最小二乘回归:预测房价
十八套房,面积和房龄两个特征,价格是目标。 先划分训练测试集,再训练、看系数、算 R 方和 RMSE。
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.model_selection import train_test_split
AREA = [62, 75, 88, 95, 105, 118, 128, 70, 82, 100, 112, 92,
66, 79, 91, 108, 122, 86]
AGE = [15, 12, 8, 5, 3, 2, 1, 18, 10, 6, 4, 9,
14, 11, 7, 5, 2, 9]
PRICE = [78, 92, 118, 128, 146, 163, 172, 76, 100, 134, 154, 118,
82, 98, 124, 148, 168, 112]
X = np.array([[AREA[i], AGE[i]] for i in range(18)], dtype=float)
y = np.array(PRICE, dtype=float)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.25, random_state=42)
print("训练 %d 条,测试 %d 条" % (len(Xtr), len(Xte)))
m = LinearRegression().fit(Xtr, ytr)
print("截距 %.4f,面积 %.4f,房龄 %.4f"
% (m.intercept_, m.coef_[0], m.coef_[1]))
print("训练 R 方 %.4f,测试 R 方 %.4f"
% (r2_score(ytr, m.predict(Xtr)), r2_score(yte, m.predict(Xte))))
print("测试 RMSE %.2f 万元"
% (mean_squared_error(yte, m.predict(Xte)) ** 0.5))
print("一套 100 平米、5 年房龄的预测价:%.2f 万元"
% m.predict([ [100, 5]])[0])
实跑输出:
--------------------------------------------------------------------
最小二乘回归:预测房价
--------------------------------------------------------------------
① 数据长什么样
--------------------------------------------------------------------
十八套房,两个特征:面积(平米)和房龄(年),目标是价格(万元)。
| 面积 | 房龄 | 价格 |
|---:|---:|---:|
| 62 | 15 | 78 |
| 75 | 12 | 92 |
| 88 | 8 | 118 |
| 95 | 5 | 128 |
| 105 | 3 | 146 |
| 118 | 2 | 163 |
| 128 | 1 | 172 |
| 70 | 18 | 76 |
面积从 62 到 128 平米,房龄从 1 到 18 年,价格从 76 到 172 万。
! 样本只有十八个,结论只能当练习用。真做房价模型,几百上千条才算起步。
② 留一部分做考试
--------------------------------------------------------------------
总共 18 条,训练集 13 条,测试集 5 条。
训练集学规律,测试集考成绩。拿训练集考自己,等于把答案提前给了学生。
! random_state=42 是写死的种子。不写的话每次划分都不一样,分数忽高忽低没法比。
③ 训练与系数
--------------------------------------------------------------------
截距 43.3143,面积系数 1.0489,房龄系数 -2.2789。
读法:面积每多一平米,价格多 1.0489 万;房龄每多一年,价格少 2.2789 万。
系数为正说明同向,为负说明反向。房龄系数是负的,符合常识。
! 系数的大小不能直接比重要性——面积以平米计、房龄以年计,量纲不同,得先标准化。
④ 打分:R 方和 RMSE
--------------------------------------------------------------------
训练集 R 方 0.9962,测试集 R 方 0.9830。
测试集 RMSE 3.93 万元。
R 方是「解释了多少波动」,越接近 1 越好;RMSE 是「平均差多少万」,越小越好。
两个指标一起报:R 方好看不代表误差小,单位不一样,读者感受也不一样。
! R 方 0.9 的意思是「价格的波动里有九成能被面积和房龄解释」,剩下一成是别的因素。
⑤ 训练集比测试集好,正常吗
--------------------------------------------------------------------
这次训练集 R 方 0.9962,测试集 0.9830。
训练集通常比测试集好看,这不算问题。差得太多才是问题——那叫过拟合。
判断标准不是「差没差」,而是「差多少」。差个 0.05 无妨,差 0.3 就得回头看。
! 样本只有 5 条测试数据,R 方的波动会很大。小样本上的分数,看趋势别看小数位。
test_size=0.25 是「四分之一拿去考试」。样本少时常用 0.2 到 0.3。
random_state 一定要写。同一份数据换一次划分,R 方可能差零点几。
predict 的入参形状要和训练时一致:两个特征就写两个数,[ [100, 5]]。
30 秒实验
- 把 random_state 改成 7,再跑一次,看测试 R 方差多少。
- 只留面积一个特征,去掉房龄,看 R 方掉多少。
- 想一想:如果 R 方 0.98 但 RMSE 30 万,这个模型能用吗?
常见误区
- 不划分测试集:训练分再高,也不知道模型在新数据上行不行。
- 不写 random_state:每次划分不同,前后两次结果没法比。
- 只报 R 方不报 RMSE:读者感受不到「差多少钱」。
- 直接比系数大小:量纲不同,得先标准化才能比重要性。
自测三问(点开对答案)
1. 为什么必须留测试集? —— 训练集只能说明「背得下来」,测试集才能说明「会不会做新题」。 2. R 方 0.9830 是什么意思? —— 价格波动里有 98.3% 能被面积和房龄解释,剩下 1.7% 是别的因素。 3. 训练分比测试分高,什么时候该担心? —— 差得少很正常;差很多(比如 0.3)才说明过拟合。系数看着还行,可一旦特征变多,最小二乘就不稳了。下一篇:岭回归。
- ☐ (本篇完,下一篇 8.3 岭回归:给系数上缰绳)