三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

别再只调sklearn了!深入拆解线性回归:从损失函数MSE到评估指标R²的数学原理与Python实现

别再只调sklearn了!深入拆解线性回归:从损失函数MSE到评估指标R²的数学原理与Python实现

线性回归的数学本质:从最小二乘法到评估指标的全链路解析

线性回归作为机器学习领域的"第一课",常被简化为几行sklearn代码的调用。但当你真正理解其背后的数学原理时,会发现这个看似简单的算法蕴含着深刻的统计思想和几何意义。本文将从最小二乘法的几何解释出发,推导正规方程解的数学原理,并手动实现核心算法,最后通过波士顿房价数据集验证我们的实现与sklearn结果的一致性。

1. 最小二乘法的多维视角

当我们使用sklearn.linear_model.LinearRegression时,算法默认优化的目标函数就是均方误差(MSE)。但为什么选择MSE而不是绝对误差或其他损失函数?这需要从几何和概率两个角度来理解。

1.1 几何视角:投影与残差最小化

在n维特征空间中,线性回归实际上是在寻找一个超平面,使得所有样本点到该超平面的垂直距离(即残差)的平方和最小。这等价于将响应变量y投影到由特征矩阵X列向量张成的子空间上。

数学表达为:

minimize ||y - Xθ||²

其中:

  • ||·||表示L2范数(欧几里得距离)
  • θ为待求参数向量
  • X为设计矩阵(含截距项)

1.2 概率视角:最大似然估计

假设误差项ε服从正态分布N(0,σ²),则y的条件分布为:

y|X ~ N(Xθ, σ²I)

此时,最小化MSE等价于最大化似然函数

L(θ) = ∏ (1/√(2πσ²)) exp(-(y_i - x_iθ)²/(2σ²))

取对数后,最大化对数似然就等同于最小化MSE。

2. 正规方程解的数学推导

2.1 矩阵求导法

要最小化MSE,我们对θ求导并令导数为零:

  1. 展开MSE表达式:

    J(θ) = (y - Xθ)ᵀ(y - Xθ) = yᵀy - 2θᵀXᵀy + θᵀXᵀXθ
  2. 对θ求导:

    ∇J(θ) = -2Xᵀy + 2XᵀXθ
  3. 令导数为零,得到正规方程:

    XᵀXθ = Xᵀy
  4. 解得:

    θ = (XᵀX)⁻¹Xᵀy

2.2 Python实现正规方程

import numpy as np def linear_regression(X, y): # 添加截距项 X = np.concatenate([np.ones((X.shape[0], 1)), X], axis=1) # 计算正规方程解 theta = np.linalg.inv(X.T @ X) @ X.T @ y return theta # 示例使用 X = np.array([[1], [2], [3]]) # 特征 y = np.array([2, 3, 4]) # 目标值 theta = linear_regression(X, y) print(f"模型参数: {theta}")

注意:当XᵀX不可逆时(特征共线或样本不足),需要引入正则化或使用伪逆(np.linalg.pinv)

3. 评估指标R²的深入理解

3.1 定义与数学表达

R²(决定系数)的计算公式为:

R² = 1 - SS_res / SS_tot

其中:

  • SS_res = Σ(y_i - ŷ_i)² (残差平方和)
  • SS_tot = Σ(y_i - ȳ)² (总平方和)

3.2 为什么R²能衡量拟合优度?

从方差分解的角度看:

总方差 = 解释方差 + 未解释方差

R²实际反映的是模型解释的方差占总方差的比例。当R²=1时,模型完美拟合;R²=0时,模型不优于均值预测。

3.3 Python实现R²计算

def r2_score(y_true, y_pred): ss_res = np.sum((y_true - y_pred)**2) ss_tot = np.sum((y_true - np.mean(y_true))**2) return 1 - (ss_res / ss_tot) # 示例 y_true = np.array([3, -0.5, 2, 7]) y_pred = np.array([2.5, 0.0, 2, 8]) print(f"R²分数: {r2_score(y_true, y_pred):.4f}")

4. 波士顿房价预测实战

4.1 数据准备与预处理

from sklearn.datasets import load_boston from sklearn.preprocessing import StandardScaler boston = load_boston() X, y = boston.data, boston.target # 特征标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 添加截距项 X_final = np.concatenate([np.ones((X.shape[0], 1)), X_scaled], axis=1)

4.2 手动实现与sklearn对比

手动实现结果

theta_manual = np.linalg.inv(X_final.T @ X_final) @ X_final.T @ y y_pred_manual = X_final @ theta_manual mse_manual = np.mean((y - y_pred_manual)**2) r2_manual = r2_score(y, y_pred_manual)

sklearn实现

from sklearn.linear_model import LinearRegression model = LinearRegression() model.fit(X_scaled, y) y_pred_sk = model.predict(X_scaled) mse_sk = np.mean((y - y_pred_sk)**2) r2_sk = model.score(X_scaled, y)

结果对比表

指标手动实现sklearn差异
MSE21.894821.89480
0.74060.74060
参数数量14140

4.3 结果分析

从对比可见,我们的手动实现与sklearn结果完全一致,验证了数学推导的正确性。在实际项目中,理解这些底层原理能帮助我们:

  1. 更好地解释模型结果
  2. 诊断模型问题(如共线性)
  3. 进行定制化修改(如加权最小二乘)

5. 进阶讨论:线性回归的局限与扩展

虽然线性回归简单直观,但在实际应用中需要注意:

  1. 非线性关系:当特征与目标存在非线性关系时,可考虑:

    • 多项式特征扩展
    • 样条回归
    • 核方法
  2. 异常值敏感:MSE对异常值敏感,替代方案包括:

    • Huber损失
    • 分位数回归
  3. 高维数据:当特征维度高于样本量时,需要:

    • 正则化(岭回归、Lasso)
    • 降维处理
# 岭回归示例 alpha = 1.0 # 正则化强度 theta_ridge = np.linalg.inv(X_final.T @ X_final + alpha*np.eye(X_final.shape[1])) @ X_final.T @ y

理解线性回归的数学本质,是掌握更复杂模型的基础。当你下次调用model.fit()时,希望你能看到代码背后那些优美的数学原理。

← 返回列表