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':
Then I get the error message of:
ValueError: Inconsistent shapes between bounds and
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()
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!