[SciPy-user] scipy.optimize.leastsq col_deriv strangeness w/ data fit

John Hunter jdhunter at ace.bsd.uchicago.edu
Mon Apr 21 14:55:09 EDT 2003


I am using leastsq to do a best fit to a simple exponential function.
In my test script, I find that if I use col_deriv=0, I get a different
answer than I get if I do a col_deriv=1 with the err func returning
the transposed jacobian.  When I compare the true parameters with the
best fit parameters, the correct answer is with col_deriv=1 but not
with col_deriv=0.  Am I misusing this parameter or is something amiss?

In the data fitting problem, x is the independent variable with
parameters parsTrue.  I create the data values by assuming they are 

  data = func(pars) + noise

Here is the test script that works, to fit the data to 

where func(pars) is a*exp(alpha*x) + k


To get the best fit params, I minimize over pars

  data - func(pars)

------------------------------------------------------------
from scipy import exp, arange, zeros, Float, ones
from RandomArray import normal
from scipy.optimize import leastsq

parsTrue = 2.0, -.76, 0.1   # a, alpha, k
x = arange(0, 4, 0.001)

def func(pars):
    a, alpha, k = pars
    return a*exp(alpha*x) + k

def errfunc(pars):
    return data - func(pars)  #return the error


def deriv_errfunc(pars):
    'The Jacobian of the errfunc is -Jacobian of the func'

    a, alpha, k = pars
    J = zeros( (3,len(x)), Float)  # init the Jacobian only once
    #deriv with respect to a
    J[0,:] = -exp(alpha*x)

    #deriv with respect to alpha
    J[1,:] = -x*a*exp(alpha*x)

    #deriv with respect to k
    J[2,:] = -ones((len(x),), Float) # this is indep of k
    return J


# some pseudo data; add some noise
data = func(parsTrue) + normal(0.0, 0.1, x.shape)


guess = 1.0, -.4, 0.0   # the intial guess of the params

best, info, ier, mesg = leastsq(errfunc, guess,
                                full_output=1,
                                Dfun=deriv_errfunc,
                                col_deriv=1,
                                )

print 'true', parsTrue
print 'best', best

------------------------------------------------------------
This returns best fit params
true (2.0, -0.76000000000000001, 0.10000000000000001)
best [ 2.00487303 -0.74859602  0.09035577]



However, If I replace the deriv_errfunc with row derivs, manually
transposing the jacobian at creation time

def deriv_errfunc(pars):
    'The Jacobian of the errfunc is -Jacobian of the func'

    a, alpha, k = pars
    J = zeros( (len(x),3), Float)  # init the Jacobian only once

    # deriv with respect to a
    J[:,0] = -exp(alpha*x)

    # deriv with respect to alpha
    J[:,1] = -x*a*exp(alpha*x)

    # deriv with respect to k
    J[:,2] = -ones((len(x),), Float) 
    return J


and 

best, info, ier, mesg = leastsq(errfunc, guess,
                                full_output=1,
                                Dfun=deriv_errfunc,
                                col_deriv=0,
                                )
The fit is poor, eg, 

true (2.0, -0.76000000000000001, 0.10000000000000001)
best [ 1.13708025 -0.40303463  0.1669024 ]


With col_deriv=0 sometimes the solution is found and sometimes not
depending on the run, but it is consistently around the values
reported above (ie, wrong).  With col_deriv=1, though, the solution is
always found and is correct.


Suggestions?

John Hunter



More information about the SciPy-User mailing list