Python Gaussian curve fitting高斯函数拟合数据失败问题咨询
高斯拟合不生效问题修复
你的代码存在3类核心错误,修正后即可得到符合预期的拟合结果:
存在的问题
- 初始参数计算逻辑错误
- 计算加权均值、标准差时,分母应该是y值的总和,你错误使用了x序列长度
n=19,得到的初始值完全偏离数据真实分布 - 你计算的是方差值,高斯函数中参数sigma为标准差,缺少开平方步骤
- 你注释掉了
curve_fit的初始参数传入项,该函数默认所有参数初始值为1,对于你这份峰值约80、分布中心在x=9~10区间的数据,非常容易收敛到局部最优值甚至直接不收敛
- 计算加权均值、标准差时,分母应该是y值的总和,你错误使用了x序列长度
- 拟合结果绘图传参错误
生成拟合曲线时你给高斯函数传入的第一个参数是y,正确应该传入x轴序列,直接导致拟合曲线坐标完全错位,无法展示正确效果 - 注释的测试数据存在语法错误
被注释的测试y序列中0.215. 0.049部分用点号代替了分隔逗号,取消注释运行会直接触发语法报错
修正后可运行代码
import matplotlib.pyplot as plt from scipy.optimize import curve_fit from numpy import asarray as ar, exp import numpy as np x = ar(range(19)) y = ar([0, 0, 0, 0, 0, 0, 0.01955, 1.163025, 19.7159833333333, 81.3119708333334, 80.0329166666667, 19.3835833333333, 0.03378, 0, 0, 0, 0, 0, 0]) # 正确计算高斯初始参数 y_sum = np.sum(y) mean = np.sum(x * y) / y_sum sigma = np.sqrt(np.sum(y * (x - mean)**2) / y_sum) a0 = np.max(y) # 振幅初始值取y的最大值 def gaus(x, a, x0, sigma): return a * exp(-(x - x0)**2 / (2 * sigma**2)) # 传入合理初始参数保证收敛 popt, pcov = curve_fit(gaus, x, y, p0=[a0, mean, sigma]) # 绘图 plt.scatter(x, y, color='blue', label='raw data') plt.plot(x, y, color='blue', linestyle='-', linewidth=2) # 生成更密集的x点让拟合曲线更平滑 x_fit = np.linspace(x.min(), x.max(), 200) plt.plot(x_fit, gaus(x_fit, *popt), label='gaussian fit', color='red', linestyle='--', linewidth=2) plt.xlabel('No of Resets', fontsize=20) plt.ylabel('Frequency', fontsize=20) plt.legend(loc='upper right') plt.title('Gaussian Fit', fontsize=20) plt.show() # 输出拟合参数 print(f"拟合结果:振幅a={popt[0]:.2f}, 分布中心x0={popt[1]:.2f}, 标准差sigma={popt[2]:.2f}")
补充说明
你提供的这份数据本身非常接近理想高斯分布,修正后拟合优度R²会接近1,和原始数据匹配度很高。如果后续拟合带基线、非对称的高斯类数据,可以给curve_fit传入bounds参数限定各参数的取值范围,进一步降低收敛异常的概率。
内容的提问来源于stack exchange,提问作者HMM
相关产品推荐
相关产品推荐

