机器学习大师课 第 3 课:多特征回归与机器学习头号敌人 —— 过拟合

课程承诺:1 个核心概念(多特征线性回归)+1 个核心思想(过拟合与泛化)+1 段实战代码。学完你能解决真实世界的多变量预测问题,一眼识别并解决机器学习最常见的 "死穴"。

本节课目标:从单特征升级到多特征预测,彻底搞懂 "过拟合" 这个所有 AI 工程师每天都在战斗的问题,亲手用正则化把过拟合的模型拉回正轨。


🧩 先回答上一课的思考题

问题:如果损失函数不是一个完美的 "碗" 形,而是有多个山谷,梯度下降会发生什么?

答案 :它会掉进第一个遇到的局部山谷(局部最小值),而不一定能走到最深的那个全局山谷(全局最小值)。

不过不用太担心:

  • 在简单的线性回归中,损失函数永远是完美的碗形,只有一个全局最小值
  • 在复杂的深度学习中,科学家发现:绝大多数局部最小值的效果和全局最小值几乎一样好

🧠 第一个核心概念:多特征线性回归

前两课我们只用了一个特征(面积 / 学习时间)来预测结果,但真实世界的所有问题,都是多特征共同作用的结果

比如房价,不仅和面积有关,还和:

  • 房间数量
  • 所在楼层
  • 房龄
  • 学区
  • 地铁距离
  • ... 等等几十上百个因素有关

多特征线性回归的公式

单特征:y = w*x + b多特征:y = w1*x1 + w2*x2 + w3*x3 + ... + wn*xn + b

  • x1, x2, ..., xn:不同的特征(面积、房间数、楼层...)
  • w1, w2, ..., wn:每个特征对应的权重(表示这个特征对结果的影响大小)
  • b:截距

权重的意义

  • 权重为正:这个特征越大,结果越大(比如面积越大,房价越高)
  • 权重为负:这个特征越大,结果越小(比如房龄越大,房价越低)
  • 权重绝对值越大:这个特征对结果的影响越大

代码实战:多特征房价预测

我们用 4 个特征预测房价:面积、卧室数、卫生间数、房龄

python

运行

python 复制代码
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

# 1. 准备多特征数据(真实数据的简化版)
# 特征:[面积(平米), 卧室数, 卫生间数, 房龄(年)]
X = np.array([
    [50, 1, 1, 10], [60, 2, 1, 8], [70, 2, 1, 5], [80, 3, 2, 3], [90, 3, 2, 2],
    [100, 3, 2, 1], [110, 4, 2, 15], [120, 4, 3, 10], [130, 4, 3, 5], [140, 5, 3, 2]
])
# 标签:房价(万元)
y = np.array([100, 125, 150, 180, 210, 240, 220, 270, 310, 350])

# 2. 划分训练集和测试集(极其重要!)
# 80%的数据用来训练,20%的数据用来测试模型的真实能力
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 3. 创建并训练模型(和单特征代码完全一样!)
model = LinearRegression()
model.fit(X_train, y_train)

# 4. 查看每个特征的权重
print("各特征权重:")
print(f"面积:{model.coef_[0]:.2f} 万元/平米")
print(f"卧室数:{model.coef_[1]:.2f} 万元/个")
print(f"卫生间数:{model.coef_[2]:.2f} 万元/个")
print(f"房龄:{model.coef_[3]:.2f} 万元/年")
print(f"截距:{model.intercept_:.2f} 万元")

# 5. 评估模型
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)

print(f"\n训练集误差(MSE):{mean_squared_error(y_train, y_train_pred):.2f}")
print(f"测试集误差(MSE):{mean_squared_error(y_test, y_test_pred):.2f}")

# 6. 预测一套新房子的价格
new_house = np.array([[105, 3, 2, 7]])
predicted_price = model.predict(new_house)
print(f"\n预测105平米、3卧2卫、7年房龄的房子价格:{predicted_price[0]:.2f}万元")

运行结果解读

你会看到类似这样的输出:

plaintext

python 复制代码
各特征权重:
面积:2.15 万元/平米
卧室数:5.32 万元/个
卫生间数:12.78 万元/个
房龄:-3.21 万元/年
截距:-15.67 万元

训练集误差(MSE):12.34
测试集误差(MSE):18.56
  • 卫生间数的权重最大,说明在这个数据集中,卫生间数量对房价的影响最大
  • 房龄的权重为负,符合我们的常识:房子越老越便宜
  • 测试集误差比训练集误差大一点,这是正常的

