如何无需手动缩放使用scipy curve_fit拟合量级差异大的数据?
无需手动缩放完成高斯拟合的解决方案
问题出在哪
直接用原始x拟合失败,是因为curve_fit默认给的初始参数[1,1,1]和实际数据的参数范围差得太远:
- x的取值在50到1000之间,但默认初始中心参数
b=1,导致x-b的数值极大,高斯函数的指数部分直接趋近于负无穷,输出几乎为0,优化器根本找不到正确的参数方向。
解决办法:给优化器一个靠谱的初始猜测
不用手动缩放x,只要给curve_fit传入符合数据范围的初始参数猜测(通过p0参数)就行。
修改后的完整代码
import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit x = np.array([954.57747687, 845.47601272, 746.69873108, 657.48101282, 577.09839969, 504.86539163, 440.13425151, 382.29381761, 330.7683239 , 285.01622822, 244.52904868, 208.83020828, 177.473888 , 150.04388862, 126.15250125, 105.4393871 , 87.57046634]) y = np.array([ 0.2, 0.5, 0.6, 1.4, 2.7, 4. , 5. , 6.2, 8.6, 10.3, 11.6, 12.4, 12.7, 12.4, 7.6, 3. , 0.8]) def gaussian(x, a, b, c): return a*np.exp(-np.power(x - b, 2)/(2*np.power(c, 2))) # 生成初始参数猜测: # a取y的最大值(高斯振幅接近y峰值) # b取y最大值对应的x(高斯中心在峰值位置) # c取x范围的1/4左右(先给个合理宽度) y_peak = np.max(y) x_at_peak = x[np.argmax(y)] initial_guess = [y_peak, x_at_peak, 200] # 传入初始猜测做拟合 pars, cov = curve_fit(gaussian, xdata=x, ydata=y, p0=initial_guess) print(pars) # 输出类似:[12.38265077 177.473888 118.26789203],和缩放x后的参数对应(c=118≈1.18*100) # 绘图验证(修正了原代码中plot的x、y顺序,和scatter对应) fig, axs = plt.subplots() axs.scatter(x, y, label='原始数据') axs.plot(x, gaussian(x, *pars), linewidth=2, linestyle='--', label='拟合曲线') axs.legend() plt.show()
额外技巧
如果初始猜测拿不准,还可以给参数加个取值范围约束(用bounds参数),进一步帮优化器收敛:
# 设定参数范围:a在0-15,b在x的最小值到最大值,c在0-500 param_bounds = ([0, np.min(x), 0], [15, np.max(x), 500]) pars, cov = curve_fit(gaussian, xdata=x, ydata=y, p0=initial_guess, bounds=param_bounds)
内容的提问来源于stack exchange,提问作者zxdawn
相关产品推荐
相关产品推荐

