高斯曲线拟合遇exp溢出警告及拟合效果差的解决求助
解决高斯曲线拟合的溢出错误与拟合效果差问题
问题描述
运行高斯曲线拟合代码时出现RuntimeWarning: overflow encountered in exp,对应代码行是y = A*np.exp(-1*B*x**2),拟合生成的曲线效果极差。数据已归一化到1,推测是数值范围问题导致报错。原代码如下:
import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit def GaussFit(): xdata_raw = [0,24,22,20,18,16,14,12,10,8,6,4,2,-24,-22,-20,-18,-16,-14,-12,-10,-8,-6,-4,-2] ydata_raw =[0.398,0.061,0.066,0.076,0.095,0.115,0.148,0.183,0.211,0.270,0.330,0.361,0.391,0.061,0.066,0.076,0.095,0.115,0.148,0.183,0.211,0.270,0.330,0.361,0.391] y_norm = [] for i in range(len(ydata_raw)): temp = ydata_raw[i]/0.398 y_norm.append(temp) plt.plot(xdata_raw, y_norm, 'o') xdata = np.asarray(xdata_raw) ydata = np.asarray(y_norm) def Gauss(x, A, B): y = A*np.exp(-1*B*x**2) return y parameters, covariance = curve_fit(Gauss, xdata, ydata) fit_A = parameters[0] fit_B = parameters[1] fit_y = Gauss(xdata, fit_A, fit_B) plt.plot(xdata, ydata, 'o', label='data') plt.plot(xdata, fit_y, '-', label='fit') plt.grid(color='grey', linestyle='-', linewidth=0.25, alpha=0.5) plt.legend() plt.xlabel('Winkel der Auslenkung in °') plt.ylabel('Intensität [I]') plt.title('vertikale Ausrichtung') GaussFit()
问题原因
- 初始参数不合理:
curve_fit默认初始参数为[1, 1],当B=1时,x=24的平方是576,-B*x²=-576,exp(-576)几乎为0;若拟合过程中B变为负数,-B*x²会变成大正数,直接导致exp计算溢出。 - 无参数约束:未限制B的取值范围,拟合过程中可能出现负的B值,既引发溢出,又导致曲线形状完全偏离预期。
解决方案
1. 提供合理初始参数
根据归一化后的数据,峰值A接近1;通过x=24时的y值估算B≈0.003,设置初始参数p0=[1, 0.003],引导拟合收敛到正确方向。
2. 约束参数范围
用bounds参数限制A和B为非负数,彻底避免出现导致溢出的负B值。
3. 简化数据处理
用numpy数组操作替代循环,提升代码效率和可读性。
修改后的完整代码
import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit def GaussFit(): xdata_raw = [0,24,22,20,18,16,14,12,10,8,6,4,2,-24,-22,-20,-18,-16,-14,-12,-10,-8,-6,-4,-2] ydata_raw = [0.398,0.061,0.066,0.076,0.095,0.115,0.148,0.183,0.211,0.270,0.330,0.361,0.391,0.061,0.066,0.076,0.095,0.115,0.148,0.183,0.211,0.270,0.330,0.361,0.391] # 用numpy简化归一化操作 y_norm = np.array(ydata_raw) / 0.398 xdata = np.array(xdata_raw) ydata = y_norm def Gauss(x, A, B): return A * np.exp(-B * x**2) # 设置初始参数与参数约束范围 initial_params = [1, 0.003] param_bounds = ([0, 0], [np.inf, np.inf]) # 约束A、B均非负 parameters, covariance = curve_fit(Gauss, xdata, ydata, p0=initial_params, bounds=param_bounds) fit_A, fit_B = parameters fit_y = Gauss(xdata, fit_A, fit_B) plt.plot(xdata, ydata, 'o', label='data') plt.plot(xdata, fit_y, '-', label='fit') plt.grid(color='grey', linestyle='-', linewidth=0.25, alpha=0.5) plt.legend() plt.xlabel('Winkel der Auslenkung in °') plt.ylabel('Intensität [I]') plt.title('vertikale Ausrichtung') plt.show() GaussFit()
效果说明
修改后,curve_fit会从合理的初始值开始收敛,参数约束避免了溢出问题,拟合曲线会与数据点高度吻合。
内容的提问来源于stack exchange,提问作者Wolle_Wolle
相关产品推荐
相关产品推荐

