尝试用边界进行曲线拟合时,获得“x0”是不可行的错误

问题描述 投票:0回答:1

我正在尝试对我进行的光谱测量进行多高斯解构,但我得到了

ValueError: 'x0' is infeasible
。我正在使用
curve_fit
并且我试图将我的测量结果分解为 3 个高斯。这是我的代码:

import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
directory=r"C:\Users\jh\data"
filename = "test(0,1).txt"
filepath = os.path.join(directory, filename)
data = pd.read_csv(filepath, delimiter = "\t")

x = data['Wavelength (nm)']
y = data['Absorbance']
#Gaussian 1
amp1 = 100
cen1 = 450
sig1 = 15

#Gaussian 2
amp2 = 50
cen2 = 550
sig2 = 10

#Gaussian 3
amp3 = 20
cen3 = 760
sig3 = 5

p0 = [amp1, cen1, sig1, amp2, cen2, sig2, amp3, cen3, sig3]
def gaussian(x, amp, cen, sig):
    gau = amp*(1/(sig*(np.sqrt(2*np.pi))))*(np.exp((-1/2)*(((x-cen)/sig)**2)))
    return gau

def three_gaussian(x, amp1, cen1, sig1, amp2, cen2, sig2, amp3, cen3, sig3): #Amp: Amplitude, Cen: Center, Sig: Sigma
    gau1 = amp1*(1/(sig1*(np.sqrt(2*np.pi))))*(np.exp((-1/2)*(((x-cen1)/sig1)**2)))
    gau2 = amp2*(1/(sig2*(np.sqrt(2*np.pi))))*(np.exp((-1/2)*(((x-cen2)/sig2)**2)))
    gau3 = amp3*(1/(sig3*(np.sqrt(2*np.pi))))*(np.exp((-1/2)*(((x-cen3)/sig3)**2)))
    return gau1 + gau2 + gau3
popt, pcov = curve_fit(three_gaussian, x, y, p0, bounds = ((400, -np.inf, -np.inf, 500, -np.inf, -np.inf, 650, -np.inf, -np.inf), (470, np.inf, np.inf, 600,  np.inf, np.inf, 900,  np.inf, np.inf)))

RRa_pars = popt[0:3]
RRe_pars = popt[3:6]
Pol_pars = popt[6:9]

RRa = gaussian(x, *RRa_pars)
RRe = gaussian(x, *RRe_pars)
Pol = gaussian(x, *Pol_pars)

我确信问题出在

curve_fit
电话中的这一行:

popt = curve_fit(three_gaussian, x, y, p0, bounds = ((400, -np.inf, -np.inf, 500, -np.inf, -np.inf, 650, -np.inf, -np.inf), (470, np.inf, np.inf, 600,  np.inf, np.inf, 900,  np.inf, np.inf)))

我之前无限制地尝试过这段代码并且它可以工作,但是该模型与我的预期不准确。因此,我引入了边界来尝试将中心限制在我期望的位置。这就是引入

ValueError: 'x0' is infeasible
的原因。这就是没有界限的拟合的样子:

enter image description here

拟合良好,但两个高斯函数的幅度应该更接近,并且应该更左移。 (我忽略了这张图片中的最后一个高斯,因为它不是有问题的)。

我不太确定如何解决这个问题。

python curve-fitting scipy-optimize
1个回答
0
投票

当您提供边界和初始猜测时,初始猜测必须满足边界,否则初始猜测被认为是“不可行的”(这只是说它不满足约束的另一种方式)。请考虑文档中

scipy.optimize.curve_fit
示例的修改版本。

import numpy as np
from scipy.optimize import curve_fit

def func(x, a, b, c):
    return a * np.exp(-b * x) + c

xdata = np.linspace(0, 4, 50)

rng = np.random.default_rng(42)
y_noise = 0.2*rng.normal(size=xdata.size)
ydata = func(xdata, 2.5, 1.3, 0.5) + y_noise

如果我们这样称呼曲线拟合:

popt, pcov = curve_fit(func, xdata, ydata, p0=(2., 0.6, 0.2), bounds=(0, [3., 2., 1.]))

没有任何问题,因为最初的猜测满足约束。

但是如果我们这样称呼它:

popt, pcov = curve_fit(func, xdata, ydata, p0=(4., 0.6, 0.2), bounds=(0, [3., 2., 1.]))

我们得到

ValueError: 'x0' is infeasible
,因为
a
初始猜测不在范围内。

© www.soinside.com 2019 - 2024. All rights reserved.