章节导语

“在这个世界上,只有两类人试图预知未来:算命先生和机器学习工程师。前者的工具是水晶球,后者的工具是历史数据。”

欢迎来到监督学习(Supervised Learning)的世界。这是目前AI应用最广泛的领域,从推荐系统到自动驾驶,背后其实都遵循着同一个朴素的逻辑:从历史中寻找规律,用规律预测未来

本章我们将学习最基础、最经典,也是所有AI算法的“老祖宗”——线性回归(Linear Regression)。别被名字骗了,它并不深奥。简单来说,它就是教计算机画一条“最准”的直线,穿过那一堆乱糟糟的数据点。

这一章,我们将正式引入大名鼎鼎的 Scikit-learn 库,带你像搭积木一样构建你的第一个预测模型。


4.1 学习目标

在学完本章后,你将能够:

  1. 打破黑盒:理解什么是特征(Features)、标签(Labels)和权重(Weights)。

  2. 直观理解算法:用“下山法”理解梯度下降(Gradient Descent),无需死记硬背数学公式。

  3. 掌握标准范式:熟练使用 Scikit-learn 的“三板斧”——fit(训练)、predict(预测)、score(打分)。

  4. 工程思维:理解为什么一定要把数据切分为“训练集”和“测试集”。

  5. 实战落地:基于加州房价数据集,训练一个能根据房龄、收入预测房价的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块 = 误差很大

为了减小误差,它需要调整权重。这就像一个蒙着眼睛的人下山:

  1. 计算损失(Loss):我现在站在多高的地方?(误差有多大?)

  2. 计算梯度(Gradient):哪个方向是下坡?(怎么调权重能让误差变小?)

  3. 步长(Learning Rate):往那个方向走一步。

机器重复这个过程几千次,直到走到山谷底端(误差最小化)。这就是大名鼎鼎的梯度下降


4.3 Scikit-learn:AI工程师的军火库

在Python中,我们不需要自己手写梯度下降的数学公式。我们有 Scikit-learn (sklearn)。 它是传统机器学习领域的绝对霸主,具有高度统一的工程接口

不管是用简单的线性回归,还是复杂的随机森林,在sklearn里永远只有三步:

  1. 初始化model = Model() (建立模型对象)

  2. 训练model.fit(X_train, y_train) (喂数据,找规律)

  3. 预测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 章节小结

恭喜你,你已经成功训练了人生中第一个机器学习模型!

本章我们抛弃了复杂的数学推导,从工程应用的角度掌握了:

  1. 监督学习 就是找 $f(x)$ 的过程。

  2. 梯度下降 就是蒙眼下山找最优解。

  3. Scikit-learn 工作流:准备数据 -> 切分数据 -> model.fit -> model.predict -> 评估可视化。

线性回归虽然简单,但它是所有复杂模型的基石。当你理解了“权重”和“误差”,你就理解了AI的灵魂。

4.6 思考与扩展练习

  1. 模型保存: 训练好的模型如果关掉电脑就没了,岂不是太浪费?请查阅 joblib 库的用法,尝试将训练好的 model 保存为 .pkl 文件,并在另一个脚本中加载它进行预测。

  2. 特征工程思考: 我们在热力图中看到“经度”和“纬度”与房价的相关性很低。这是否意味着地理位置不重要? 提示:当然重要!但简单的线性关系(越北越贵?)可能不存在。有些地方(如沿海)贵,内陆便宜,这是一种非线性关系。线性回归处理不了这种关系,怎么办?

  3. 代码挑战: 尝试只使用 MedInc(收入)这一个特征来训练模型。比较一下,用一个特征预测和用所有特征预测,R2分数差了多少?这能让你直观感受到“信息量”对预测准确度的影响。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