基于MINUIT的Python参数转换

基于MINUIT的Python参数转换,python,constraints,scipy,bounds,Python,Constraints,Scipy,Bounds,我正在基于scipy的optimize.leastsq为2D数据编写一个自动曲线拟合例程,它可以正常工作。然而,当添加许多起始值很小的曲线时,我会得到非物理结果(例如负振幅) 我找到了这篇文章,并试图根据欧洲核子研究所的Minuit使用参数转换。在上面提到的问题中,有人提供了一些python代码的链接 code.google.com/p/nmrglue/source/browse/trunk/nmrglue/analysis/leastsqbound.py 我编写了这个最小的工作示例(扩展代码

我正在基于scipy的optimize.leastsq为2D数据编写一个自动曲线拟合例程,它可以正常工作。然而,当添加许多起始值很小的曲线时,我会得到非物理结果(例如负振幅)

我找到了这篇文章,并试图根据欧洲核子研究所的Minuit使用参数转换。在上面提到的问题中,有人提供了一些python代码的链接

code.google.com/p/nmrglue/source/browse/trunk/nmrglue/analysis/leastsqbound.py
我编写了这个最小的工作示例(扩展代码)

这是绘图输出,其中绿色表示开始条件,红色表示拟合结果:

这是正确的用法吗?External2如果超出边界,内部转换只会抛出一个nan。leastsq似乎能处理这个问题


我上传了拟合数据。只需粘贴到名为constraint.dat的文本文件中。

已有一个流行的constraint.dat代码

使用python实现


我建议不要重新发明轮子

根据sega_sai的回答,我使用mpfit.py给出了这个最小的工作示例

import matplotlib.pyplot as plt
from mpfit import mpfit
import numpy as np

def _evaluate(p, x):
    '''
    Linear plus Lorentzian curve
    p = list with three parameters ([a, b, I, Pos, FWHM])
    '''
    return p[0] + p[1] * x + p[2] / (1 + np.power((x - p[3]) / (p[4] / 2), 2))

def residuals(p, fjac = None, x = None, y = None, err = None):
    status = 0
    error = _evaluate(p, x) - y
    return [status, error / err]

if __name__ == '__main__':
    data = np.loadtxt('constraint.dat') # read data
    x = data[:, 0]
    y = data[:, 1]
    err = 0 * np.ones(y.shape, dtype = 'float64')
    parinfo = [{'value':5000., 'fixed':0, 'limited':[0, 0], 'limits':[0., 0.], 'parname':'a'},
               {'value':0., 'fixed':0, 'limited':[0, 0], 'limits':[0., 0.], 'parname':'b'},
               {'value':500., 'fixed':0, 'limited':[0, 0], 'limits':[0., 0.], 'parname':'I'},
               {'value':2450., 'fixed':0, 'limited':[0, 0], 'limits':[0., 0.], 'parname':'Pos'},
               {'value':3., 'fixed':0, 'limited':[0, 0], 'limits':[0., 0.], 'parname':'FWHM'}]
    fa = {'x':x, 'y':y, 'err':err}
    m = mpfit(residuals, parinfo = parinfo, functkw = fa)
    print m
拟合结果如下:

mpfit.py: 3714.97545, 0.484193283, 2644.47271, 2440.13385, 22.1898496
leastsq:  3714.97187, 0.484194545, 2644.46890, 2440.13391, 22.1899295
结论:两种方法都有效,都允许约束。但由于mpfit来自一个非常成熟的来源,我更相信它。如果可用,它也会接受错误值。

试试lmfit py-

  • 它还通过scipy.optimize.leastsq使用Levenberg-Marquardt(LM)算法。不确定因素是可以的

  • 它不仅可以使用边界约束拟合参数,还可以使用它们之间的数学表达式约束拟合参数,而无需修改拟合函数

  • 忘记使用那些糟糕的p[0],p[1]。。。在拟合函数中。只需通过parameters类使用管件参数的名称


  • 谢谢你指出这一点。我以前没有找到任何关于mpfit的参考资料,它看起来正是我试图实现的目标。但是一个最小的工作示例会是什么样子呢?该用法与scipy的leastsq不同。似乎没有传递x和y值,而是传递引用?mpfit.py中的示例也不起作用。下面是一个肯定有效的示例:我使用了您链接的测试文件中的第一个示例来运行下面的解决方案。起初我有点困惑,因为它们使用起始值p0=[1,1],但在参数字典parinfo中,它们使用3.2和1.78。另外,调用中实际上不需要p0。请参见我的另一个:mpfit.py不适合。是的。
    mpfit.py: 3714.97545, 0.484193283, 2644.47271, 2440.13385, 22.1898496
    leastsq:  3714.97187, 0.484194545, 2644.46890, 2440.13391, 22.1899295