Scipy中曲线拟合向量函数

2024-05-15 20:38:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我想用Scipy的^{}(或者更合适的方法,如果有的话)来匹配向量输出的函数。例如,考虑以下函数:

import numpy as np
def fmodel(x, a, b):
    return np.vstack([a*np.sin(b*x), a*x**2 - b*x, a*np.exp(b/x)])

每个组件都是一个不同的函数,但它们共享我希望拟合的参数。理想情况下,我会这样做:

^{pr2}$

但是curve_fit不能与向量输出的函数一起工作,并且抛出一个错误Result from function call is not a proper array of floats.。相反,我所做的是将输出平铺如下:

def fmodel_flat(x, a, b):
    return fmodel(x[0:len(x)/3], a, b).flatten()

popt, pcov = curve_fit(f=fmodel_flat, xdata=np.tile(x, 3),
                       ydata=y_noisy.flatten(), p0=[0.3, 0.1])

这很管用。如果不是向量函数,而是使用不同的输入拟合多个函数,但这些函数共享模型参数,那么我可以同时连接输入和输出。在

有没有更合适的方法来拟合向量函数与Scipy或其他模块?对我来说,一个主要的考虑因素是效率——实际要匹配的函数要复杂得多,并且要花费一些时间,所以如果这种curve_fit的使用被破坏并导致过多的运行时,我想知道我应该怎么做。在


Tags: 方法函数importnumpy参数returndefnp
2条回答

我觉得你做得很有效率。我将尝试研究实现并提出更量化的方法,但目前我的理由是这样的。在

您在曲线拟合期间所做的是优化参数(a,b),以便

res = sum_i |f(x_i; a,b)-y_i|^2

是最小的。我的意思是你有任意维度的数据点(x_i,y_i),两个参数(a,b),还有一个拟合模型,它近似于查询点x_i处的数据。在

曲线拟合算法从一个起始的(a,b)对开始,将其放入一个计算上述平方误差的黑盒中,并尝试产生一个产生较小误差的新(a',b')对。我的观点是,上面的错误实际上是拟合算法的一个黑匣子:拟合的配置空间仅仅由(a,b)参数定义。如果你想象一下如何实现一个简单的曲线拟合函数,你可以想象你尝试做,比如说,一个梯度下降,平方误差作为代价函数。在

现在,黑盒如何计算误差应该与拟合过程无关。很容易看出,x_i的维数与标量函数无关,因为不管你有1000个1d查询点,还是3d空间中10x10x10的网格。重要的是你有1000个点x_i,你需要从模型中计算f(x_i) ~ y_i。在

唯一需要进一步注意的是,对于向量值函数,误差的计算并非微不足道。在我看来,用向量值函数的2范数定义每个x_i点的误差是很好的。但是嘿:在这个例子中,x_i点的平方误差是

^{pr2}$

这意味着每个分量的平方误差是累积的。这就意味着你现在所做的是正确的:通过复制你的x_i点并单独考虑函数的每个组成部分,你的平方误差将精确地包含每个点的误差的2范数。在

所以我的观点是你所做的在数学上是正确的,我不希望拟合过程的任何行为取决于多元/向量值函数的处理方式。在

如果我可以直截了当地推荐我自己的包symfit,我认为它正是您所需要的。关于使用共享参数拟合的示例可以在docs中找到。在

上述具体问题将变成:

from symfit import variables, parameters, Model, Fit, sin, exp

x, y_1, y_2, y_3 = variables('x, y_1, y_2, y_3')
a, b = parameters('a, b')
a.value = 0.3
b.value = 0.1

model = Model({
    y_1: a * sin(b * x), 
    y_2: a * x**2 - b * x, 
    y_3: a * exp(b / x),
})

xdata = np.linspace(1, 20, 50)
ydata = model(x=xdata, a=0.1, b=0.5)
y_noisy = ydata + 0.2 * np.random.normal(size=(len(model), len(xdata)))

fit = Fit(model, x=xdata, y_1=y_noisy[0], y_2=y_noisy[1], y_3=y_noisy[2])
fit_result = fit.execute()

查看docs了解更多信息!在

相关问题 更多 >