💡 第一个核心思想:过拟合与泛化能力

这是机器学习最重要、最核心的思想,没有之一。所有 AI 工程师 90% 的工作,都是在和这个问题战斗。

最通俗的类比:学生考试

我们训练模型的过程,就像学生备考:

  • 训练集 = 课本上的例题
  • 测试集 = 期末考试题(学生从来没见过的题)
  • 模型训练 = 学生做例题学习
  • 模型预测 = 学生做考试题

现在有三个学生:

  1. 学渣(欠拟合):上课不听,例题也不会做,考试当然考不好

    • 表现:训练集误差大,测试集误差也大
    • 原因:模型太简单,连数据的基本规律都没学到
  2. 学霸(拟合良好):理解了知识点,例题会做,考试也能考高分

    • 表现:训练集误差小,测试集误差也小
    • 这是我们想要的理想模型
  3. 书呆子(过拟合):死记硬背了所有例题,例题能考满分,但考试遇到新题就不会

    • 表现:训练集误差极小,甚至为 0,但测试集误差极大
    • 原因:模型太复杂,学到了很多数据中的随机噪声,而不是真正的规律

什么是泛化能力?

模型在从未见过的新数据 上的表现能力,就叫泛化能力

  • 我们训练模型的最终目标,不是让它在训练集上表现好,而是让它在新数据上表现好
  • 过拟合的模型,泛化能力极差,完全没有实用价值

为什么会发生过拟合?

  • 数据太少
  • 特征太多
  • 模型太复杂

💻 代码实战:亲眼看到过拟合

我们用一个简单的多项式回归例子,让你亲眼看到过拟合是怎么发生的。

完整代码

python

运行

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error

# 1. 生成带噪声的模拟数据
np.random.seed(42)
X = np.linspace(0, 10, 10).reshape(-1, 1)
y = 2*X + 3 + np.random.normal(0, 1, 10).reshape(-1, 1)  # 真实规律是y=2x+3,加了一点噪声

# 2. 定义一个函数,用来训练不同次数的多项式模型
def train_polynomial_model(degree):
    # 把原始特征转换成多项式特征
    poly = PolynomialFeatures(degree=degree)
    X_poly = poly.fit_transform(X)
    
    # 训练模型
    model = LinearRegression()
    model.fit(X_poly, y)
    
    # 预测
    X_plot = np.linspace(0, 10, 100).reshape(-1, 1)
    X_plot_poly = poly.transform(X_plot)
    y_plot = model.predict(X_plot_poly)
    
    # 计算误差
    y_pred = model.predict(X_poly)
    mse = mean_squared_error(y, y_pred)
    
    return X_plot, y_plot, mse

# 3. 训练不同次数的模型,对比效果
degrees = [1, 3, 9]
plt.figure(figsize=(15, 5))

for i, degree in enumerate(degrees):
    X_plot, y_plot, mse = train_polynomial_model(degree)
    
    plt.subplot(1, 3, i+1)
    plt.scatter(X, y, color='red', label='真实数据')
    plt.plot(X_plot, y_plot, color='blue', label=f'拟合曲线(次数={degree})')
    plt.title(f'多项式次数={degree},训练集误差={mse:.2f}')
    plt.xlabel('X')
    plt.ylabel('y')
    plt.legend()
    plt.ylim(0, 25)

plt.tight_layout()
plt.show()

运行结果分析

你会看到三张图:

  1. 次数 = 1(线性回归) :拟合曲线是一条直线,训练集误差≈0.8
    • 这是欠拟合,因为真实数据有一点弯曲,直线无法捕捉
  2. 次数 = 3 :拟合曲线很平滑,很好地捕捉了数据的真实规律,训练集误差≈0.5
    • 这是拟合良好,泛化能力最好
  3. 次数 = 9 :拟合曲线弯弯曲曲,完美地经过了每一个数据点,训练集误差≈0
    • 这就是严重过拟合!它记住了所有的噪声点,但如果给它一个新的 x 值,预测结果会非常离谱

🛠️ 解决过拟合的神器:正则化

解决过拟合有很多方法,最常用、最有效的就是正则化

正则化的核心思想

让模型变得更简单

我们在损失函数中加入一个 "惩罚项",惩罚那些绝对值太大的参数。参数越小,模型越简单,越不容易过拟合。

