Python 在曲线拟合中固定拟合参数

Python 在曲线拟合中固定拟合参数,python,scipy,curve-fitting,Python,Scipy,Curve Fitting,我有一个函数virtual,它描述了一个物理过程,我想把它应用到一个数据集x\u interpolate,y\u interpolate。该函数是洛伦兹峰值函数的一种形式,我有一些用户给定的初始值,除了我使用峰值查找算法找到的f_peak(峰值位置)。除偏移量外,所有拟合参数都应为正值,因此我相应地设置了bounds_I def Imaginary(freq, alpha, res, Ms, off): numerator = (2*alpha*freq*res**2) deno

我有一个函数
virtual
,它描述了一个物理过程,我想把它应用到一个数据集
x\u interpolate,y\u interpolate
。该函数是洛伦兹峰值函数的一种形式,我有一些用户给定的初始值,除了我使用峰值查找算法找到的
f_peak
(峰值位置)。除偏移量外,所有拟合参数都应为正值,因此我相应地设置了
bounds_I

def Imaginary(freq, alpha, res, Ms, off):
    numerator = (2*alpha*freq*res**2)
    denominator = (4*(alpha*res*freq)**2) + (res**2 - freq**2)**2
    Im = Ms*(numerator/denominator) + off
    return Im

pI = np.array([alpha_init, f_peak, Ms_init, 0])

bounds_I = ([0,0,0,0, -np.inf], [np.inf,np.inf,np.inf, np.inf])

poptI, pcovI = curve_fit(Imaginary, x_interpolate, y_interpolate, pI, bounds=bounds_I)
在某些情况下,我希望在拟合过程中保持参数
f_peak
固定。我尝试了一个简单的解决方案,将
bounds\u I
更改为:

bounds_I = ([0,f_peak+0.001,0,0, -np.inf], [np.inf,f_peak-0.001,np.inf, np.inf])

由于很多原因,这并不是一个最佳的方法,所以我想知道是否有一个更像蟒蛇的方法?感谢您的帮助

如果某个参数是固定的,则它实际上不是一个参数,因此应将其从参数列表中删除。定义一个将该参数替换为固定值的模型,并进行拟合。下面的示例为简洁起见进行了简化,并且是独立的:

x = np.arange(10)
y = np.sqrt(x)    
def parabola(x, a, b, c):
  return a*x**2 + b*x + c

fit1 = curve_fit(parabola, x, y)  #  [-0.02989396,  0.56204598,  0.25337086]
b_fixed = 0.5
fit2 = curve_fit(lambda x, a, c: parabola(x, a, b_fixed, c), x, y) 
第二次调用fit返回
[-0.02350478,0.35048631]
,这是a和c的最佳值。b的值固定在0.5

当然,参数应该从初始向量pI和边界中移除

您可能会发现lmfit()很有帮助。该库为scipy优化例程添加了一个更高级别的接口,旨在为优化和曲线拟合提供更具python风格的方法。例如,它使用参数对象来允许设置边界和固定参数,而无需修改目标或模型函数。对于曲线拟合,它定义了可以使用的高级模型函数

例如,您可以使用编写时使用的
虚构的
函数

from lmfit import Model
lmodel = Model(Imaginary)
然后创建参数(lmfit将根据您的函数签名命名参数对象),提供初始值:

params = lmodel.make_params(alpha=alpha_init, res=f_peak, Ms=Ms_init, off=0)
默认情况下,所有参数都是未绑定的,并且在拟合中会有所不同,但您可以修改这些属性(无需重写模型函数):

您可以将一个(或多个)参数设置为不随配合变化,如下所示:

params['res'].vary = False
需要明确的是:这不需要修改模型函数,使其更容易修改,因为它是固定的,可能会施加什么边界,等等

然后使用模型和以下参数执行拟合:

result = lmodel.fit(y_interpolate, params, freq=x_interpolate)
您可以通过以下方式获得拟合统计信息、最佳拟合值和参数不确定性的报告:

print(result.fit_report())
最佳拟合参数将保存在
result.params

FWIW、lmfit还有许多常见形式的内置模型,包括洛伦兹和常数偏移。因此,您可以将此模型构建为

from lmfit.models import LorentzianModel, ConstantModel

mymodel = LorentzianModel(prefix='l_') + ConstantModel()

params = mymodel.make_params()
其参数名为
l_振幅
l_中心
l_西格玛
,和
c
(其中
c
为常数),模型将使用名称
x
作为自变量(您的
频率
)。当您可能希望更改峰值或背景的函数形式,或将多个峰值拟合到光谱时,此方法会变得非常方便

from lmfit.models import LorentzianModel, ConstantModel

mymodel = LorentzianModel(prefix='l_') + ConstantModel()

params = mymodel.make_params()