【问题标题】:Python Spinmob curve_fit works but fitter does notPython Spinmob curve_fit 有效,但 fitter 无效
【发布时间】:2018-11-30 19:47:54
【问题描述】:

我正在尝试用高斯拟合数据。

原始数据本身显示了一个非常明显的峰值。 当我尝试使用curve_fit进行拟合时,拟合会识别出峰值,但它没有弯曲的顶部。 我现在也在尝试用 spinmob 的 fitter 来拟合数据。然而,这个拟合只是给出了一条直线。

我已尝试更改拟合器的几个参数、高斯函数定义以及拟合的初始参数,但似乎没有任何效果。

代码如下:

from scipy.optimize import curve_fit
from scipy import asarray as ar,exp
import spinmob as s

x = x30
y = ydata

def gaussian(x, A, mu, sig): # See http://mathworld.wolfram.com/GaussianFunction.html
    return A/(sig * np.sqrt(2*np.pi)) * np.exp(-np.power(x-mu, 2) / (2 * np.power(sig, 2)))

popt,pcov = curve_fit(gaussian,x,y,p0=[1,7.688,0.005])

FWHM = 2*np.sqrt(2*np.log(2))*popt[2]
print("FWHM: {}".format(FWHM))

plt.plot(x,y,'bo',label='data')
plt.plot(x,gaussian(x,*popt),'r+-',label='fit')
plt.legend()

fitter = s.data.fitter()
fitter.set(subtract_bg=True, plot_guess_zoom=True)
fitter.set_functions(f=gaussian, p='A=1,mu=8.688,sig=0.001')
fitter.set_data(x, y, eydata = 0.03)
fitter.fit()

curve_fit 返回此图: Curve_fit plot

spinmob fitter plot 给出了这个: Spinmob Fitter Plot

【问题讨论】:

  • 能否请您发布数据链接?
  • 作为测试,如果您使用 spinmob 中的值作为 curve_fit 的 p0 值并且它工作正常,那么问题应该是传递给 curve_fit 的初始参数。你能做这个测试吗?

标签: python curve-fitting gaussian


【解决方案1】:

假设 spinmob 实际上在后台使用 scipy.curve_fit,我猜(抱歉)问题是您给它的初始值太远了,它不可能找到解决方案。

当然,A=1 对于scipy.curve_fit()spinmob.fitter() 都不是一个很好的猜测。峰值肯定是负数,您应该猜测的值更像-0.1 而不是+1。事实上,您可能会断言A 必须是

您为curve_fit() 提供的mu 的初始值7.688 非常好,并且可以提供解决方案。我不知道这是否是一个错字,但你给mu 的初始值 8.688 给spinmob.fitter() 非常遥远(即,超出数据范围),并且拟合永远不会能够从那里改进到正确解决方案的方式。

初始值对曲线拟合很重要,糟糕的初始值会导致糟糕的结果。

它可能被某些人视为无耻的插件,但请允许我鼓励您尝试lmfit (https://lmfit.github.io/lmfit-py/)(我是主要作者)解决此类问题。 Lmfit 用命名的 Parameter 对象替换参数值数组,以便更好地组织拟合。它还有一个内置的高斯模型(它也计算 FWHM,包括不确定性)。也就是说,使用 Lmfit,您的脚本可能如下所示:

import numpy as np
import matplotlib.pyplot as plt

from lmfit.models import GaussianModel
from lmfit.lineshapes import gaussian

# create fake data that looks like yours
xdata = 7.670 + np.arange(41)*0.0010
ydata = gaussian(xdata, amplitude=-0.196, center=7.6881, sigma=0.001)
ydata += np.random.normal(size=41, scale=10.0)

# create gaussian model
gmodel = GaussianModel()

# fit data, giving initial values for amplitude, center, and sigma
result = gmodel.fit(ydata, x=xdata, amplitude=-0.1, center=7.688, sigma=0.005)

# show results
print(result.fit_report())
plt.plot(xdata, ydata, 'bo', label='data')
plt.plot(xdata, result.best_fit, 'r+-', label='fit')
plt.legend()
plt.show()

这将打印出类似的报告

[Model]]
    Model(gaussian)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 21
    # data points      = 41
    # variables        = 3
    chi-square         = 5114.87632
    reduced chi-square = 134.602009
    Akaike info crit   = 203.879794
    Bayesian info crit = 209.020510
[[Variables]]
    sigma:      9.7713e-04 +/- 1.5456e-04 (15.82%) (init = 0.005)
    center:     7.68822727 +/- 1.5484e-04 (0.00%) (init = 7.688)
    amplitude: -0.19273945 +/- 0.02643400 (13.71%) (init = -0.1)
    fwhm:       0.00230096 +/- 3.6396e-04 (15.82%) == '2.3548200*sigma'
    height:    -78.6917624 +/- 10.7894236 (13.71%) == '0.3989423*amplitude/max(1.e-15, sigma)'
[[Correlations]] (unreported correlations are < 0.100)
    C(sigma, amplitude) = -0.577

并生成数据图和最佳拟合,例如

这应该接近你想要做的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-18
    • 2010-11-29
    • 1970-01-01
    • 2016-10-17
    • 2012-06-14
    • 2018-11-01
    相关资源
    最近更新 更多