news 2026/4/17 18:52:16

别再只会调包了!手把手教你用NumPy从零推导线性回归的OLS公式(附Python代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再只会调包了!手把手教你用NumPy从零推导线性回归的OLS公式(附Python代码)

从零构建线性回归:用NumPy揭秘最小二乘法的数学本质

在数据科学领域,线性回归就像乐高积木中的基础模块——看似简单却能构建复杂模型。许多初学者能够熟练调用sklearnLinearRegression完成预测,但当被问到"为什么参数要这样计算"时却陷入沉默。这种现象被业界称为"调包侠综合征":只会使用工具却不理解背后的数学逻辑。本文将带你用NumPy从零推导普通最小二乘法(OLS),就像拆开黑箱,亲眼看看机器学习的齿轮如何转动。

1. 线性回归的统计基础

线性回归的核心思想是用直线描述自变量X和因变量Y之间的关系。当我们说"拟合一条直线"时,实际上是在寻找参数β₀(截距)和β₁(斜率)的最佳估计值。这里的"最佳"在统计学中有明确定义——使预测值与真实值之间的差距最小。

考虑一个简单的消费支出案例:假设每月消费(Spending)与可支配收入(Income)存在线性关系:

Spending = β₀ + β₁ × Income + ε

其中ε代表无法用收入解释的随机误差。我们的目标是找到β₀和β₁,使得所有数据点到预测直线的垂直距离(残差)最小。这就是最小二乘法的直观解释。

关键概念:残差平方和(RSS)是衡量模型拟合优度的核心指标,计算公式为Σ(yᵢ - ŷᵢ)²,其中ŷᵢ表示第i个预测值

2. OLS的数学推导过程

2.1 构建优化问题

最小二乘法的数学本质是一个优化问题:找到参数使残差平方和最小。用矩阵表示,对于n个观测值和p个特征:

RSS(β) = (Y - Xβ)ᵀ(Y - Xβ)

其中:

  • Y是n×1的响应向量
  • X是n×(p+1)的设计矩阵(含截距项)
  • β是(p+1)×1的参数向量

展开这个二次型,我们得到:

RSS(β) = YᵀY - 2βᵀXᵀY + βᵀXᵀXβ

2.2 求解极值点

为了找到最小值,我们对β求导并令导数等于零:

∂RSS/∂β = -2XᵀY + 2XᵀXβ = 0

整理得到正规方程(Normal Equation):

XᵀXβ = XᵀY

当XᵀX可逆时,参数的最优解为:

β̂ = (XᵀX)⁻¹XᵀY

这就是OLS估计量的矩阵形式,揭示了参数估计如何通过数据矩阵运算得到。

3. NumPy实现核心算法

现在我们将数学公式转化为NumPy代码,不使用任何现成的机器学习库。以下是关键步骤的实现:

import numpy as np def ols_fit(X, y): """手动实现OLS参数估计""" # 添加截距列 X = np.column_stack([np.ones(X.shape[0]), X]) # 计算XᵀX的逆 XtX = np.dot(X.T, X) XtX_inv = np.linalg.inv(XtX) # 计算Xᵀy Xty = np.dot(X.T, y) # 求解参数 beta = np.dot(XtX_inv, Xty) return beta # 示例数据:收入与消费 income = np.array([800,1100,1400,1700,2000,2300,2600,2900,3200,3500]) spending = np.array([638,935,1155,1254,1408,1650,1925,2068,2266,2530]) # 拟合模型 beta = ols_fit(income, spending) print(f"截距β₀: {beta[0]:.2f}, 斜率β₁: {beta[1]:.2f}")

执行结果应显示:

截距β₀: 142.00, 斜率β₁: 0.67

这个简单的实现揭示了机器学习库背后的核心计算过程。值得注意的是,实际应用中我们会使用更稳定的数值计算方法(如QR分解),但上述代码最直接地反映了数学原理。

4. 算法验证与效果评估

4.1 与统计包结果对比

为了验证我们的实现是否正确,可以使用statsmodels进行交叉验证:

import statsmodels.api as sm X_with_intercept = sm.add_constant(income) model = sm.OLS(spending, X_with_intercept).fit() print(model.params)

两种方法得到的参数估计应该完全一致,这说明我们的手动实现是正确的。

4.2 模型诊断指标

除了参数估计,完整的回归分析还需要评估模型质量。以下是几个核心指标的计算方法:

指标名称计算公式解释
1 - RSS/TSS解释的方差比例
调整R²1 - (RSS/(n-p-1))/(TSS/(n-1))考虑参数数量的修正R²
MSERSS/n均方误差
参数标准误√(σ²(XᵀX)⁻¹对角元素)估计的精确度

其中:

  • RSS = Σ(yᵢ - ŷᵢ)² (残差平方和)
  • TSS = Σ(yᵢ - ȳ)² (总平方和)
  • σ² = RSS/(n-p-1) (误差方差估计)

在NumPy中实现这些指标:

def model_metrics(X, y, beta): X_design = np.column_stack([np.ones(X.shape[0]), X]) y_pred = np.dot(X_design, beta) residuals = y - y_pred n = len(y) p = X.shape[1] RSS = np.sum(residuals**2) TSS = np.sum((y - np.mean(y))**2) r_squared = 1 - RSS/TSS adj_r_squared = 1 - (RSS/(n-p-1))/(TSS/(n-1)) mse = RSS/n sigma_squared = RSS/(n-p-1) var_beta = sigma_squared * np.linalg.inv(np.dot(X_design.T, X_design)) std_err = np.sqrt(np.diag(var_beta)) return { 'R²': r_squared, '调整R²': adj_r_squared, 'MSE': mse, '参数标准误': std_err }

5. 工程实践中的注意事项

在实际项目中,直接使用正规方程可能会遇到数值不稳定的问题。以下是几个常见挑战及解决方案:

  1. 多重共线性问题

    • 当特征高度相关时,XᵀX接近奇异矩阵
    • 解决方法:使用正则化(Ridge回归)或主成分分析(PCA)
  2. 大数据场景

    • 当n很大时,计算(XᵀX)⁻¹需要O(p³)时间
    • 解决方法:使用随机梯度下降(SGD)等迭代算法
  3. 数值稳定性

    • 直接求逆可能引入数值误差
    • 更好的替代方案:
      # 使用QR分解替代直接求逆 Q, R = np.linalg.qr(X) beta = np.linalg.solve(R, np.dot(Q.T, y))
  4. 缺失值处理

    • 原始OLS假设数据完整
    • 实际应用中需要先进行缺失值填充或删除

专业提示:在实现生产级线性回归时,考虑使用Cholesky分解代替直接矩阵求逆,能显著提高数值稳定性并减少计算时间。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 18:51:22

el-upload 多文件上传优化:如何利用 FormData 实现批量请求

1. 为什么需要优化 el-upload 的多文件上传? 在实际开发中,我们经常遇到需要批量上传文件的场景。比如用户需要一次性上传10张产品图片,或者批量导入100个Excel数据文件。如果采用默认的 el-upload 配置,每个文件都会单独发送一个…

作者头像 李华
网站建设 2026/4/17 18:50:21

彻底告别音频线!Scream虚拟声卡:Windows网络音频共享终极指南

彻底告别音频线!Scream虚拟声卡:Windows网络音频共享终极指南 【免费下载链接】scream Virtual network sound card for Microsoft Windows 项目地址: https://gitcode.com/gh_mirrors/sc/scream 还在为电脑音频无法无线传输到其他设备而烦恼吗&a…

作者头像 李华
网站建设 2026/4/17 18:45:59

告别复制粘贴!Chrome二维码插件让网页分享效率提升300%

告别复制粘贴!Chrome二维码插件让网页分享效率提升300% 【免费下载链接】chrome-qrcode chrome-qrcode - 一个 Chrome 浏览器插件,可以生成当前 URL 或选中文本的二维码,或解码网页上的二维码。 项目地址: https://gitcode.com/gh_mirrors/…

作者头像 李华
网站建设 2026/4/17 18:45:16

实战解析:如何利用jstat与GC日志精准定位频繁FullGC的根源

1. 从现象到本质:FullGC频繁触发的典型表现 最近在排查线上Java应用性能问题时,发现一个有趣的现象:应用发布新版本后,FullGC次数突然从日均个位数飙升到每小时20次。虽然暂时没有引发严重故障,但作为有经验的开发者都…

作者头像 李华