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

Scipy ODR传入数组型误差时报错:解处矩阵非满秩

scipy.odr传入数组型误差触发“非满秩”错误的解决办法

问题场景

在使用scipy.odr对线性模型执行正交距离回归(ODR)时,若给RealData传入数组型的x、y误差(即每个数据点对应独立的误差值),会触发Problem is not full rank at solution错误。但传入标量误差时程序可正常运行,而业务需求必须使用数组型的逐点误差。

即使使用简单合成数据复现,或参考其他ODR解决方案实现,都会触发该错误。环境版本:Numpy 1.26.4,Scipy 1.13.0。最小复现代码如下:

import numpy as np
import scipy.odr as odr
import matplotlib.pyplot as plt

def odrlin(b, x):
    return b[0]*x + b[1]
linmodel = odr.Model(odrlin)

fig, ax = plt.subplots()

x = np.linspace(1,10,10)
y = 2.8*x + 4.2
y = y*(1 + (np.random.random(len(y))-0.5)*0.2)  # y方向添加噪声
xerr, yerr = np.ones(len(x))*x*0.1, np.ones(len(y))*y*0.1  # 10%相对误差
ax.errorbar(x, y, xerr=xerr, yerr=yerr, ls='', marker='.')

# 正常运行:标量误差
print('case 1')
sx, sy = 0.1, 2
odrdata = odr.RealData(x=x, y=y, sx=sx, sy=sy)
myodr = odr.ODR(odrdata, linmodel, beta0=[2,4])
odrout = myodr.run()
odrout.pprint()

# 报错:数组型相对误差
print('\n case 2')
sx, sy = xerr, yerr
odrdata = odr.RealData(x=x, y=y, sx=sx, sy=sy)
myodr = odr.ODR(odrdata, linmodel, beta0=[2,4])
odrout = myodr.run()
odrout.pprint()

# 报错:数组型固定误差
print('\n case 3')
sx, sy = np.ones(len(x))*0.1, np.ones(len(y))*2
odrdata = odr.RealData(x=x, y=y, sx=sx, sy=sy)
myodr = odr.ODR(odrdata, linmodel, beta0=[2,4])
odrout = myodr.run()
odrout.pprint()

原因分析

scipy.odr默认使用的'odr'拟合方法(正交距离回归的原生实现)在处理数组型逐点误差时,容易因权重矩阵的构造方式导致信息矩阵秩亏缺,进而触发“非满秩”错误。而标量误差下权重矩阵是对角矩阵且对角元素一致,矩阵结构更稳定,不会出现该问题。

解决方案

显式指定拟合方法为'leastsq'(Levenberg-Marquardt最小二乘法),该方法对数组型权重的兼容性更好,能避免秩亏缺问题。只需在调用run()方法时添加method='leastsq'参数即可。

修改后的验证代码

将case2和case3的run()调用修改为:

odrout = myodr.run(method='leastsq')

修改后重新运行,程序将正常输出拟合结果,不再触发“非满秩”错误。例如case2的输出会包含正确的拟合参数、残差等信息,格式与case1一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 13:25:00