使用lmfit拟合洛伦兹模型后,如何生成多数据点平滑曲线?
Lorentzian拟合平滑曲线异常的修复方案
问题描述
使用lmfit的LorentzianModel拟合数据时,绘制的最佳拟合曲线仅在原始数据的x值点显示,尝试用np.linspace生成平滑x序列绘制拟合曲线时结果异常。
原始数据与代码
数据
y_means = [2.32070822e-06, 1.90175015e-06, 2.09473380e-06, 2.80934411e-06, 2.38255275e-06, 3.02204121e-06, 3.84290466e-06, 3.84136311e-06, 7.53941486e-06, 8.68364774e-06, 1.20078494e-05, 2.20557048e-05, 3.73314724e-05, 6.03141332e-05, 9.84530711e-05, 1.58565010e-04, 3.61269554e-04, 7.53586472e-04, 3.56518897e-04, 1.60734633e-04, 1.06442283e-04, 5.41622644e-05, 2.73085592e-05, 2.54361900e-05, 9.10802093e-06, 4.81356192e-06, 6.49884117e-06, 4.94871197e-06, 3.27389990e-06, 2.65197533e-06, 2.52672943e-06, 2.56496345e-06, 2.11445845e-06, 1.96091323e-06, 2.60823301e-06] all_xslices = [ 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, 30, 31, 32, 33, 34]
原始代码
# lorentzian fit from lmfit.models import LorentzianModel model = LorentzianModel() params = model.guess(y_means, x=all_xslices) all_xslices_fit = np.linspace(min(all_xslices), max(all_xslices), 100) result = model.fit(y_means, params, x=all_xslices) result_smooth = model.eval(x=all_xslices_fit) # plotting the decay along y-axis: log axis plt.figure(figsize=(8, 5), dpi=300) plt.scatter(all_xslices, y_means, marker = '.', s = 200, c = 'g', label = "") # plt.plot(all_xslices,lorentzian(all_xslices,*popt), 'g', label='Lorentz 1') plt.plot(all_xslices, result.best_fit, 'g', label='Lorentz') plt.plot(all_xslices_fit, result_smooth, 'r', label='Lorentz') plt.xlabel("y length", fontsize = 15) plt.ylabel("FFT amplitude", fontsize = 15) plt.xticks(fontsize = 15) plt.yticks(fontsize = 15) plt.yscale('log') plt.subplots_adjust(right=0.96,left=0.15,top=0.96,bottom=0.12) plt.legend(loc = 'best') plt.show()
问题原因
生成平滑拟合曲线时,直接调用model.eval()但未传入拟合后的最优参数,导致使用初始猜测的params而非拟合得到的结果,这是平滑曲线异常的核心原因。
修正后的代码
import numpy as np import matplotlib.pyplot as plt from lmfit.models import LorentzianModel # 数据 y_means = [2.32070822e-06, 1.90175015e-06, 2.09473380e-06, 2.80934411e-06, 2.38255275e-06, 3.02204121e-06, 3.84290466e-06, 3.84136311e-06, 7.53941486e-06, 8.68364774e-06, 1.20078494e-05, 2.20557048e-05, 3.73314724e-05, 6.03141332e-05, 9.84530711e-05, 1.58565010e-04, 3.61269554e-04, 7.53586472e-04, 3.56518897e-04, 1.60734633e-04, 1.06442283e-04, 5.41622644e-05, 2.73085592e-05, 2.54361900e-05, 9.10802093e-06, 4.81356192e-06, 6.49884117e-06, 4.94871197e-06, 3.27389990e-06, 2.65197533e-06, 2.52672943e-06, 2.56496345e-06, 2.11445845e-06, 1.96091323e-06, 2.60823301e-06] all_xslices = [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, 30, 31, 32, 33, 34] # Lorentzian拟合 model = LorentzianModel() params = model.guess(y_means, x=all_xslices) result = model.fit(y_means, params, x=all_xslices) # 生成平滑x序列并计算拟合值(使用拟合后的最优参数) all_xslices_fit = np.linspace(min(all_xslices), max(all_xslices), 100) result_smooth = result.eval(x=all_xslices_fit) # 重点:用result.eval而非model.eval # 绘图 plt.figure(figsize=(8, 5), dpi=300) plt.scatter(all_xslices, y_means, marker='.', s=200, c='g', label='原始数据') plt.plot(all_xslices, result.best_fit, 'g--', label='原始点拟合曲线') plt.plot(all_xslices_fit, result_smooth, 'r-', label='平滑拟合曲线') plt.xlabel("y length", fontsize=15) plt.ylabel("FFT amplitude", fontsize=15) plt.xticks(fontsize=15) plt.yticks(fontsize=15) plt.yscale('log') plt.subplots_adjust(right=0.96, left=0.15, top=0.96, bottom=0.12) plt.legend(loc='best') plt.show() # 可选:打印拟合结果 print(result.fit_report())
关键修改点
- 替换
model.eval(x=all_xslices_fit)为result.eval(x=all_xslices_fit):result对象包含拟合后的最优参数,调用其eval方法才能得到基于最优参数的平滑拟合曲线。 - 补充缺失的
numpy和matplotlib导入语句,保证代码可直接运行。 - 给图例添加明确标签,区分原始数据、原始点拟合曲线和平滑拟合曲线,提升可读性。
内容的提问来源于stack exchange,提问作者Abhinav Kumar
相关产品推荐
相关产品推荐

