You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用lmfit进行穆斯堡尔光谱曲线拟合时遇报错求助

穆斯堡尔光谱双洛伦兹拟合报错求助

我是lmfit新手,在处理约27000个数据点的穆斯堡尔光谱数据时持续报错,现提供报错信息、拟合代码、数据特征及数据集,恳请专业人士提供解决方案。

报错信息

RuntimeError: Optimal parameters not found: Number of calls to function has reached maxfev = 1000

数据特征

数据呈现两个明显的负向洛伦兹峰,Channel范围约0-8000,Counts为负值的峰形数据。

原始拟合代码

import numpy as np
import matplotlib.pyplot as plt
from lmfit import Model
import pandas as pd

plt.rcParams['figure.dpi'] = 300
plt.rcParams['savefig.dpi'] = 300

# Define the Lorentzian function with a negative sign
def lorentzian(x, amp, cen, wid):
    return (-amp * wid ** 2 / ((x - cen) ** 2 + wid ** 2))

# Define the sum of two Lorentzian peaks
def multi_lorentzian(x, a1, c1, w1, a2, c2, w2):
    return (lorentzian(x, a1, c1, w1) + lorentzian(x, a2, c2, w2))

csv_names = ['Channel', 'Energy', 'Counts']
fp2 = "C:\Users\mfern\Downloads\Data_3_8.csv"

df = pd.read_csv(fp2, skiprows=23, names=csv_names).dropna()  # Remove rows with NaN values

xdata = df['Channel']
ydata = df['Counts']

model = Model(multi_lorentzian)

params = model.make_params(a1=0, c1=0, w1=0, a2=0, c2=0, w2=0)
params['a1'].min = 0
params['a2'].min = 0
params['w1'].min = 0
params['w2'].min = 0

result = model.fit(ydata, params=params, x=xdata)

# Print the fit report
print(result.fit_report())

# Plot the data and the fit curve
plt.scatter(xdata, ydata, label='data', s=2, c='b')
plt.plot(xdata, result.best_fit, 'r-', label='fit')
plt.legend()

解决方案及修改后代码

问题分析

  1. 初始参数完全为0:拟合算法无法从全0参数出发找到有效优化方向,必须根据数据特征设置合理初始值。
  2. 迭代次数不足:默认最大迭代次数(maxfev=1000)不足以处理27000个数据点的拟合。
  3. Windows路径转义问题:原始路径中的反斜杠未转义,可能导致文件读取错误。

修改后代码

import numpy as np
import matplotlib.pyplot as plt
from lmfit import Model
import pandas as pd

plt.rcParams['figure.dpi'] = 300
plt.rcParams['savefig.dpi'] = 300

# 带负号的洛伦兹函数
def lorentzian(x, amp, cen, wid):
    return (-amp * wid ** 2 / ((x - cen) ** 2 + wid ** 2))

# 双洛伦兹峰求和
def multi_lorentzian(x, a1, c1, w1, a2, c2, w2):
    return lorentzian(x, a1, c1, w1) + lorentzian(x, a2, c2, w2)

csv_names = ['Channel', 'Energy', 'Counts']
# 使用原始字符串避免Windows路径转义问题
fp2 = r"C:\Users\mfern\Downloads\Data_3_8.csv"

df = pd.read_csv(fp2, skiprows=23, names=csv_names).dropna()

xdata = df['Channel'].values
ydata = df['Counts'].values

model = Model(multi_lorentzian)

# 根据数据特征设置合理初始参数
# 从数据图看,两个峰中心大概在1500和6500,峰值绝对值约500,峰宽约200
params = model.make_params(a1=500, c1=1500, w1=200, a2=500, c2=6500, w2=200)
params['a1'].min = 0
params['a2'].min = 0
params['w1'].min = 0
params['w2'].min = 0

# 增加最大迭代次数,可选添加加权拟合(计数数据误差为sqrt(abs(ydata)))
result = model.fit(ydata, params=params, x=xdata, max_nfev=50000, weights=1/np.sqrt(abs(ydata)))

# 打印拟合报告
print(result.fit_report())

# 绘制数据与拟合曲线
plt.scatter(xdata, ydata, label='原始数据', s=2, c='b')
plt.plot(xdata, result.best_fit, 'r-', label='拟合曲线')
plt.xlabel('Channel')
plt.ylabel('Counts')
plt.legend()
plt.show()

额外说明

  • 初始参数的设置可以通过观察数据可视化图手动估算,越接近真实值,拟合成功率越高。
  • 加权拟合能让拟合算法更关注误差小的数据点,提升拟合精度。
  • 如果仍有报错,可以尝试调整优化算法,比如在fit时添加method='leastsq'(默认)或其他优化器如'nelder'。

内容的提问来源于stack exchange,提问作者matthew fernandez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 20:25:06