当前位置: 首页 > news >正文

别再死记硬背公式了!用Python和NumPy手撕多元线性回归的最小二乘法

用Python和NumPy手撕多元线性回归:最小二乘法的代码实践

在机器学习的入门阶段,线性回归往往是第一个接触的算法。但很多初学者会被矩阵运算和求导公式吓退,转而直接调用现成的库函数。本文将带你用Python和NumPy从零实现多元线性回归,通过代码理解最小二乘法的数学本质。

1. 最小二乘法原理回顾

最小二乘法的核心思想很简单:找到一组参数,使得预测值与真实值之间的平方误差最小。对于多元线性回归模型:

$$ \hat{y} = X\theta $$

其中$X$是特征矩阵,$\theta$是参数向量。我们的目标是找到$\theta$使得:

$$ \min_\theta |X\theta - y|^2 $$

通过矩阵求导可以得到闭式解:

$$ \theta = (X^TX)^{-1}X^Ty $$

这个公式看起来简单,但实际实现时会遇到各种数值计算问题。下面我们就用代码一步步实现它。

2. 数据准备与预处理

首先导入必要的库并生成一些模拟数据:

import numpy as np import matplotlib.pyplot as plt # 生成模拟数据 np.random.seed(42) X = 2 * np.random.rand(100, 1) # 100个样本,1个特征 y = 4 + 3 * X + np.random.randn(100, 1) # 真实关系为y=4+3x+噪声 # 添加偏置项 X_b = np.c_[np.ones((100, 1)), X] # 每个样本添加x0=1

注意:在多元线性回归中,我们通常会在特征矩阵中添加一列全1的向量,这对应于截距项$\theta_0$。

3. 最小二乘法的NumPy实现

现在我们来实现最小二乘法的核心计算:

def least_squares(X, y): """最小二乘法实现""" theta = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(y) return theta # 计算参数 theta_best = least_squares(X_b, y) print("最优参数:", theta_best)

这段代码直接实现了正规方程,但实际应用中可能会遇到以下问题:

  1. 矩阵$X^TX$不可逆(奇异矩阵)
  2. 当特征数量很大时,矩阵求逆计算量很大

4. 数值稳定性优化

为了提高数值稳定性,我们可以使用伪逆(Moore-Penrose逆)代替直接求逆:

def stable_least_squares(X, y): """数值稳定的最小二乘法实现""" theta = np.linalg.pinv(X).dot(y) return theta theta_stable = stable_least_squares(X_b, y) print("稳定解参数:", theta_stable)

伪逆的计算使用了奇异值分解(SVD),即使$X^TX$不可逆也能得到合理的解。

5. 结果可视化与评估

让我们看看模型的拟合效果:

# 预测 X_new = np.array([[0], [2]]) X_new_b = np.c_[np.ones((2, 1)), X_new] y_predict = X_new_b.dot(theta_best) # 绘制结果 plt.plot(X_new, y_predict, "r-", linewidth=2, label="预测") plt.plot(X, y, "b.") plt.xlabel("X", fontsize=18) plt.ylabel("y", rotation=0, fontsize=18) plt.legend(loc="upper left", fontsize=14) plt.axis([0, 2, 0, 15]) plt.show()

评估模型性能可以使用均方误差(MSE):

def mse(y_true, y_pred): """计算均方误差""" return np.mean((y_true - y_pred)**2) y_pred = X_b.dot(theta_best) print("训练集MSE:", mse(y, y_pred))

6. 扩展到多元情况

上面的例子是一元线性回归,现在我们扩展到多元情况。假设我们有两个特征:

# 生成多元数据 X_multi = 2 * np.random.rand(100, 2) # 两个特征 y_multi = 4 + X_multi[:, [0]] + 3 * X_multi[:, [1]] + np.random.randn(100, 1) # 添加偏置项 X_multi_b = np.c_[np.ones((100, 1)), X_multi] # 计算参数 theta_multi = stable_least_squares(X_multi_b, y_multi) print("多元回归参数:", theta_multi)

对于更高维的数据,最小二乘法依然适用,只是计算量会增大。

7. 与scikit-learn实现对比

为了验证我们的实现是否正确,可以与scikit-learn的线性回归对比:

from sklearn.linear_model import LinearRegression lin_reg = LinearRegression() lin_reg.fit(X, y) print("sklearn截距:", lin_reg.intercept_) print("sklearn系数:", lin_reg.coef_)

你会发现两者的结果几乎相同,这说明我们的实现是正确的。

8. 实际应用中的注意事项

