4

I want to fit a sigmoidal curve to some data. Since SageMath's included find_fit function failed, I'm trying to use scipy.optimize.curve_fit directly. It's not doing a very good job and the outcome is extremely sensitive to the initial guess, often getting stuck on it, so I'm trying to provide a Jacobian in the hope that this will help. What form does the Jacobian function need to take? Right now, my code is the following:

#Compute the Jacobian (using SageMath)
c=8
x4Sigmoid(x) = c*x^n/(h+x^n)
sigjac = jacobian(x4Sigmoid, [n,h]) 

from scipy.optimize import curve_fit
from numpy import inf, power

#Define sigmoid function as Python function
def sigmoid(x, n, h):
    return 8*power(x,n)/(h+power(x,n))

def jacfun(x, *args):
    h,n = args[0]
    return sigjac(x,h=h,n=n)

#Separate x and y values of data
x4xData = [val[0] for val in x4ciscoperchRelAbundanceData]
x4yData = [val[1] for val in x4ciscoperchRelAbundanceData]

#Do the fitting
popt, pcov = curve_fit(sigmoid, x4xData, x4yData, p0=[3,4], bounds = ([1, 0], [inf, inf]), jac=jacfun)
show(popt)

This produces the error message ValueError: too many values to unpack. How do I give SciPy a Jacobian it can use? Or should I try something else?

jaia
  • 304
  • 1
  • 2
  • 8
  • Try `def jacfun(x, n, h):`, and remove `h,n = args[0]`. – Warren Weckesser Jun 20 '17 at 00:01
  • @WarrenWeckesser That's what I originally did, but curve_fit appeared to insist on an unpacked list. – jaia Jun 20 '17 at 00:03
  • 1
    I just tried an example. If you define it with the signature `def jacfun(x, h, n)`, then the array returned by `jacfun(x, h, n)` should have shape `x.shape + (2,)`. – Warren Weckesser Jun 20 '17 at 00:45
  • Wait, by x, do you mean the list of x values? I was using it to refer to the symbolic x in Sage. – jaia Jun 21 '17 at 00:02
  • @WarrenWeckesser Just doing ``def jacfun(x, h, n): return sigjac(x,h=h,n=n)`` gives ``TypeError: jacfun() takes exactly 3 arguments (4 given)`` – jaia Jun 26 '17 at 21:38

0 Answers0