Skip to main content
 首页 » 编程设计

python之Levenberg-Marquardt-算法和 ODR 之间的区别

2025年05月04日14mayingbao

我能够使用 peak-o-mat 将曲线拟合到 x/y 数据集, 如下所示。那是线性背景和 10 条洛伦兹曲线。

因为我需要拟合许多相似的曲线,所以我使用 mpfit.py 编写了一个脚本化的拟合例程,这是 Levenberg-Marquardt 算法。然而,拟合需要更长的时间,而且在我看来,它不如 peak-o-mat 结果准确:

起始值

固定线性背景的拟合结果(从 peak-o-mat 结果中获取的线性背景值)

所有变量自由拟合结果

我相信起始值已经非常接近,但即使有固定的线性背景,左洛伦兹显然是拟合的退化。

完全自由拟合的结果更糟。

Peak-o-mat 似乎使用了 scipy.odr.odrpack .现在更有可能的是:

  1. 我犯了一些实现错误吗?
  2. odrpack 更适合这个特定问题?

拟合一个更简单的问题(中间有一个峰的线性数据)显示 peak-o-mat 和我的脚本之间有很好的相关性。我也没有找到很多关于 ordpack 的信息。

编辑: 看来我可以自己回答这个问题,但答案有点令人不安。使用 scipy.odr(它允许使用 odr 或 leastsq 方法进行拟合)都将结果作为 peak-o-mat,即使没有约束。

下图再次显示了数据、起始值(几乎完美)以及 odr 和 leastsq 拟合。组件曲线是针对 odr 的

我会改用 odr,但这仍然让我心烦意乱。这些方法(mpfit.py、scipy.optimize.leastsq、leastsq 模式下的 scipy.odr)“应该”产生相同的结果。

对于偶然发现这篇文章的人:要执行 odr 拟合,必须为 x 和 y 值指定错误。如果没有错误,请使用带有 sx << sy 的小值。

linear = odr.Model(f) 
mydata = odr.RealData(x, y, sx = 1e-99, sy = 0.01) 
myodr = odr.ODR(mydata, linear, beta0 = beta0, maxit = 2000) 
myoutput1 = myodr.run()  

请您参考如下方法:

您也可以使用 peak-o-mat 编写脚本。最简单的方法是创建包含您想要通过 GUI 拟合的所有数据的项目,清理它,转换它并将基本模型附加(即选择一个模型,提供初始猜测和拟合)到其中一个集合。然后您可以(深度)复制该模型并将其附加到所有其他数据集。试试这个:

from peak_o_mat.project import Project 
from peak_o_mat.fit import Fit 
from copy import deepcopy 
 
p = Project() 
p.Read('in.lpj') 
 
base = p[2][0]    # this is the set which has been fit already 
 
for data in p[2][1:]: # all remaining sets of plot number 2 
 
    mod = deepcopy(base.mod) 
    data.mod = mod 
 
    f = Fit(data, data.mod) 
    res = f.run() 
 
    pars = res[0] 
    err = res[1] 
 
    data.mod._newpars(pars, err) 
 
    print data.mod.parameters_as_table() 
 
p.Write('out') 

如果您需要更多详细信息,请告诉我。