steve
steve

Reputation: 25

curve fitting with scipy curvefit in python

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

Answers (1)

David Kretch
David Kretch

Reputation: 390

  1. 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.
  2. 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

Related Questions