曲线拟合遇到麻烦-lmfit无法对峰值数据产生适当的拟合 [英] Trouble with curve fitting - lmfit won't produce proper fit to peak data

查看:205
本文介绍了曲线拟合遇到麻烦-lmfit无法对峰值数据产生适当的拟合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对python和lmfit模型还很陌生,遇到了一些麻烦.我想将峰值函数(例如高斯或Voigtian轮廓图)拟合到我的实验数据中,但是它从未给我带来任何良好的结果.最佳拟合是线性函数,它描述了我的峰轮廓的基线.

I'm quite new to python and the lmfit model and having some trouble. I want to fit a peak function (something like Gaussian or Voigtian profil) to my experimental data, but it never gives me any good results. Its best fit is a linear function, which kind of describes the base line of my peak profile.

用于拟合过程的x数据只是从0到100的数字.这是我的y数据:

The x data for the fitting process are simply numbers running from 0 to 100. Here are my y data:

array([ 0.99518284,  0.99449661,  0.99609029,  0.996     ,  0.994307  ,
    0.999693  ,  0.99826185,  0.99680361,  0.99474041,  0.99793228,
    0.99385553,  0.99869526,  1.00044695,  0.99625734,  0.99758916,
    0.99489842,  1.00032957,  0.9967088 ,  0.99655982,  0.99990068,
    0.99515576,  0.99665914,  0.99990068,  0.99595034,  0.99792777,
    0.9941851 ,  0.99458691,  0.99312415,  0.99815801,  0.99851919,
    0.99637472,  0.996     ,  0.99632957,  0.99185102,  0.99173363,
    0.9915395 ,  0.99038826,  0.9917246 ,  0.99315124,  0.98968397,
    0.99120993,  0.98981038,  0.9892009 ,  0.99009932,  0.98853725,
    0.98624379,  0.98620316,  0.9826772 ,  0.99204966,  0.98455982,
    0.99049661,  0.98591422,  0.98906546,  0.98664108,  0.98740858,
    0.99076298,  0.99046953,  0.99067269,  0.99255982,  0.99264108,
    0.99215801,  0.99990068,  0.9948623 ,  0.99616704,  0.99307449,
    0.99626637,  0.9934447 ,  0.99476749,  0.99636117,  0.99840181,
    0.9984921 ,  0.99782844,  0.99853273,  0.99575621,  0.9985553 ,
    0.99936343,  0.99643792,  0.99825734,  0.9964605 ,  0.99879007,
    1.00068172,  0.99580135,  0.99898871,  1.00069074,  0.99920993,
    0.9963702 ,  0.99591874,  0.99730023,  0.99765237,  0.99334537,
    0.99798194,  0.99770655,  0.99702935,  0.99716027,  0.99662754,
    0.99779684,  0.9967088 ,  0.99736343,  0.99786907,  0.9968623 ,
    0.99961174])

我尝试了以下具有不同模型函数(高斯,Voigtian和PseudoVoigtian)的方法:

I tried the following approaches with different model functions (Gaussian, Voigtian and PseudoVoigtian):

>>> from lmfit.models import PseudoVoigtModel
>>> mod = PseudoVoigtModel()
>>> pars = mod.guess(y, x=x)
>>> out = mod.fit(y, pars, x=x)
>>> print(out.fit_report(min_correl=0.25))
>>> out.plot()

完全相同的代码对于我创建的配置文件测试功能非常有效,因此我想它没有什么问题.但是对于真实的测量数据,无论我选择哪种轮廓模型,它始终具有线性函数.这是一个示例:

The exact same code works very well for a profile test function, which I created, so I guess there is nothing wrong with it. But for the real measurement data, it always gives a linear function, no matter which profile model I choose. Here is an example:

