You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何numpy最小二乘求解结果正确,scipy却得出异常结果?

为啥numpy和scipy最小二乘结果差这么大?

嘿,这个问题我太熟了!我来帮你拆解一下为啥会出现这种离谱的差异~

核心原因:两者的求解逻辑根本不一样

这两个函数看起来都是“最小二乘”,但本质完全不同:

  • numpy.linalg.lstsq:是专门为线性最小二乘设计的工具,它直接通过矩阵分解(比如QR分解)来求解,属于解析解法,结果稳定、唯一,完全适合你这种线性回归场景(y = X @ p)。
  • scipy.optimize.leastsq:是一个通用的非线性最小二乘优化器,它靠迭代搜索来找到残差平方和最小的参数。它不仅能处理线性问题,更擅长非线性,但代价是需要你提供初始参数猜测,而且对初始值非常敏感——如果初始值给得太离谱,很容易发散到奇怪的结果,甚至每次迭代的数值误差都会导致结果不一样。

你大概率踩了这几个坑

结合你的描述,问题几乎肯定出在scipy的使用方式上:

  1. 初始参数x0给得太离谱
    如果你没指定初始值,或者给了比如[0,0]、随机值,甚至极端大的数,对于线性问题来说,迭代过程可能直接发散,得到你看到的那种超大数值结果。
  2. 残差函数构造错误
    比如你把残差写成了X @ p - y(虽然平方和一样,但优化方向可能有影响),或者函数逻辑写错了,导致优化器找错方向。
  3. 没调整优化参数
    比如迭代次数不够(maxfev参数),或者公差设置太松,导致优化器还没收敛就停止了。

正确使用scipy leastsq的示例

给你写个对比代码,照着改就能得到和numpy一致的结果:

import numpy as np
from scipy.optimize import leastsq

# 先构造模拟数据(和你的场景一致)
X = np.random.rand(100, 2) * 10
true_params = np.array([9.94, 5.06])
y = X @ true_params + np.random.randn(100) * 0.5

# numpy的解法(稳定可靠)
p_np, _, _, _ = np.linalg.lstsq(X, y, rcond=None)
print("numpy求解结果:", p_np)

# scipy的正确解法
def residual(params, X, y):
    # 残差必须是 y - 预测值,也就是真实值减模型输出
    return y - X @ params

# 给一个合理的初始猜测!比如接近真实值的数,或者全1都可以
initial_guess = np.array([1, 1])
p_scipy, _ = leastsq(residual, initial_guess, args=(X, y))
print("scipy正确求解结果:", p_scipy)

总结建议

  • 如果是线性回归问题,优先用numpy的lstsq或者sklearn的LinearRegression,它们是专门为这类问题设计的,速度快、结果稳定,sklearn的LinearRegression底层其实也是用类似的线性代数方法,所以和numpy结果一致是正常的。
  • 非要用scipy leastsq的话,一定要给合理的初始参数,并且确保残差函数正确。

内容的提问来源于stack exchange,提问作者deepak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:49:10