Scipy curve_fit设置bounds参数后返回初始猜测值的问题求助
解决scipy curve_fit添加bounds后返回初始猜测值的问题
问题背景
使用scipy的curve_fit拟合高斯+洛伦兹复合曲线时,仅设置初始猜测p0能得到合理结果,但添加bounds参数后,拟合结果始终停留在初始猜测值,与数据偏差较大。
拟合函数定义
import numpy as np from scipy.optimize import curve_fit def gaussian(x, a, x0, sig): return a * np.exp(-1/2 * (x - x0)**2 / sig**2) def lorentzian(x, a, b, c): return a*c**2/((x-b)**2+c**2) def decompose(x, z, n, b, *par): hb_n = gaussian(x, par[0], 4861.3*(1+z), n) hb_b = lorentzian(x, par[1], 4861.3*(1+z), b) return hb_b + hb_n
正常拟合代码(仅p0)
guess = [0.0001, 2, 10, 3e-16, 3e-16] p, c = curve_fit(decompose, wave, residual, guess)
异常情况(添加bounds)
guess = [0.0001, 2, 10, 3e-16, 3e-16] p, c = curve_fit(decompose, wave, residual, guess, bounds=([-0.001, 0, 0, 0, 0], [0.001, 10, 100, 1e-15, 1e-15]))
解决建议
1. 修正固定参数与拟合参数的传递逻辑
这是核心问题:curve_fit中,函数的非自变量参数如果是固定值,需要通过args传递,而非放入p0或bounds。你的decompose函数中,z, n, b是固定参数,只有*par对应的2个参数(高斯振幅、洛伦兹振幅)是待拟合参数,之前的代码把固定参数和拟合参数混在了一起,导致参数映射完全错误。
修正后的代码示例:
# 替换为你的实际固定参数值 fixed_z = ... fixed_n = ... fixed_b = ... # 仅保留待拟合的2个参数的初始猜测 guess = [3e-16, 3e-16] # 对应2个拟合参数的边界 bounds = ([0, 0], [1e-15, 1e-15]) # 通过args传递固定参数z, n, b p, c = curve_fit(decompose, wave, residual, p0=guess, bounds=bounds, args=(fixed_z, fixed_n, fixed_b))
2. 切换适配有约束优化的求解器
curve_fit默认的lm方法(Levenberg-Marquardt)对边界支持有限,建议切换为专门的有约束优化方法trf或dogbox:
p, c = curve_fit(decompose, wave, residual, p0=guess, bounds=bounds, args=(fixed_z, fixed_n, fixed_b), method='trf')
如果优化迭代次数不足,可增加max_nfev参数:
p, c = curve_fit(decompose, wave, residual, p0=guess, bounds=bounds, args=(fixed_z, fixed_n, fixed_b), method='trf', max_nfev=10000)
3. 检查边界的合理性
避免设置过于严格的边界,导致优化器无法在范围内找到更优解。可先放宽边界(比如将上限临时调大),验证是否能得到合理结果后,再逐步缩小边界范围。
4. 参数缩放提升数值稳定性
如果待拟合参数数量级差异过大(如部分参数为1e-16,部分为1e-3),会影响优化器的数值稳定性。可对小数量级参数进行缩放(如乘以1e16),拟合完成后再还原,或在拟合函数内做归一化处理。
5. 验证拟合函数逻辑
单独调用gaussian和lorentzian函数,传入固定参数,检查输出是否符合预期,确保复合函数的公式、中心波长计算等逻辑正确。
内容的提问来源于stack exchange,提问作者como
相关产品推荐
相关产品推荐

