scipy.optimize.curvefit:拟合中的不对称误差

4

我试图使用scipy.optimize.curvefit将函数拟合到我的数据中。

Q=optimization.curve_fit(func,X,Y, x0,ERR)

它很好用。

然而,现在我正在尝试使用不对称误差,但我不知道如何做到这一点 - 或者是否可能。

通过不对称误差,我的意思是误差不是例如:3+-0.5 而是 3 +0.6 -0.2。因此ERR是一个具有两列的数组。

如果有人有想法如何做到这一点 - 或者可以指向一个不同的Python例程,该例程可能能够实现它,那将是非常棒的。

这是我正在使用的代码片段 - 但我不确定它是否更清晰:

A=numpy.genfromtxt('WF.dat')
cc=A[:,4]
def func(A,a1,b1,c1):
    N=numpy.zeros(len(x))
    for i in range(len(x)):
        N[i]=1.0*erf(a1*(A[i,1]-c1*A[i,0]**b1))

return N


x0   = numpy.array([2.5  , -0.07 ,-5.0])
Q=optimization.curve_fit(func,A,cc, x0, Error)

错误=[ErP,ErM](2列)


你能否发布一些(最好是可运行的)代码,以便我们可以更详细地了解问题? - YXD
你不能简单地将 3 +0.6 -0.2 转换为 3.2 +/- 0.4 吗? - Jaime
1
不是真的。这样做会失去拥有如此精确错误的目的。 - user2622479
如果您按照E先生的建议提供一个简单可运行的示例以突出问题,那么这个问题可能更有趣。请不要从文件中加载数据,而是生成一个非对称高斯函数并添加一些随机噪声(np.random.random)。然后,解决方案可以尝试拟合该函数,并获取平均值的非对称误差。 - DanHickstein
4个回答

1
在当前版本中,恐怕无法实现。 curve_fit 是对流行的Fortran库minipack的包装。检查\scipy_install_path\optimize\minipack.py的源代码,您将看到:(第498-509行):
if sigma is None:
    func = _general_function
else:
    func = _weighted_general_function
    args += (1.0/asarray(sigma),)

基本上意思是如果未提供 sigma,则将调用 minipack 中的非加权 Levenberg-Marquardt 方法。如果提供了 sigma,则将调用加权 LM。这意味着,如果要提供 sigma,它必须作为与 XY 长度相同的数组提供。这意味着,如果您想在 Y 上具有非对称误差残差,则必须对目标函数进行一些修改,如 @Jaime 建议的那样。

1

curve_fitscipy.optimize.leastsq这样的最小二乘算法不能处理此类问题,因为损失函数是二次的,所以对于正误差和负误差是对称的。

我没有看到过针对此类问题的模型,也许PAIDA可以处理,正如DanHickstein所提到的那样。

否则,您可以使用非线性优化器,例如optimize.fmin并构建自己的非对称损失函数。

def loss_function(params, ...):
    error = (y - func(x, params))
    error_neg = (error < 0)
    error_squared = error**2 / (error_neg * sigma_low + (1 - error_neg) * sigma_upp))
    return error_squared.sum()

可以使用fminfmin_bfgs来最小化这个函数。

(我从未尝试过这个方法。)


0

0
一个我经常使用的解决方案是从一个分裂正态分布中抽取实现(比如100-1000个),并在每个实现上运行拟合算法,将误差设置为0.0。然后你就会得到100-1000个最佳拟合参数,你可以简单地取中位数,并选择任何你想要使用的误差估计。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接