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

使用scipy.minimize拟合三高斯模型遇参数传递错误求助

解决scipy.minimize拟合多高斯函数的参数传递问题

嘿,我来帮你搞定这个问题!你遇到的错误核心是目标函数的参数结构和scipy.minimize的调用方式不匹配,还有几个其他小问题需要调整,咱们一步步来:

错误原因分析

  1. 错误的函数调用方式:你在minimize里传的是sumGauss(x, y),这会直接执行这个函数并把结果传给minimize,但minimize需要的是一个可调用的函数对象,而不是函数执行后的结果。这直接导致sumGauss执行时args为空,所以解包9个参数时失败。
  2. 目标函数参数顺序错误:scipy.minimize要求目标函数的第一个参数是待优化的参数数组,额外的数据集(比如x、y)需要通过args参数传递,而不是反过来。
  3. 目标函数返回值不对:你当前返回的是残差数组,但minimize默认需要一个标量值来最小化——我们通常会最小化残差的平方和(这样才是标准的拟合误差)。
  4. 错误使用了Rosenbrock函数的导数/海森矩阵:rosen_der和rosen_hess是专门给Rosenbrock测试函数用的,和你的高斯拟合完全不相关,不能直接用在这儿。

修正后的完整代码

import numpy
from matplotlib import pyplot
from scipy.optimize import minimize

# 实验数据
x = numpy.arange(0, 55)
y = [-0.00058032, -0.00063992, -0.00057869, -0.00058395, -0.00053528, -0.0002694, -0.0003716, -0.000284, 0.00104651, 0.00209935, 0.00360213, 0.00502779, 0.00625538, 0.00715873, 0.00753231, 0.00712235, 0.00689089, 0.0061677, 0.00544124, 0.00478251, 0.00487787, 0.00415067, 0.00368579, 0.00370327, 0.00323007, 0.0029862, 0.00250529, 0.00219493, 0.00212242, 0.00209026, 0.0020827, 0.00204044, 0.00218628, 0.00236552, 0.00245056, 0.00282404, 0.0031072, 0.00332862, 0.00351655, 0.00367349, 0.00387923, 0.00395812, 0.00388796, 0.00379902, 0.00369458, 0.00350222, 0.00337815, 0.0032241, 0.00306897, 0.00294152, 0.00276761, 0.00257586, 0.00231613, 0.00211727, 0.00190347]

# 目标函数:计算残差的平方和(最小化这个值)
def sumGauss(params, x, y):
    # params是待优化的参数数组,解包成各个高斯参数
    m1, m2, m3, s1, s2, s3, k1, k2, k3 = params
    # 计算三个高斯的和
    gauss_sum = (k1 * numpy.exp(-(x - m1)**2 / (2 * s1**2)) +
                 k2 * numpy.exp(-(x - m2)**2 / (2 * s2**2)) +
                 k3 * numpy.exp(-(x - m3)**2 / (2 * s3**2)))
    # 返回残差的平方和(这是我们要最小化的标量)
    return numpy.sum((gauss_sum - y)**2)

# 初始猜测值
initial_values = [15, 29, 43, 1, 1, 1, 0.007, 0.002, 0.004]
# 调整了初始的k值,更接近数据的峰值,有助于拟合收敛

# 调用minimize:第一个参数是目标函数,第二个是初始值,args传递额外的x和y
res = minimize(sumGauss, initial_values, args=(x, y), 
               method='L-BFGS-B',  # 换一个更适合曲线拟合的方法,不需要自定义jac/hess
               options={'gtol': 1e-8, 'disp': True})

# 打印拟合结果
print("拟合得到的参数:")
print(res.x)

# 绘制拟合结果
fit_y = (res.x[6] * numpy.exp(-(x - res.x[0])**2 / (2 * res.x[3]**2)) +
         res.x[7] * numpy.exp(-(x - res.x[1])**2 / (2 * res.x[4]**2)) +
         res.x[8] * numpy.exp(-(x - res.x[2])**2 / (2 * res.x[5]**2)))

pyplot.scatter(x, y, label='实验数据')
pyplot.plot(x, fit_y, 'r-', label='拟合曲线')
pyplot.legend()
pyplot.show()

关键调整点说明

  • 目标函数参数顺序:把待优化的params放在第一个位置,x和y作为后续参数,通过minimize的args=(x,y)传递给目标函数。
  • 返回残差平方和:这样minimize才有一个标量值可以最小化,符合拟合的需求。
  • 移除错误的jac/hess参数:我们用了L-BFGS-B方法,它会自动计算近似的导数,不需要手动指定(而且你之前用的Rosen函数的导数完全不匹配)。
  • 优化初始猜测值:调整了k1/k2/k3的初始值,更接近数据的实际峰值,能帮助拟合算法更快收敛。

运行结果说明

运行后你会看到拟合的参数输出,同时会弹出图像显示实验数据和拟合曲线的对比。如果拟合效果还不够理想,可以尝试调整初始值,或者换用其他minimize方法(比如'Nelder-Mead')。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:25:42