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

关于lmfit的绝对值边界设置问题:拟合存在未定义区间的函数

关于lmfit的绝对值边界设置问题:拟合存在未定义区间的函数

兄弟,我太懂你这种拟合时碰到参数跨零踩坑的糟心了!你说的这个双向指数高斯函数,估计在gamma=0的时候是个奇点或者函数形式直接发生了突变,所以拟合算法在gamma接近0的时候很容易卡壳、发散或者出异常结果对吧?

我给你分享几个实用的解决思路,都是我自己踩过坑后摸索出来的:

  • 用“绝对值+符号参数”绕开零点
    这是最稳妥的方法,直接把gamma拆成两个参数,彻底避开gamma=0的区间:

    • 新增gamma_abs参数,设置它的下限为一个极小的正数(比如1e-6),确保它永远不会接近0;
    • 再新增gamma_sign参数,让它只负责控制正负,你可以把它的范围设为[-1, 1],或者直接强制它取+1/-1;
    • 最后在拟合函数里,把实际用的gamma定义为gamma_sign * gamma_abs。

    给你段示例代码参考:

    from lmfit import Model, Parameters
    import numpy as np
    
    def bidirectional_exp_gauss(x, center, amplitude, sigma, gamma_abs, gamma_sign):
        # 组合出实际的gamma参数
        gamma = gamma_sign * gamma_abs
        # 这里替换成你实际的双向指数高斯函数实现
        exp_term = np.exp(-((x - center)/sigma)**2 / 2)
        gamma_term = np.exp(gamma * (x - center)/sigma)
        return amplitude * exp_term * gamma_term
    
    # 初始化模型和参数
    model = Model(bidirectional_exp_gauss)
    params = Parameters()
    params.add('center', value=10, min=0)
    params.add('amplitude', value=5, min=0)
    params.add('sigma', value=2, min=1e-6)
    params.add('gamma_abs', value=0.3, min=1e-6)
    # gamma_sign控制正负,范围设为-1到1即可
    params.add('gamma_sign', value=1, min=-1, max=1, vary=True)
    
    # 执行拟合
    result = model.fit(your_y_data, params, x=your_x_data)
    print(result.fit_report())
    
  • 分两次拟合后选最优结果
    如果你觉得拆参数麻烦,也可以直接分两次拟合:一次把gamma限制为正数(下限设为1e-6),一次限制为负数(上限设为-1e-6),最后比较两次拟合的残差,选残差更小的那个结果。这种方法简单粗暴,但胜在直观,完全不会碰到零点的问题。

    示例代码如下:

    from lmfit import Model, Parameters
    import numpy as np
    
    # 先定义原始的拟合函数
    def bidirectional_exp_gauss(x, center, amplitude, sigma, gamma):
        exp_term = np.exp(-((x - center)/sigma)**2 / 2)
        gamma_term = np.exp(gamma * (x - center)/sigma)
        return amplitude * exp_term * gamma_term
    
    model = Model(bidirectional_exp_gauss)
    # 第一次拟合:gamma为正
    params_pos = Parameters()
    params_pos.add('center', value=10, min=0)
    params_pos.add('amplitude', value=5, min=0)
    params_pos.add('sigma', value=2, min=1e-6)
    params_pos.add('gamma', value=0.3, min=1e-6)
    result_pos = model.fit(your_y_data, params_pos, x=your_x_data)
    
    # 第二次拟合:gamma为负
    params_neg = Parameters()
    params_neg.add('center', value=10, min=0)
    params_neg.add('amplitude', value=5, min=0)
    params_neg.add('sigma', value=2, min=1e-6)
    params_neg.add('gamma', value=-0.3, max=-1e-6)
    result_neg = model.fit(your_y_data, params_neg, x=your_x_data)
    
    # 选残差小的作为最优结果
    best_result = result_pos if result_pos.chisqr < result_neg.chisqr else result_neg
    print(best_result.fit_report())
    

最后再提个小建议:不管用哪种方法,初始参数的设置都很关键!如果初始值离真实值太远,拟合很容易跑偏,最好先根据你的数据大致判断下gamma的正负,给个靠谱的初始值,拟合成功率会高很多。

备注:内容来源于stack exchange,提问作者Joshua Derrick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 17:14:37