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

如何用lmfit合并7条拟洛伦兹拟合曲线?自定义模型报错求助

解决自定义洛伦兹模型组合拟合的警告与连续曲线合并问题

咱们一步步拆解你的问题来解决:

1. 先修复参数名的低级错误

看你定义组合模型参数的时候,写了p2_ampe=16——这明显是笔误!应该是p2_amp=16才对。这个错误会导致p2_amp参数没有被正确初始化,拟合时系统可能会给它一个默认的0或者NaN,后续计算参数的标准差(stderr)时就会触发invalid value的警告。

2. 解决RuntimeWarning的核心原因

那个警告来自par.stderr/par.value的计算,通常是因为:

  • 某个参数的stderr是NaN(比如参数被过度约束、初始值不合理导致拟合无法收敛)
  • 参数的value为0,导致除法出错

针对你的情况,可以这么处理:

(1)固定不需要拟合的参数

如果你不需要拟合e参数(初始值设为0),直接把它固定住,这样lmfit就不会计算它的stderr,自然不会触发警告:

# 固定所有峰的e参数
for peak in ['p1_', 'p2_', 'p3_']:
    params[f'{peak}e'].vary = False

(2)给参数设置合理的边界

比如amp和sig不能为负数,可以给它们加边界约束:

# 为振幅和半宽设置非负边界
params['p1_amp'].min = 0
params['p1_sig'].min = 0
params['p2_amp'].min = 0
params['p2_sig'].min = 0
params['p3_amp'].min = 0
params['p3_sig'].min = 0

(3)用完整的x数据集拟合

之前你是分段拟合每个峰,现在要合并成连续曲线,应该用覆盖所有峰的完整x范围(比如x = freqs[100:-7780],这个范围要包含8Hz、14Hz、21Hz等所有峰),而不是分x1、x2。这样组合模型可以同时拟合整个曲线,参数的拟合结果会更稳定,stderr计算也更可靠。

3. 完整的正确实现示例

下面是修改后的完整代码,包含自定义模型组合、参数设置、拟合和绘图:

import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
from lmfit import Model

# 自定义拟洛伦兹函数
def lorentzian(x, amp, cen, sig, e):
    return (amp*(1-e)) / ((pow((1.0 * x - cen), 2)) + (pow(sig, 2)))

# 准备数据(和你原来的代码一致)
dataset = np.asarray(Bxfft)
freqs, psd = signal.welch(dataset, fs=266336/300, window='hamming', nperseg=16192, scaling='spectrum')
plt.semilogy(freqs[0:-7000], psd[0:-7000]/dataset.size**0, color='r', label='Bx')

# 选择覆盖所有峰的完整x范围
x = freqs[100:-7780]
y = psd[100:-7780]

# 创建带前缀的单个峰模型
peak1 = Model(lorentzian, prefix='p1_')
peak2 = Model(lorentzian, prefix='p2_')
peak3 = Model(lorentzian, prefix='p3_')
# 组合成总模型
model = peak1 + peak2 + peak3

# 初始化参数(修正笔误,添加合理边界)
params = model.make_params(
    p1_amp=6, p1_cen=8, p1_sig=1, p1_e=0,
    p2_amp=16, p2_cen=14, p2_sig=3, p2_e=0,  # 修正了p2_ampe的笔误
    p3_amp=16, p3_cen=21, p3_sig=3, p3_e=0
)

# 固定e参数(如果不需要拟合)
for peak_prefix in ['p1_', 'p2_', 'p3_']:
    params[f'{peak_prefix}e'].vary = False

# 为振幅和半宽设置非负边界
for param_name in params:
    if 'amp' in param_name or 'sig' in param_name:
        params[param_name].min = 0

# 拟合总模型
result = model.fit(y, params, x=x)

# 输出拟合报告
print(result.fit_report(min_correl=0.25))

# 绘制拟合后的连续曲线
plt.plot(x, result.best_fit, 'k-', linewidth=2, label='Combined Lorentzian Fit')
plt.legend()
plt.show()

4. 额外调试技巧

如果还是出现警告,可以打印所有参数的拟合结果,检查是否有异常值:

result.params.pretty_print()

如果某个参数的stderr是NaN,说明这个参数可能不需要拟合(可以固定),或者初始值设置得太不合理,需要调整初始值或边界。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:03:47