python - 使用复合 PseudoVoigt 模型时出现 NameError

标签 python python-3.x curve-fitting lmfit

将复合 PseudoVoigt 模型与参数命名前缀结合使用时,我收到 NameError。

我几乎复制了上一个问题中的复合模型示例,使用洛伦兹分布 ( Fitting a multi-peak function to a DataSet using LMFIT )。 这对我来说效果很好,但洛伦兹线形状并不是我想要拟合的函数。

当我将 PseudoVoigtModel 用于单个峰值时,我没有任何问题。另外,洛伦兹模型与下面的代码配合得很好(我也将它包含在代码中,以便您可以自己仔细检查/确认)。

from lmfit.models import LorentzianModel, PseudoVoigtModel
import numpy as np
import matplotlib.pyplot as plt

def make_model_L(num):
    pref = "f{0}_".format(num)
    model = LorentzianModel(prefix = pref)
    model.set_param_hint(pref+'amplitude', value=amplitude[num], min=0, max=5*amplitude[num])
    model.set_param_hint(pref+'center', value=center[num], min=center[num]-0.5, max=center[num]+0.5)
    model.set_param_hint(pref+'sigma', value=width[num], min=0, max=2)
    return model


def make_model_V(num):
    pref = "f{0}_".format(num)
    model = PseudoVoigtModel(prefix = pref)
    print('before',model.param_names)
    model.set_param_hint(pref+'fraction',value = 0.7, vary = False)
    model.set_param_hint(pref+'amplitude', value=amplitude[num], min=0, max=5*amplitude[num])
    model.set_param_hint(pref+'center', value=center[num], min=center[num]-0.5, max=center[num]+0.5)
    model.set_param_hint(pref+'fwhm', value=3, min=3/5, max=3*5)
    model.set_param_hint(pref+'sigma', value=1, min=0, max=2)
    model.set_param_hint(pref+'height', value=1, min=-np.inf, max=np.inf, expr='(((1-fraction)*amplitude)/(sigma*sqrt(pi/log(2)))+(fraction*amplitude)/(pi*sigma))')
    print(model.param_names)
    return model

# Some really coarse "data"
x = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29]
y = [1,1,1,1,3,4,5,6,5,4,3,1,1,1,1,1,1,1,1,3,4,5,6,5,4,3,1,1,1,1]

peaks_in_interval = np.array([43, 159, 191, 296, 435, 544])
amplitude = [3,3]
width = [1,1]
center = [7,21]

mod = None
for i in range(len(center)):
    #this_mod = make_model_L(i)
    this_mod = make_model_V(i)
    if mod is None:
        mod = this_mod
    else:
        mod = mod + this_mod

out=mod.fit(y, x=x, method='leastsq')
plt.interactive(True)
print(out.fit_report())
plt.plot(x, y)
plt.plot(x, out.best_fit, label='best fit')
plt.plot(x, out.init_fit, 'r--', label='fit with initial values')
plt.show()

我收到的错误消息:

名称错误 <_ast.Module 对象位于 0x7f562524dbe0> ^^^ 名称“分数”未定义

NameError: at expr='<_ast.Module 对象位于 0x7f562524dbe0>'

我没有包含 TraceBack。它从“out=mod.fit(y, x=x, method='leastsq')”开始,以“~/anaconda3/lib/python3.6/site-packages/asteval/asteval.py in raise_exception(self ,节点,exc,msg,expr,lineno)”

如前所述,使用 LorentzianModel 一切正常,我得到了一个拟合(不是一个很好的拟合,但这是由于测试数据造成的)。

我不太精通 python,所以我无法真正给出有关问题可能是什么的明智提示。但是,我怀疑它与分数的命名以及它如何在 lmfit.fit() 函数中传递有关。

最好, 一月

最佳答案

最好找到并发布一个显示问题的最小示例,并且最好包含完整的输出(包括回溯)。

例如,您会看到遇到的问题:

from lmfit.models import PseudoVoigtModel

pref = 'f1_'
model = PseudoVoigtModel(prefix = pref)
print('before',model.param_names)
model.set_param_hint(pref+'fraction',value = 0.7, vary = False)
model.set_param_hint(pref+'amplitude', value=2, min=0, max=5)
model.set_param_hint(pref+'center', value=0, min=-0.5, max=0.5)
model.set_param_hint(pref+'fwhm', value=3, min=3/5, max=3*5)
model.set_param_hint(pref+'sigma', value=1, min=0, max=2)
# suspect line:
model.set_param_hint(pref+'height', value=1, min=-np.inf, max=np.inf,
                     expr='(((1-fraction)*amplitude)/(sigma*sqrt(pi/log(2)))+(fraction*amplitude)/(pi*sigma))')

print(model.param_names)
params = model.make_params()
for p in params.values():
    print(p)

问题的出现是因为没有名为fraction的参数。正如上面几行所定义的,它被命名为 f1_fraction

要解决此问题,您应该更改 pref+'height' 的表达式,以便还包含 fraction 所需的 pref 前缀字符串、振幅西格玛

或者:您可以删除对 height 的提示,因为无论如何都会自动完成,并正确使用您提供的前缀。

另外:

a)绝对不鼓励像您一样使用参数提示来提供初始值。提示属于模型,不应依赖于任何特定的数据集。将模型作为一般事物创建,然后为每个数据集创建具有初始值的参数。

b) 不要将边界设置得太紧或基于初始值。界限(尤其是在参数提示中)应该用于防止参数变为非物理值,例如“sigma 为负数是没有意义的”,而不是因为定义模型的人认为“那应该足够接近了”。让合身发挥其作用。如果您确实需要设置自定义边界,请针对每个数据集进行设置。

关于python - 使用复合 PseudoVoigt 模型时出现 NameError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55533645/

相关文章:

python - matplotlib 图中的条形大小不一致

python-3.x - Ubuntu 16.04 Docker容器中的PySpark开发环境

python - 将(三重)高斯拟合到数据 python

python - 使用最小二乘法进行指数拟合 Python

python - 曲线拟合问题,exp遇到溢出

c++ - 从 Python 调用 C/C++?

python - IRC 机器人 Python |识别昵称

python - 在numpy中连接两个多维数组

python - 尝试在 GoDaddy 上部署 Flask 应用程序时出现 403

python - 在 Python 3 中使用 partial 在元类中创建实例方法