在实际项目中应用最小二乘法时,需要注意以下几点:

  1. 特征缩放:当特征量纲差异大时,应先进行标准化
  2. 多重共线性:当特征高度相关时,$X^TX$接近奇异矩阵
  3. 异常值处理:最小二乘法对异常值敏感
  4. 计算效率:当特征数>10000时,考虑使用梯度下降

下面是一个特征缩放的例子:

from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(X) X_scaled_b = np.c_[np.ones((100, 1)), X_scaled] theta_scaled = stable_least_squares(X_scaled_b, y) print("缩放后参数:", theta_scaled)

9. 性能优化技巧

对于大规模数据,我们可以使用一些优化技巧:

  1. Cholesky分解:比直接求逆更高效稳定
  2. 增量计算:适用于流式数据
  3. 并行计算:利用多核CPU加速矩阵运算

Cholesky分解的实现:

def cholesky_least_squares(X, y): """使用Cholesky分解的最小二乘法""" XtX = X.T.dot(X) L = np.linalg.cholesky(XtX) # Cholesky分解 z = np.linalg.solve(L, X.T.dot(y)) # 解Lz=X^Ty theta = np.linalg.solve(L.T, z) # 解L^Tθ=z return theta theta_cholesky = cholesky_least_squares(X_b, y) print("Cholesky解:", theta_cholesky)

10. 从线性回归到更复杂的模型

理解最小二乘法是学习更复杂模型的基础。许多高级技术如:

  • 岭回归(L2正则化)
  • Lasso回归(L1正则化)
  • 弹性网络
  • 多项式回归

都是在最小二乘法的基础上发展而来的。掌握了核心原理后,这些扩展就更容易理解了。

http://www.cnnetsun.cn/news/2576269.html

相关文章:

  • [Dify实战] 工作流里的变量为什么越传越乱?先把输入输出契约、默认值和异常分支写清楚
  • YOLOv8推理速度翻倍秘籍:除了换GPU,你的PyTorch版本装对了吗?
  • PTELL稀疏矩阵格式与可逆逻辑硬件加速架构解析
  • 基于Whisper、Ollama与Gradio构建本地语音AI助理全流程指南
  • Unity多语言工具链:从RTL适配到字体图集热替换的工程实践
  • yuzu模拟器终极指南:在PC上免费畅玩Switch游戏的完整教程
  • Agent 一接推理模型就开始行动延迟飙升:从 Think-Act 解耦到 Reasoning Budget 的工程实战
  • VCAM虚拟相机完整指南:安卓摄像头替换终极教程
  • 联想老本IdeaPad 310S升级记:8G内存+512G固态+Win10/Ubuntu双系统保姆级教程
  • Azure Terraform实战:从踩坑到生产级IaC落地指南
  • 碧蓝航线自动化脚本:5步打造你的专属游戏管家,解放双手轻松升级
  • ComfyUI Reactor Node:重新定义AI换脸的技术边界
  • 自制设备内置电池测试台:PIC单片机实现充放电监测与容量分析
  • 基于边缘AI与低功耗设计的野外生态监测系统构建实战
  • Burp Suite Dashboard深度解析:从数据源到风险决策中枢
  • 不止能收信!手把手教你用hMailServer配置SMTP中继,彻底解决个人邮局发信难题
  • 怎么监控线程池Java
  • 3大核心功能彻底掌握OmenSuperHub:惠普游戏本性能控制完全指南
  • 在Qt Widgets和Qt Quick应用中,如何优雅地嵌入并控制Web页面?一个完整Demo带你搞定
  • 番茄小说下载器:解锁离线阅读新体验,随时随地畅享精彩故事
  • Lovable看板权限失控危机预警(2024Q2最新审计报告):3类越权访问漏洞已致平均数据泄露时长↑217%
  • UE5 Niagara模型位置渲染全链路解析
  • drawio-desktop:打破平台壁垒,让专业图表制作触手可及
  • 告别LPC!从引脚危机到性能瓶颈,一文看懂Intel eSPI总线为何是PC架构的救星
  • App加固与Frida检测原理及合规实践指南
  • uiautomator2与Appium选型实战指南:Android自动化测试工具决策树
  • AI代码审计与开源治理:构建自动化安全开发新范式
  • 终极惠普OMEN笔记本性能控制指南:OmenSuperHub完全掌握手册
  • 鸿蒙开发-空间建模的C语言接口有哪些?spatial_recon_interface详解
  • 手把手教你部署 Browser-Use Web UI:拥有你的专属浏览器自动化助手