我有一些数据点的 x 和 y 坐标都有错误。因此我需要使用python的
scipy.odr.ODR
工具来计算最佳拟合斜率和该斜率上的误差。但是,当我尝试添加错误时,ODR 失败并仅返回初始猜测参数。
我尝试运行它而没有错误,并且它按预期工作:
# Import statements
import numpy as np
import matplotlib.pyplot as plt
from scipy.odr import ODR, Model, Data, RealData
# Model function - linear fit
def model_func(params, x):
m, c = params
return m * x + c
#Model object - linear fit
model = Model(model_func)
# example data
n = 50
x = np.linspace(0, 50, n)
y = 2.0 * x + 1.0
x_err = np.abs(np.random.normal(0,2.5,n))
y_err = np.abs(np.random.normal(0,2.5,n))
x_data = np.random.normal(x,x_err,n)
y_data = np.random.normal(y,y_err,n)
# Data object with errors
data1 = Data(x_data, y_data, wd=1./x_err, we=1./y_err)
# Data object without errors
data2 = Data(x_data, y_data)
# odr object, and parameters for data1
odr1 = ODR(data1, model, beta0=[1., 1.])
odr1.set_job(fit_type=0)
output1 = odr1.run()
params1 = output1.beta
param_errors1 = output1.sd_beta
# odr object, and parameters for data1
odr2 = ODR(data2, model, beta0=[1., 1.])
odr2.set_job(fit_type=0)
output2 = odr2.run()
params2 = output2.beta
param_errors2 = output2.sd_beta
print("Fitted parameters with err:", params1)
print("Parameter errors with err:", param_errors1)
print("Fitted parameters without err:", params2)
print("Parameter errors without err:", param_errors2)
# Draw plots
fig, ax = plt.subplots()
plt.errorbar(x_data, y_data, yerr=y_err, xerr=x_err, linestyle="", marker="o", label="data")
plt.axline((x_data[0],model_func(params1,x_data[0])),slope=params1[0], color="k", label="Fit without errors")
plt.axline((x_data[0],model_func(params2,x_data[0])),slope=params2[0], color="r", label="Fit with errors")
plt.legend()
plt.show()
打印语句给出:
Fitted parameters with err: [1. 1.]
Parameter errors with err: [0. 0.]
Fitted parameters without err: [1.94789948 2.92857792]
Parameter errors without err: [0.05371152 1.5487141 ]
并且这个是图像: 最适合的数据和线条
当我添加错误参数时出了什么问题?
问题出在定义数据的方式和指定的拟合权重中。在 ODR 中,较大的权重表示较小的方差,因此对拟合有更大的影响。正在使用误差的倒数来定义权重 (
wd=1./x_err, we=1./y_err
)。
但是,的某些数据点中的
x_err
和
y_err
值接近于零。当取这些接近零的值的倒数时,得到的权重非常大(接近无穷大)。这些巨大的权重会导致拟合算法出现问题,因为它基本上会强制拟合算法完全通过这些点,而忽略其他数据点。
为了解决此问题,可以:
- 避免接近零的错误: 调查为什么的数据点中会出现接近零的错误。如果可能,请更正数据或错误估计过程。
-
设置错误阈值:
在计算权重之前,为
x_err
和y_err
设置一个小的阈值。例如,可以将所有小于 0.1 的错误替换为 0.1。这将防止出现极大的权重。 -
使用不同的权重方案:
不要使用误差的倒数,请考虑使用其他权重方案,例如
wd=1./x_err**2, we=1./y_err**2
,这会减轻极端权重的影响。
以下是修改后的代码,其中包含用于设置错误阈值的选项:
# ...(其他导入和代码)
# 设置错误阈值
error_threshold = 0.1
x_err[x_err < error_threshold] = error_threshold
y_err[y_err < error_threshold] = error_threshold
# 数据对象(使用修改后的错误)
data1 = Data(x_data, y_data, wd=1./x_err, we=1./y_err)
# ...(其余代码)
通过应用这些更改,ODR 拟合应该可以正确处理错误并为提供合理的参数估计和错误。
标签:python,scipy,scipy-optimize From: 78836025