2016-11-20 162 views
0

我正在尝试做一些曲线拟合。我有一个测量曲线,我相信这将是我的Y数据,我试图用一些其他曲线的加权和进行拟合,我相信这些曲线是我的X数据。python中的scipy curvefit曲线拟合

我最近试图做到这一点的尝试如下,但我有几个错误,我决定询问是否有人能帮助指出我做错了什么?

import numpy as np 
import scipy.optimize 

ydata = np.array([1.0, 7.0, 4.0]) 
xdata = np.array([[0.0, 1.0],[3.5, 0.0],[1.0, 2.0]]) 

def fitfunc(xdata, *params): 
    ctx = 0.0 
    for n in np.nditer(c): 
     ctx = c[n]*xdata[:,n] + ctx 
    return ctx 

# initial guesses for fitting parameters, answer for this simple example is 2.0, 1.0 
c = np.array([0.6, 0.3]) 

# fit data using SciPy's Levenberg-Marquart method 
nlfit, nlpcov = scipy.optimize.curve_fit(fitfunc, xdata, ydata, p0=[c], sigma=None) 

print(nlfit) 

道歉,因为无疑将是错误无处不在这一点,但我希望我的什么,我试图完成描述清楚

预先感谢您

+1

您确定您正在处理曲线拟合问题吗?看来你正试图将向量'ydata'逼近为两个向量'xdata [:,0]','xdata [:,1]'的线性组合,这本质上是一个线性代数问题。 – Stelios

回答

1
  1. fitfunc环路过来的参数的c,但n实际上是c的值,而不是指数。它试图运行例如ctx = c[0.6]*xdata[:,0.6] + ctx
  2. fitfunc使用固定的全局c,而不是curve_fit传递给它的参数。它应该参考params,而不是c

你想要什么,而不是为

def fitfunc(xdata, *params): 
    ctx = 0.0 
    for n in range(len(params)): 
     ctx = params[n]*xdata[:,n] + ctx 
    return ctx 

我们可以看到,它的工作原理是通过自身运行它与print(fitfunc(xdata, *c)),返回[ 0.3 2.1 1.2]

请注意,*cprint(fitfunc(xdata, *c))中取c的元素,并将它们作为单独的参数传递,而不是作为单个数组传递。这相当于编写了fitfunc(xdata, c[0], c[1])

正如Stelios在评论中指出的,这是矩阵乘法,xdata[:,0] * c[0] + xdata[:,1] * c[1]。您可以使用np.matmul,这可能更快,如下所示:

def fitfunc(xdata, *params): 
    return np.matmul(xdata, params) 
+0

谢谢你的回答。我确实怀疑我的问题的这部分是线性的。在此之前,我已经在Excel中使用了Solver,但有人确信我应该学习Python,它看起来非常强大。我的例子很简单,可能还有一些额外的操作,比如允许列向上或向下移动以获得最佳拟合,由于实际数据中的噪声和实验位移,可能会使其非线性?但我会一步一步来看看我能否先让这部分工作。再次感谢你,史蒂夫。 – steve

+0

这种特定的方法将始终是线性的,因为您拟合的函数是线性的 - y = b1 * x1 + b2 * x2。 [curve_fit文档](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html)有一个非线性函数的例子 - y = a * e ^( b * x)+ c。我建议查看数据的散点图,看看是否有明显的非线性。 – David

+0

再次感谢您,代码现在完全符合我的要求。我选择了使用矩阵乘法的更简单的fitfunc。一些建议表明,我应该看看使用线性代数的解决方案,所以我会阅读我如何用这种方法解决这类问题,而不是曲线拟合问题,因为这对我来说都是新的。我还将研究可能的方式,以便我可以允许我的xdata的列相对于另一个“上下滑动”,以便在该功能可以改善配合的情况下。 – steve