Scipy curve_fit无法拟合高斯函数问题求助
拟合高斯数据失效的问题排查
问题描述
我用以下代码生成高斯数据:
import numpy as np import pandas as pd from scipy.optimize import curve_fit import matplotlib.pyplot as plt x_array = np.linspace(0,0.5,100) mu = 0.25 # Mean sigma = 0.1 # Standard deviation y_array_gauss = (1 / (sigma * np.sqrt(2 * np.pi))) * np.exp(-0.5 * ((x_array - mu) / sigma) ** 2) y_array_gauss = y_array_gauss * (1.3 - 1.1) + 1.1 df = pd.DataFrame({'Time(s)': x_array, 'CH1(V)': y_array_gauss})
随后用自定义拟合函数fit2和高斯模型gauss2拟合:
def fit2(data, func, fit_init_guess, fit_bounds): fig, ax = plt.subplots(figsize = (20,6), facecolor='w') best_vals, covar = curve_fit(func, data['Time(s)'],data['CH1(V)'],p0 = fit_init_guess, bounds=fit_bounds) print(best_vals,' ', covar) ax.plot(data['Time(s)'], data['CH1(V)'], '-') ax.plot(data['Time(s)'], func(data['Time(s)'], *best_vals),'r-',label='Fit:B+A*e^((-(delta_2)^2)/(2*gamma^2)) \n B=%5.4f, A=%5.4f, gamma=%5.6f, t_0=%5.6f,' % tuple(best_vals)) plt.legend(loc='lower right') return None def gauss2(B, A, delta, gamma, t_0): delta_2 = delta - t_0 return B+A*np.exp((-(delta_2)**2)/(2*gamma**2)) fitInitGuess = [1.2, 1.9, 0.25, 0.25] fitBounds=((1.1, 0, 0, 0),(1.3, 2.5, 0.5, 0.5)) fit2(df, gauss2, fitInitGuess, fitBounds)
但拟合效果极差,初始猜测和边界看似合理,求排查原因。
核心失效原因
1. 拟合模型完全脱离自变量
你的gauss2函数存在致命错误:它没有将拟合的自变量x(即Time(s))作为参数传入,而是用delta - t_0这个固定值计算指数项,导致模型输出是常数,完全不随时间变化,自然无法拟合随x变化的高斯曲线。
正确的高斯模型需要绑定自变量x,且公式要匹配数据生成逻辑:
def gauss2(x, B, A, mu, sigma): # 对应生成数据的公式:B + A * exp( -0.5*((x - mu)/sigma)^2 ) return B + A * np.exp(-0.5 * ((x - mu)/sigma)**2)
2. 参数顺序与curve_fit规则冲突
curve_fit要求拟合函数的第一个参数必须是自变量x,但你定义的gauss2第一个参数是B,导致参数传递完全错位,初始猜测和边界的数值根本对应不到正确的参数上。
3. 初始猜测数值偏差过大
生成数据中A的实际值为:
A_actual = (1.3 - 1.1) / (sigma * np.sqrt(2 * np.pi)) ≈ 0.7979
而你设置的初始猜测fitInitGuess中A为1.9,偏差超过100%,会干扰拟合算法的收敛方向。
修正方案
1. 调整模型与参数顺序
替换gauss2为正确的模型,同时修正初始猜测和边界:
def gauss2(x, B, A, mu, sigma): return B + A * np.exp(-0.5 * ((x - mu)/sigma)**2) # 匹配实际数据的初始猜测:B≈1.1,A≈0.8,mu=0.25,sigma=0.1 fitInitGuess = [1.15, 0.8, 0.25, 0.1] fitBounds=((1.1, 0, 0, 0.05),(1.3, 1.0, 0.5, 0.2))
2. 更新拟合函数的图例标注
在fit2中修改图例的参数对应关系:
ax.plot(data['Time(s)'], func(data['Time(s)'], *best_vals),'r-', label='Fit: B + A*exp(-0.5*((x-mu)/sigma)^2) \n B=%5.4f, A=%5.4f, mu=%5.6f, sigma=%5.6f' % tuple(best_vals))
修正后,curve_fit会输出接近真实值的参数,拟合曲线与原始数据几乎重合。
内容的提问来源于stack exchange,提问作者GMML
相关产品推荐
相关产品推荐

