Reputation: 25
I am trying to do some curve fitting. I have a measured curve which I believe would be my Y
data, and I'm attempting to fit it with a weighted sum of a number of other curves which I believe would be my X
data.
My latest attempt to try to accomplish this is below but I have several errors and I decided to ask if someone can help point out what I am doing wrong?
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)
Apologies as there will undoubtedly be errors everywhere in this, but hopefully my description of what I am trying to accomplish is clear
Thank you in advance
Upvotes: 0
Views: 1036
Reputation: 390
fitfunc
loops over the parameters of c
, but n
is actually the values of c
, not the indices. It is trying to run e.g. ctx = c[0.6]*xdata[:,0.6] + ctx
. fitfunc
uses the fixed, global c
, and not the parameters passed to it by curve_fit
. It should refer to params
, not c
.What you want instead is
def fitfunc(xdata, *params):
ctx = 0.0
for n in range(len(params)):
ctx = params[n]*xdata[:,n] + ctx
return ctx
We can see that it works by running it by itself with print(fitfunc(xdata, *c))
, which returns [ 0.3 2.1 1.2]
.
Note that the *c
in print(fitfunc(xdata, *c))
takes the elements of c
and passes them as separate arguments, instead of as a single array. This is equivalent to writing fitfunc(xdata, c[0], c[1])
.
As Stelios noted in the comments, this is matrix multiplication, xdata[:,0] * c[0] + xdata[:,1] * c[1]
. You can use np.matmul
, which is likely faster, as in:
def fitfunc(xdata, *params):
return np.matmul(xdata, params)
Upvotes: 1