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

SciPy curve_fit拟合洛伦兹分布无法偏移峰值问题排查

异常根本原因

问题来自接口使用错误叠加数值尺度隐患:

  1. curve_fit参数顺序传反:scipy.optimize.curve_fit的固定调用格式是curve_fit(拟合函数, 自变量x数据, 因变量y数据, ...),你的代码里写的是curve_fit(lorentzian, test_data, frequencies, ...),把洛伦兹输出的幅值数据(本应是因变量y)当成了自变量x,把频率数组(本应是自变量x)当成了要拟合的因变量y,拟合目标和你定义的洛伦兹函数完全不匹配——相当于要让模型学会「输入洛伦兹幅值返回对应频率」,而这个映射本身是一对多的非单值函数,优化器根本找不到有效的梯度下降方向,所以参数从始至终停在初始猜测值不动,自然无法估计协方差,返回全inf的协方差矩阵。
  2. 数值尺度风险:你的频率参数在1e9量级,线宽gamma在1.5e7量级,不同参数的数值差了2个数量级,雅可比矩阵计算时很容易出现浮点精度截断问题,哪怕参数顺序正确,在有噪声的实测场景下也可能出现收敛异常。
修复方案
  • 首先修正curve_fit的参数传入顺序,把自变量frequencies放在第二个参数位置,因变量test_data放在第三个参数位置,修正后的调用语句为:
popt, pcov = curve_fit(lorentzian, frequencies, test_data, maxfev = 100000, p0 = guess)
  • 对于你当前生成的无噪声理想数据,只修正参数顺序即可得到完全准确的拟合结果,拟合参数会和你设定的fake参数完全一致,不会再报协方差估计失败的警告。
  • 如果后续要拟合带噪声的实测数据,建议先对频率轴做尺度缩放,比如将所有频率值减去标称中心频率5e9,把自变量范围压缩到±5e7区间,拟合完成后再给中心频率参数加回5e9即可,能大幅提升数值稳定性,避免大数值带来的精度问题。
修正后的完整测试代码
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit

def lorentzian(freq, gamma, center_freq, amplitude):
    return amplitude * gamma**2 / ( gamma**2 + ( freq - center_freq )**2) + 1

frequencies = np.arange(4.95e9, 5.05e9, 0.1e9/1000)

guess = [15000000, 4.997e9, 28]
fake = [15000000, 5.02e9, 28]
test_data = lorentzian(frequencies, *fake)
# 修正参数顺序
popt, pcov = curve_fit(lorentzian, frequencies, test_data, maxfev = 100000, p0 = guess)
fit_lorentzian = lorentzian(frequencies, *popt)
plt.plot(frequencies, test_data, label='Ideal data')
plt.plot(frequencies, fit_lorentzian, linestyle='--', label='Fit result')
plt.legend()
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:45:36