《Python AI入门》第4章 预测的艺术——线性回归与加州房价预测
这一章,我们将正式引入大名鼎鼎的 Scikit-learn 库,带你像搭积木一样构建你的第一个预测模型。
章节导语
“在这个世界上,只有两类人试图预知未来:算命先生和机器学习工程师。前者的工具是水晶球,后者的工具是历史数据。”
欢迎来到监督学习(Supervised Learning)的世界。这是目前AI应用最广泛的领域,从推荐系统到自动驾驶,背后其实都遵循着同一个朴素的逻辑:从历史中寻找规律,用规律预测未来。
本章我们将学习最基础、最经典,也是所有AI算法的“老祖宗”——线性回归(Linear Regression)。别被名字骗了,它并不深奥。简单来说,它就是教计算机画一条“最准”的直线,穿过那一堆乱糟糟的数据点。
这一章,我们将正式引入大名鼎鼎的 Scikit-learn 库,带你像搭积木一样构建你的第一个预测模型。
4.1 学习目标
在学完本章后,你将能够:
-
打破黑盒:理解什么是特征(Features)、标签(Labels)和权重(Weights)。
-
直观理解算法:用“下山法”理解梯度下降(Gradient Descent),无需死记硬背数学公式。
-
掌握标准范式:熟练使用 Scikit-learn 的“三板斧”——
fit(训练)、predict(预测)、score(打分)。 -
工程思维:理解为什么一定要把数据切分为“训练集”和“测试集”。
-
实战落地:基于加州房价数据集,训练一个能根据房龄、收入预测房价的AI模型。
4.2 什么是线性回归?——给数据算个命
4.2.1 假如你要买房
想象一下,你是一名房产估价师。当你走进一套房子,你会怎么给它估价? 你心里可能有一个公式:
$$ 房价 = 基础价格 + (面积 \times 5万) + (房间数 \times 10万) + (离地铁距离 \times -2万) $$
在这个公式里:
-
特征 ($x$):面积、房间数、距离。这是客观存在的属性。
-
标签 ($y$):房价。这是我们想预测的目标。
-
权重 ($w$):5万、10万、-2万。这代表了你对每个特征重要性的判断(面积越大越贵,离地铁越远越便宜)。
-
偏置 ($b$):基础价格。
线性回归的本质,就是让计算机通过看成千上万套房子的成交记录,自己把这些权重 ($w$) 和偏置 ($b$) 算出来。
一旦算出了这些数字,机器就学会了“估价模型”。下次你给它一套新房子的数据,它就能套用公式算出价格。
4.2.2 机器是怎么学习的?(直观版梯度下降)
计算机一开始是不知道权重的,它可能随机猜这套房卖100块(显然猜错了)。 它计算了一下:真实价格 500万 - 预测价格 100块 = 误差很大。
为了减小误差,它需要调整权重。这就像一个蒙着眼睛的人下山:
-
计算损失(Loss):我现在站在多高的地方?(误差有多大?)
-
计算梯度(Gradient):哪个方向是下坡?(怎么调权重能让误差变小?)
-
步长(Learning Rate):往那个方向走一步。
机器重复这个过程几千次,直到走到山谷底端(误差最小化)。这就是大名鼎鼎的梯度下降。
4.3 Scikit-learn:AI工程师的军火库
在Python中,我们不需要自己手写梯度下降的数学公式。我们有 Scikit-learn (sklearn)。 它是传统机器学习领域的绝对霸主,具有高度统一的工程接口。
不管是用简单的线性回归,还是复杂的随机森林,在sklearn里永远只有三步:
-
初始化:
model = Model()(建立模型对象) -
训练:
model.fit(X_train, y_train)(喂数据,找规律) -
预测:
model.predict(X_new)(考考它)
记住这个 Fit-Predict 范式,它将贯穿本书的机器学习篇章。
4.4 实战案例:加州房价预测系统
我们将使用著名的 California Housing Dataset(加州房价数据集)。 注:早期的教科书常使用波士顿房价数据集,但由于该数据集中包含种族相关的伦理问题,Scikit-learn从1.2版本开始已强烈不推荐使用。作为新时代的工程师,我们选用更合规的加州数据集。
4.4.1 第一步:加载与探索数据
新建一个文件 housing_predict.py 或使用 Jupyter Notebook。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import fetch_california_housing
# 1. 加载数据集
# as_frame=True 可以直接返回 Pandas DataFrame 格式,方便查看
housing = fetch_california_housing(as_frame=True)
df = housing.frame
# 2. 查看数据长什么样
print("--- 数据前5行 ---")
print(df.head())
print("\n--- 数据描述 ---")
# MedInc: 收入中位数, HouseAge: 房龄, AveRooms: 平均房间数...
# MedHouseVal: 房价中位数(这是我们要预测的目标,单位是10万美元)
print(df.describe())
4.4.2 第二步:相关性分析(工程直觉)
在把数据丢给模型前,先用上一章学的热力图看看哪些因素最影响房价。
# 绘制相关性热力图
plt.figure(figsize=(10, 8))
sns.heatmap(df.corr(), annot=True, cmap='coolwarm', fmt=".2f")
plt.title("加州房价特征相关性热力图")
plt.show()
【工程视角】 观察热力图,你会发现
MedInc(收入中位数)与MedHouseVal(房价)的相关系数高达 0.69。这意味着:这片区域的人越有钱,房价就越高。这非常符合常识。如果相关系数很低,线性回归的效果通常不会好。
4.4.3 第三步:切分试卷——训练集与测试集
这是新手最容易忽略的一步。 永远不要用训练模型的数据去测试模型! 那样就像是考试前把答案透漏给了学生,它是拿满分了,但并没有学会解题。
我们需要把数据切成两份:
-
训练集 (Training Set):约占80%,给模型用来学习。
-
测试集 (Test Set):约占20%,模型完全没见过,用来模拟“未来”。
from sklearn.model_selection import train_test_split
# X 是特征矩阵 (去掉房价那一列)
X = df.drop(columns=['MedHouseVal'])
# y 是标签 (只留房价那一列)
y = df['MedHouseVal']
# 切分数据
# test_size=0.2 表示20%做测试
# random_state=42 是一个魔法数字,保证每次切分的结果都一样(可复现)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"训练集维度: {X_train.shape}")
print(f"测试集维度: {X_test.shape}")
【小贴士】关于 Random State 42 你会在全世界的AI教程里看到
random_state=42。它是《银河系漫游指南》中“宇宙终极问题的答案”。在工程上,固定这个随机种子是为了确保你的实验结果别人能复现。
4.4.4 第四步:建立并训练模型
激动人心的时刻到了,虽然代码只有三行。
from sklearn.linear_model import LinearRegression
# 1. 初始化模型
model = LinearRegression()
# 2. 训练模型 (只喂训练集!)
# 这一步,计算机正在疯狂计算最佳的权重(w)和偏置(b)
model.fit(X_train, y_train)
print("模型训练完毕!")
print(f"模型截距 (Bias): {model.intercept_}")
print(f"特征权重 (Weights): {model.coef_}")
4.4.5 第五步:预测与评估
现在模型已经出师了,让我们用测试集(它没见过的数据)来考考它。
from sklearn.metrics import mean_squared_error, r2_score
# 1. 让模型预测测试集
y_pred = model.predict(X_test)
# 2. 评估考卷
# MSE (均方误差): 越小越好
mse = mean_squared_error(y_test, y_pred)
# R2 Score (决定系数): 越接近1越好,0.6以上算及格,0.8以上优秀
r2 = r2_score(y_test, y_pred)
print(f"均方误差 (MSE): {mse:.2f}")
print(f"R2 分数: {r2:.4f}")
结果解读: 如果你的 R2 Score 大约是 0.57 到 0.60 左右,这在真实数据中算是一个“及格”的分数。毕竟房价受很多复杂因素影响(如学区、政策),仅靠这几个简单的变量很难完美预测。
4.4.6 第六步:可视化真实值 vs 预测值
光看数字不直观,我们把结果画出来。
plt.figure(figsize=(8, 6))
# 画散点图
plt.scatter(y_test, y_pred, alpha=0.5, color='blue')
# 画一条理想的对角线 (完美预测线)
# 如果预测值等于真实值,点应该都落在这条红线上
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)
plt.xlabel("真实房价")
plt.ylabel("模型预测房价")
plt.title("线性回归预测效果验证")
plt.show()
观察: 你会发现大部分点分布在红线附近,但在房价非常高(5.0以上)的区域,预测值明显偏低。这说明我们的模型在预测“豪宅”时失效了。这在数据科学中称为欠拟合(Underfitting)——线性模型太简单了,无法捕捉复杂的豪宅定价规律。
4.5 章节小结
恭喜你,你已经成功训练了人生中第一个机器学习模型!
本章我们抛弃了复杂的数学推导,从工程应用的角度掌握了:
-
监督学习 就是找 $f(x)$ 的过程。
-
梯度下降 就是蒙眼下山找最优解。
-
Scikit-learn 工作流:准备数据 -> 切分数据 ->
model.fit->model.predict-> 评估可视化。
线性回归虽然简单,但它是所有复杂模型的基石。当你理解了“权重”和“误差”,你就理解了AI的灵魂。
4.6 思考与扩展练习
-
模型保存: 训练好的模型如果关掉电脑就没了,岂不是太浪费?请查阅
joblib库的用法,尝试将训练好的model保存为.pkl文件,并在另一个脚本中加载它进行预测。 -
特征工程思考: 我们在热力图中看到“经度”和“纬度”与房价的相关性很低。这是否意味着地理位置不重要? 提示:当然重要!但简单的线性关系(越北越贵?)可能不存在。有些地方(如沿海)贵,内陆便宜,这是一种非线性关系。线性回归处理不了这种关系,怎么办?
-
代码挑战: 尝试只使用
MedInc(收入)这一个特征来训练模型。比较一下,用一个特征预测和用所有特征预测,R2分数差了多少?这能让你直观感受到“信息量”对预测准确度的影响。
更多推荐




所有评论(0)