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

如何从lmfit minimizer获取拟合参数的不确定性?

问题:lmfit拟合洛伦兹曲线后无法获取参数误差棒

使用lmfit拟合洛伦兹曲线,因参数边界限制无法直接使用scipy.optimize,拟合结果正常,但始终无法获取参数误差:res.covar返回None,res.errorbars为False,调用res.uvars触发AttributeError,res.params['parameter_name'].stderr也为None。已安装numdifftools,环境为lmfit 1.3.2、numdifftools 0.9.41、Python 3.11.7,拟合过程无警告。

拟合代码

def to_minimize(params, x, y, uncertainties=None):
    x0 = params["x0"]
    ampl0 = params["ampl0"]
    ampl = params["ampl"]
    sig = params["sig"]

    model = lorentzian(x, x0, ampl0, ampl, sig)
    if uncertainties is not None:
        return (y- model) / uncertainties
    else:
        return y - model


params = lmfit.Parameters()
params.add("x0", value=guess[0], min=guess[0] - 1000, max=guess[0] + 1000)
params.add("ampl0", value=guess[1], min=0)
params.add("ampl", value=guess[2], min=0)
params.add("sig", value=guess[3], min=0)

out = lmfit.minimize(to_minimize, params, args=(x_data, y_data))

拟合输出

Fit Result
Fit Statistics
fitting method  leastsq
# function evals    156
# data points   51201
# variables 4
chi-square  9.8949e-23
reduced chi-square  1.9327e-27
Akaike info crit.   -3149414.19
Bayesian info crit. -3149378.82
Parameters
name    value   initial value   min max vary
x0  2424682.92  2424725.9731872166  2423725.97  2425725.97  True
ampl0   1.6720e-13  1.6717888361052836e-13  0.00000000  inf True
ampl    1.2557e-12  1.2557626695414776e-12  0.00000000  inf True
sig 105.300229  4.296879768371582   0.00000000  inf True

解决办法

1. 强制计算协方差矩阵

默认leastsq方法在参数接近边界时不会自动计算误差,可手动触发计算:

# 方式1:拟合时直接指定计算协方差
out = lmfit.minimize(to_minimize, params, args=(x_data, y_data), calc_covar=True)

# 方式2:拟合后手动计算
out = lmfit.minimize(to_minimize, params, args=(x_data, y_data))
out.calc_covar()

若参数接近边界导致计算失败,可尝试用数值微分工具计算:

from lmfit.minimizer import Minimizer

minimizer = Minimizer(to_minimize, params, args=(x_data, y_data))
out = minimizer.leastsq(calc_covar=True)
# 若仍失败,强制使用numdifftools计算数值协方差
out.params.add_all_covars(minimizer.calc_covar(numdifftools=True))

2. 检查参数边界限制

从拟合结果看,ampl0和ampl的初始值与拟合值几乎一致,且接近下限0。如果参数被边界限制,协方差矩阵无法正常计算:

  • 尝试放宽参数下限(比如设为-1e-16而非严格0),允许参数在边界内小幅波动
  • 检查模型是否合理,是否存在参数冗余或过度约束

3. 手动计算参数不确定性

如果上述方法无效,可通过以下方式手动计算:

  • 参数扫描法:固定其他参数,逐个调整目标参数,找到使卡方值增加1(单参数95%置信区间对应卡方增加4)的参数范围
  • 蒙特卡洛模拟:在拟合结果基础上,给参数添加正态分布噪声,重复拟合多次,统计参数分布的标准差
  • 数值微分计算协方差:用numdifftools计算模型对参数的偏导数,结合残差推导协方差:
    import numdifftools as nd
    import numpy as np
    
    def model_func(params):
        return lorentzian(x_data, params[0], params[1], params[2], params[3])
    
    # 获取拟合后的参数值
    pvals = [out.params['x0'].value, out.params['ampl0'].value, 
             out.params['ampl'].value, out.params['sig'].value]
    # 计算雅可比矩阵
    jac = nd.Jacobian(model_func)(pvals)
    # 计算残差
    resids = y_data - model_func(pvals)
    # 推导协方差矩阵
    covar = np.linalg.inv(jac.T @ jac) * (np.sum(resids**2)/(len(y_data)-4))
    # 参数标准差为协方差矩阵对角线的平方根
    stderrs = np.sqrt(np.diag(covar))
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 17:49:52