使用lmfit的RectangleModel/StepModel拟合峰+背景遇参数更新错误求助
lmfit中RectangleModel/StepModel调用guess()更新参数时报错的解决方法
问题描述
我尝试使用峰+背景模型进行数据拟合,代码如下:
import numpy as np import scipy.stats as stats import lmfit import matplotlib.pyplot as plt # 生成随机数据 np.random.seed(1234) y_data = np.random.normal(loc=5, scale=4, size=100000) + np.random.exponential(scale=5, size=100000) # 数据分桶做直方图用于拟合 y, x = np.histogram(y_data, bins=100, density=False) # 计算桶中心 x = (x[1:] + x[:-1])/2 plt.errorbar(x, y, yerr=stats.sem(y), fmt='.', zorder=1, label='data points') peak1 = lmfit.models.SkewedVoigtModel(prefix="peak_") pars = peak1.make_params() # 设置峰模型参数 pars['peak_center'].set(value=5, vary=True) pars['peak_sigma'].set(value=4, vary=True) # 设置背景模型 # background1 = lmfit.models.PolynomialModel(3,prefix="back_",) background1 = lmfit.models.RectangleModel(prefix="back_", format='arctan') pars.update(background1.guess(y, x=x)) # 构建完整拟合模型 model = peak1 + background1 # 执行拟合 out = model.fit(y, pars, x=x) # 生成更精细的x轴用于绘图 xs = np.linspace(min(x), max(x), 100) # 绘制拟合结果 plt.plot(xs, out.eval(params=out.params, x=xs), label='Total Fit') plt.legend() plt.show()
运行代码后触发错误:
TypeError: lmfit.parameter.Parameter.set() argument after ** must be a mapping, not numpy.int64
经排查,错误源于pars.update(background1.guess(y, x=x))这一行。使用PolynomialModel等其他模型时无此错误,但StepModel和RectangleModel存在该问题。我的numpy版本为1.2.0(已包含RectangleModel),换其他模型可正常运行:

解决方案
方法1:手动初始化背景模型参数,避免使用guess()
RectangleModel(format='arctan')的核心参数为amplitude、center、sigma,可以根据数据手动设置初始值,替代guess()方法:
# 替换原有的pars.update(background1.guess(y, x=x)) background1 = lmfit.models.RectangleModel(prefix="back_", format='arctan') # 根据数据特征设置初始参数 pars.update(background1.make_params( back_amplitude=np.max(y), back_center=np.median(x), back_sigma=2 ))
方法2:升级lmfit及numpy版本
numpy 1.2.0版本较老旧,可能与lmfit存在兼容性问题。建议:
- 升级lmfit到最新稳定版:
pip install --upgrade lmfit - 同步升级numpy到更现代的版本(如1.21.x及以上):
pip install --upgrade numpy
新版本的lmfit大概率修复了RectangleModel的guess()方法返回值类型异常的bug。
方法3:转换guess()返回参数的数值类型
如果必须使用guess()方法,可以将返回参数中的numpy数值类型转换为Python原生类型后再更新:
bg_guess = background1.guess(y, x=x) # 遍历参数,将numpy类型值转为Python原生类型 for param in bg_guess.values(): if isinstance(param.value, np.generic): param.value = param.value.item() pars.update(bg_guess)
内容的提问来源于stack exchange,提问作者Krishna Neupane
相关产品推荐
相关产品推荐

