使用curve_fit进行多高斯拟合时出现'x0'不可行错误的求助
多高斯分解中curve_fit报
ValueError: 'x0' is infeasible的解决方法 问题背景
使用scipy的curve_fit对光谱数据进行3个高斯峰分解,未设置边界时代码可运行,但拟合结果不符合预期(前两个峰振幅差异大、峰位偏右)。添加边界约束峰位后,出现ValueError: 'x0' is infeasible错误。
错误原因
边界参数的顺序与初始参数p0不匹配,且初始参数落在边界范围外:
p0的参数顺序为:[amp1, cen1, sig1, amp2, cen2, sig2, amp3, cen3, sig3](振幅、峰中心、标准差依次对应每个高斯峰)- 原代码中
bounds的设置错误地将峰中心的约束值赋值给了振幅的边界,导致初始参数amp1=100远低于设置的振幅下限400,初始参数不在可行域内,触发报错。 - 同时,标准差
sig作为高斯分布的参数必须为正数,原代码未对其设置合理下限,可能导致拟合过程出现无意义的负数标准差。
解决方案
- 修正
bounds的参数顺序:严格对应p0的参数顺序,分别对每个参数设置合理边界:- 振幅(
amp1/amp2/amp3):必须为正数,下限设为0 - 峰中心(
cen1/cen2/cen3):按需求设置范围(如cen1:400-470、cen2:500-600、cen3:650-900) - 标准差(
sig1/sig2/sig3):必须为正数,下限设为极小值(如1e-6)避免出现0或负数
- 振幅(
- 调整初始参数
p0:将前两个峰的振幅设为更接近的值,帮助拟合收敛到符合预期的结果
修正后的代码示例
# 调整初始参数,让前两个峰振幅更接近 amp1 = 70 cen1 = 430 sig1 = 15 amp2 = 65 cen2 = 530 sig2 = 10 amp3 = 20 cen3 = 760 sig3 = 5 p0 = [amp1, cen1, sig1, amp2, cen2, sig2, amp3, cen3, sig3] # 修正边界参数顺序,对应p0的每个参数 lower_bounds = [0, 400, 1e-6, 0, 500, 1e-6, 0, 650, 1e-6] upper_bounds = [np.inf, 470, np.inf, np.inf, 600, np.inf, np.inf, 900, np.inf] # 调用curve_fit popt, pcov = curve_fit(three_gaussian, x, y, p0, bounds=(lower_bounds, upper_bounds))
额外提示
- 若拟合仍不稳定,可尝试指定
method='dogbox',该方法在边界约束场景下的收敛表现更稳定 - 拟合前可绘制原始数据与初始参数对应的高斯曲线,验证初始设置是否合理,再启动拟合流程
内容的提问来源于stack exchange,提问作者kngo
相关产品推荐
相关产品推荐

