Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying bounds to specific variable during curve_fit (scipy) leads to an error

I am trying to apply bounds onto some of the parameters during curve fitting but I'm getting the following error message when I tried to do so:

ValueError: too many values to unpack

Doesn't each 2-tuple in the bound command corresponds to x0, k, lapse, guess in the sigmoidscaled function in my case respectively (Ie. corresponding to p0 too)?

I then tried playing around in hopes of trying to figure out how it works by reducing the bound command to the following to rid the 'too many values':

bounds=((-np.inf,np.inf), (0,1))

Then I get the error message of:

ValueError: Inconsistent shapes between bounds and x0.

What am I getting wrong here?

import pylab
from scipy.optimize import curve_fit
from matplotlib.pyplot import *

n = 20 #20 trials
ydata = [0/n, 9.0/n, 9.0/n, 14.0/n, 17.0/n] #Divided by n to fit to a plot of y =1
xdata = np.array([ 1.0, 2.0, 3.0, 4.0, 5.0])


#The scaled sigmoid function
def sigmoidscaled(x, x0, k, lapse, guess):
    F = (1 + np.exp(-k*(x-x0))) 
    z = guess + (1-guess-lapse)/F
    return z

p0=[1,1,0,0] 
popt, pcov = curve_fit(sigmoidscaled, xdata, ydata, p0, bounds=((-np.inf,np.inf), (-np.inf,np.inf), (0,1), (0,1))

#Start and End of x-axis, in spaces of n. The higher the n, the smoother the curve.
x = np.linspace(1,5,20)
#The sigmoid values along the y-axis, generated in relation to the x values and the 50% point.
y = sigmoidscaled(x, *popt)

pylab.plot(xdata, ydata, 'o', label='Psychometric Raw', color = 'blue')
pylab.plot(x,y, label='Psychometric Fit', color = 'blue')
#y axis range.
pylab.ylim(0, 1)
#Replace x-axis numbers as labels and y-axis numbers as percentage
xticks([1., 2., 3., 4., 5.], ['C1','CN2','N3','CN4','S5'])
yticks([0.0, 0.2, 0.4, 0.6, 0.8, 1.0], ['0%','20%','40%','60%','80%','100%'])
pylab.legend(loc='best')
xlabel('Conditions')
ylabel('% perceived more sin like')
pylab.show() 
like image 341
Ang Jit Wei Aaron Avatar asked May 06 '16 01:05

Ang Jit Wei Aaron


People also ask

How does curve_fit work SciPy?

The SciPy open source library provides the curve_fit() function for curve fitting via nonlinear least squares. The function takes the same input and output data as arguments, as well as the name of the mapping function to use. The mapping function must take examples of input data and some number of arguments.

What does curve_fit return?

My question is using scipy curve_fit it returns: "Optimal values for the parameters so that the sum of the squared error of f(xdata, *popt) - ydata is minimized".

What is PCOV in curve fit?

The returned parameter covariance matrix pcov is based on scaling sigma by a constant factor. This constant is set by demanding that the reduced chisq for the optimal parameters popt when using the scaled sigma equals unity. In other words, sigma is scaled to match the sample variance of the residuals after the fit.


1 Answers

The problem line is:

popt, pcov = curve_fit(sigmoidscaled, xdata, ydata, p0, bounds=((-np.inf,np.inf), (-np.inf,np.inf), (0,1), (0,1))

From the documentation, bounds needs to be a 2-tuple of array likes. So instead of specifying the lower and upper bound of each point, you need to specify the lower bound of each point in the first array-like followed by the upper bound of each point in the second array-like, like this:

popt, pcov = curve_fit(sigmoidscaled, xdata, ydata, p0, bounds=((-np.inf, -np.inf, 0, 0), (np.inf, np.inf, 1, 1)))

After this change, the plot popped right up!

like image 134
Matt Messersmith Avatar answered Oct 22 '22 11:10

Matt Messersmith