最常用的正则化是L2 正则化 ,对应的模型叫岭回归(Ridge)

代码实战:用岭回归解决过拟合

python

运行

python 复制代码
from sklearn.linear_model import Ridge

# 1. 还是用刚才的9次多项式特征
poly = PolynomialFeatures(degree=9)
X_poly = poly.fit_transform(X)

# 2. 对比普通线性回归和岭回归
model_linear = LinearRegression()
model_linear.fit(X_poly, y)

# alpha是正则化强度,alpha越大,惩罚越重,模型越简单
model_ridge = Ridge(alpha=1.0)
model_ridge.fit(X_poly, y)

# 3. 预测并画图
X_plot = np.linspace(0, 10, 100).reshape(-1, 1)
X_plot_poly = poly.transform(X_plot)

y_linear = model_linear.predict(X_plot_poly)
y_ridge = model_ridge.predict(X_plot_poly)

plt.figure(figsize=(10, 6))
plt.scatter(X, y, color='red', label='真实数据')
plt.plot(X_plot, y_linear, color='blue', linestyle='--', label='普通线性回归(过拟合)')
plt.plot(X_plot, y_ridge, color='green', linewidth=2, label='岭回归(正则化后)')
plt.title('正则化解决过拟合')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.ylim(0, 25)
plt.show()

# 4. 对比参数大小
print(f"普通线性回归参数最大值:{np.max(np.abs(model_linear.coef_)):.2f}")
print(f"岭回归参数最大值:{np.max(np.abs(model_ridge.coef_)):.2f}")

神奇的实验

修改alpha的值,观察效果:

  • alpha=0:和普通线性回归一样,严重过拟合
  • alpha=1:曲线变得平滑很多,过拟合大大缓解
  • alpha=100:曲线几乎变成了直线,变成了欠拟合

结论 :正则化强度alpha是一个需要调优的超参数,找到合适的 alpha 值,就能得到泛化能力最好的模型。


📝 本节课总结

  1. 核心概念:多特征线性回归,每个特征有对应的权重,表示其对结果的影响大小
  2. 核心思想:过拟合是机器学习的头号敌人,我们的目标是获得泛化能力好的模型
  3. 核心方法
    • 划分训练集和测试集,评估模型的真实泛化能力
    • 用正则化(岭回归)惩罚大参数,让模型变简单,解决过拟合
  4. 你已经做到了:能解决多特征预测问题,能识别并解决过拟合问题

🎯 课后作业(必须做)

  1. 运行上面的所有代码,观察不同多项式次数和不同 alpha 值的效果
  2. 用你自己写的梯度下降代码,实现多特征线性回归
  3. 思考:除了正则化,还有哪些方法可以解决过拟合?(提示:前两课提到过)
  4. 尝试用 scikit-learn 的Lasso回归(L1 正则化)解决过拟合,看看和岭回归有什么不同
相关推荐
qq_411262425 小时前
基于四博 ESP32-S3 + VB6824 打造 A1 AI 智能拍学机:视觉识别、语音交互与 AI 学习应用落地方案
人工智能·智能音箱
中海德--陈顺真5 小时前
HONEYWELL 扫描架控制板 51000398
运维·服务器·人工智能
数智前线5 小时前
零售连锁门店的柔性管理之困,海康云眸Claw如何破解?
人工智能
AI技术增长5 小时前
Pytorch图像去噪实战(十四):条件扩散模型图像去噪,让Diffusion根据带噪图恢复干净图
人工智能·pytorch·python
tangweiguo030519875 小时前
LangGraph 入门:多智能体工作流实战(阿里云百炼)
人工智能·python·langchain
饭后一颗花生米5 小时前
AI算力选型全景指南:从入门到旗舰的硬核实操
人工智能
Yue栎廷5 小时前
邪修:Markdown加粗语法**本土化改造
前端·javascript·人工智能
2301_815279525 小时前
实战分享LangChain WebUI 部署智能客服:从零搭建到生产环境优化
人工智能·langchain
三维频道5 小时前
柔性材料3D数字化:蓝光扫描在内衣胸垫设计与质检中的应用
人工智能·3d·逆向工程·蓝光3d扫描仪·服装数字化·内衣设计·柔性材料检测
科研前沿5 小时前
镜像视界浙江科技有限公司的核心引擎关键技术有哪些?
人工智能·数码相机·计算机视觉