Home > other >  Failing to pass a tuple of initial parameters into scipy.optimize curve_fit
Failing to pass a tuple of initial parameters into scipy.optimize curve_fit

Time:01-25

I want to fit a sum of a polynomial and a sine to a data set. I do not manage to pass a set of initial values for the coefficients (initial guess) into the function. I know that the asterisk (*) packs the variable.

I define the function

import pandas as pd
import numpy as np
from numpy.polynomial import Polynomial as P

def func(x,*A):
    A=A[0]  # to get the values only
    polynom=P(A[0:-3]) # all but the last three coefficients go into the polynomial
    sine=A[-3]*np.sin(A[-2]*(x-A[-1])) # the last three coefficients are for the sine
    y=polynom(x) sine # sum up both
    return y

Let's take some test values:

P0=(1,2,3,4,5,6,7,8,9,10,11)

The call of curve_fit fails:

coefs_scipy,pcov = sio.curve_fit(func,df.length,df.s,p0=P0)

where df is a pandas dataframe, the columns length and s containing the x and y values respectively.

The last error is

\AppData\Local\Temp/ipykernel_16648/911748954.py in func(x, *A)
     29 def func(x,*A):
     30     A=A[0]  # to get the values only
---> 31     polynom=P(A[0:-3]) # all but the last three coefficients go into the polynomial
     32     sine=A[-3]*np.sin(A[-2]*(x-A[-1])) # the last three coefficients are for the sine
     33     y=polynom(x) sine # sum up both

IndexError: invalid index to scalar variable.

indicating that it is not possible to extract [0:-3] from a scalar. Though A is not a scalar I assume

Astonishingly, when I just call the function with func(1,P0) it works.

What is wrong?

CodePudding user response:

The curve_fit function internally calls the target function like

func(x, *P0)

That means all the values in the P0 tuple are expanded into positional arguments to the function.

The function declaration

def func(x, *A):
    ...

collects all these positional arguments into A. So A is a tuple containing all the values and not a tuple of tuples.

To solve your problem, you should remove the

A=A[0]

line and change the direct call to the function to

func(1, *P0)
  •  Tags:  
  • Related