>>> out.best_fit
array([ 0.99410398,  0.99412124,  0.99413851,  0.99415577,  0.99417303,
    0.99419029,  0.99420755,  0.99422481,  0.99424207,  0.99425932,
    0.99427658,  0.99429383,  0.99431108,  0.99432833,  0.99434558,
    0.99436283,  0.99438007,  0.99439732,  0.99441456,  0.9944318 ,
    0.99444904,  0.99446628,  0.99448351,  0.99450075,  0.99451798,
    0.99453522,  0.99455245,  0.99456968,  0.99458691,  0.99460413,
    0.99462136,  0.99463858,  0.99465581,  0.99467303,  0.99469025,
    0.99470747,  0.99472468,  0.9947419 ,  0.99475912,  0.99477633,
    0.99479354,  0.99481075,  0.99482796,  0.99484517,  0.99486237,
    0.99487958,  0.99489678,  0.99491398,  0.99493118,  0.99494838,
    0.99496558,  0.99498278,  0.99499997,  0.99501716,  0.99503436,
    0.99505155,  0.99506874,  0.99508592,  0.99510311,  0.9951203 ,
    0.99513748,  0.99515466,  0.99517184,  0.99518902,  0.9952062 ,
    0.99522338,  0.99524055,  0.99525772,  0.9952749 ,  0.99529207,
    0.99530924,  0.9953264 ,  0.99534357,  0.99536074,  0.9953779 ,
    0.99539506,  0.99541222,  0.99542938,  0.99544654,  0.9954637 ,
    0.99548085,  0.99549801,  0.99551516,  0.99553231,  0.99554946,
    0.99556661,  0.99558376,  0.9956009 ,  0.99561805,  0.99563519,
    0.99565233,  0.99566947,  0.99568661,  0.99570375,  0.99572088,
    0.99573802,  0.99575515,  0.99577228,  0.99578941,  0.99580654,
    0.99582367])

我使用下面的方法进行了另一次尝试,但是在这里,它根本不适合某些东西,尽管它对我的高斯测试函数很好,但我只得到了nan值:

I used the following approach for another try, but here, it didn't fit something at all and I only got nan values back, although it works fine for my Gaussian test function:

from lmfit.models import GaussianModel
from lmfit import Model
import numpy as np

def gaussian(x, amp, cen, wid):
    "1-d gaussian: gaussian(x, amp, cen, wid)"
    return (amp/(sqrt(2*pi)*wid)) * exp(-(x-cen)**2 /(2*wid**2))

gmod = Model(gaussian)

mod.set_param_hint('x', value=10)
mod.set_param_hint('cent', value=47)
mod.set_param_hint('wid', value=20)
mod.set_param_hint('amp', value=0.2)
pars = gmod.make_params()

out = gmod.fit(normedy, pars, x=x)
print(out.fit_report(min_correl=0.1))
plt.figure(5, figsize=(8,8))
out.plot_fit()

我尝试将数据与原点匹配,并且确实可以工作(因此数据不是不适合的"),但是如何正确地使用python呢?您是否有其他尝试方法或可初始化的方法来使它正常工作?

I tried to fit the data with origin and it definitely works (so the data are not 'unfitable'), but how can I do it with python properly? Do you no any other ways I can try or things I can initialise to make it work?

推荐答案

PseudoVoigt函数(或Voigt或Gaussian或Lorentzian)在+/-无穷大处变为0.您的数据看起来将达到〜1.0,且下降幅度约为x = 50.

A PseudoVoigt function (or Voigt or Gaussian or Lorentzian) goes to 0 at +/- infinity. Your data looks to go to ~1.0, with a dip around x=50.

您几乎可以肯定要向模型中添加线性或常数分量.对于线性组件,请尝试:

You almost certainly want to add either a linear or constant component to the model. For a linear component, try:

mod = PseudoVoigtModel()
pars = mod.guess(y, x=x)
mod = mod + LinearModel()
pars.add('intercept', value=1, vary=True)
pars.add('slope', value=0, vary=True)
out = mod.fit(y, pars, x=x)
print(out.fit_report(min_correl=0.25))

或为常数,请尝试:

mod = PseudoVoigtModel()
pars = mod.guess(y, x=x)
mod = mod + ConstantModel()
pars.add('c', value=1, vary=True)
out = mod.fit(y, pars, x=x)
print(out.fit_report(min_correl=0.25))

作为此数据的更好模型.

as a better model for this data.

此外,为了获得更好的参数初始值,您可以尝试:

Also, to get better initial values for the parameters, you might try:

mod = PseudoVoigtModel()
pars = mod.guess((1-y), x=x)    # Note '1-y'

,因此用于初始值的曲线更像一个正峰.当然,振幅的符号将是错误的,但是其振幅将接近,并且起始中心和宽度将接近正确.那应该使拟合更加健壮.

so that the curve being used for initial values is more like a positive peak. Of course, the sign of the amplitude will be wrong, but its magnitude will be close, and the starting center and width will be close to correct. That should make the fit more robust.

这篇关于曲线拟合遇到麻烦-lmfit无法对峰值数据产生适当的拟合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