You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

双高斯峰Python拟合失败求助:结果异常、pcov值为无穷

Python双高斯峰拟合失败排查

我尝试用Python对数据进行双高斯峰拟合,但结果明显错误。参考了多种写法都无法成功拟合,尝试均值理论也没有改善。用LabVIEW能完成拟合,但Python实现失败,希望排查错误。怀疑拟合参数popt或边界设置存在问题,且发现pcov值为无穷,这十分反常。

原代码

import numpy as np
data = np.loadtxt('C:/Users/user/Desktop/sheet1 test.txt', delimiter=',')
print(data.shape)
print(data.dtype)
import matplotlib.pyplot as plt
x = data[:, 0]  
y = data[:, 1]  

#fitting function
from scipy.optimize import curve_fit
#individual peak
def gauss(x,a,w,p,c):
    #C = 0
    fun_val = 0 + ((a/1.253*w)*np.exp(-2*((x-p)**2/w**2)))
    return fun_val

#double peak
def d_gauss(x, a1, p1,a2, p2):    
    #w1 = 0.049
    #w2 = 0.029
    #c1 = c2 = 0
    fun_val1 = 0 + ((a1/1.253*0.049)*np.exp(-2*((x-p1)**2/0.049**2)))
    fun_val2 = 0 + ((a2/1.253*0.029)*np.exp(-2*((x-p2)**2/0.029**2)))
    
    return fun_val1 + fun_val2 
initial_gauss_peak = [1.43896,186.097,  1.4743,393.263]
#bnd = ( (lower limit )  , ( upper limit ) )
bnd = ((1.4,10 ,1.45,100) , (1.5 ,1000 ,1.52,5000) ) 

#fitting
popt,pcov = curve_fit(d_gauss,x,y, p0 = initial_gauss_peak, bounds = bnd)

yfit = gauss(x, popt[0], popt[1] ,popt[2], popt[3])
yfit1 = gauss(x, popt[0], 0.049 ,popt[1], 0)
yfit2 = gauss(x, popt[2], 0.029 ,popt[3], 0)

plt.plot(x,y ,'o', label = 'data')
plt.plot(x,yfit1 , label = 'peak 1' , color = 'b')
plt.plot(x,yfit2 , label = 'peak 2' , color = 'c')
plt.plot(x ,yfit ,linewidth = 2, label = 'fit' , color = 'k')
plt.legend()

#plt.plot(x, y)
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.title('Scatter Plot')
plt.show()   

拟合结果图

拟合结果图


问题排查与修正建议

核心错误点

  1. 拟合与绘图参数不匹配:d_gauss的参数是a1,p1,a2,p2,但绘图时yfit调用gauss函数传入的参数顺序是popt[0], popt[1], popt[2], popt[3],而gauss需要的是a,w,p,c,完全对应错误,导致总拟合曲线完全偏离。
  2. 固定峰宽可能不符合数据实际:强行固定w1=0.049、w2=0.029,如果实际数据的峰宽和这个值偏差较大,会导致拟合无法收敛,出现pcov无穷的情况。
  3. 边界设置逻辑混乱:初始参数p1的初始值是186,但边界下限设为10、上限1000,范围过大,容易导致拟合算法迷失最优解。

修正后的代码示例

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

# 加载数据
data = np.loadtxt('C:/Users/user/Desktop/sheet1 test.txt', delimiter=',')
x = data[:, 0]  
y = data[:, 1]  

# 标准单个高斯峰函数(包含基线)
def gauss(x, amp, wid, pos, base):
    return base + (amp / (wid * np.sqrt(2 * np.pi))) * np.exp(-((x - pos)**2) / (2 * wid**2))

# 双高斯峰函数
def double_gauss(x, amp1, wid1, pos1, amp2, wid2, pos2, base):
    return gauss(x, amp1, wid1, pos1, 0) + gauss(x, amp2, wid2, pos2, 0) + base

# 初始参数:基于LabVIEW结果或数据估计
init_params = [1.44, 0.049, 186.1, 1.47, 0.029, 393.3, 0]
# 合理设置边界:根据数据范围限制参数
bounds = (
    [1.0, 0.01, 180, 1.0, 0.01, 390, -0.1],
    [2.0, 0.1, 190, 2.0, 0.05, 400, 0.1]
)

# 执行拟合
popt, pcov = curve_fit(double_gauss, x, y, p0=init_params, bounds=bounds)

# 计算各类拟合曲线
y_total = double_gauss(x, *popt)
y_peak1 = gauss(x, popt[0], popt[1], popt[2], 0)
y_peak2 = gauss(x, popt[3], popt[4], popt[5], 0)

# 绘图
plt.figure(figsize=(10, 6))
plt.plot(x, y, 'o', label='原始数据')
plt.plot(x, y_peak1, label='峰1拟合', color='b')
plt.plot(x, y_peak2, label='峰2拟合', color='c')
plt.plot(x, y_total, linewidth=2, label='总拟合曲线', color='k')
plt.xlabel('X轴')
plt.ylabel('Y轴')
plt.title('双高斯峰拟合结果')
plt.legend()
plt.show()

# 输出拟合参数
print("拟合参数:", popt)

关键优化点

  1. 统一函数逻辑:使用标准高斯分布公式,避免自定义系数带来的误差,同时加入基线参数,适配实际数据的偏移情况。
  2. 参数全可调:放开峰宽参数,让拟合算法自动寻找最优峰宽,避免强行固定带来的拟合偏差。
  3. 参数匹配与边界收紧:确保初始参数、边界、拟合函数的参数顺序完全一致,同时根据数据实际范围收紧边界,帮助算法快速收敛。

内容的提问来源于stack exchange,提问作者Weiyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 02:52:53