Search code examples
scipycurve-fittingvalueerrorscipy-optimizequad

scipy.optimize.curve_fit ValueError: The truth value of an array with more than one element is ambiguous


I am trying to use scipy.optimize.curve_fit to fit a sigmoidal curve to my dataset but I get the following error:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "Y:\WORK\code\venv\lib\site-packages\scipy\optimize\minpack.py", line 784, in curve_fit
    res = leastsq(func, p0, Dfun=jac, full_output=1, **kwargs)
  File "Y:\WORK\code\venv\lib\site-packages\scipy\optimize\minpack.py", line 410, in leastsq
    shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
  File "Y:\WORK\code\venv\lib\site-packages\scipy\optimize\minpack.py", line 24, in _check_func
    res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
  File "Y:\WORK\code\venv\lib\site-packages\scipy\optimize\minpack.py", line 484, in func_wrapped
    return func(xdata, *params) - ydata
  File "<input>", line 7, in func
  File "Y:\WORK\code\venv\lib\site-packages\scipy\integrate\quadpack.py", line 348, in quad
    flip, a, b = b < a, min(a, b), max(a, b)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

The sigmoidal function I'm trying to fit contains an integral from negative infinity to a function of the independent variable. Here is my code:

import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from scipy.integrate import quad
import numpy as np
import math

x_data = np.array([ 2.5,  7.5, 12.5, 17.5, 22.5, 27.5, 32.5, 37.5, 42.5, 47.5, 52.5, 57.5, 62.5, 67.5, 72.5, 77.5])
y_data = np.array([0.05, 0.09, 0.13, 0.15, 0.2, 0.35, 0.45, 0.53, 0.68, 0.8, 0.9, 0.92, 0.99, 1, 0.95, 0.97])

#Constructing the sigmoidal function
def integrand(x):
    return np.exp(-np.square(x)/2)

def func(x, a, b):
    t = (x-a)/(b*a)
    integral = quad(integrand, -math.inf, t)[0]
    return math.sqrt(1/(2*math.pi))*integral

# Initial guess for parameters a, b
initialGuess = [35, 0.25]

# Perform the curve-fit
popt, pcov = curve_fit(func, x_data, y_data, initialGuess)

The problem seems to be coming from the integral part. In other similar posts, their function contains a boolean argument where if the independent variable exceeds a value then another function is provided. But not in my case. I'm very confused...


Solution

  • Thanks to @hpaulj: the quad function only takes scalar and my t was an array. I have changed the function as follows and the error went away

    def func(x, a, b):
        sigmoid_arr = np.array([])
        for i in x:
            t = (i- a)/(b*a)
            integral = quad(integrand, -math.inf, t)[0]
            sigmoid = math.sqrt(1/(2*math.pi))*integral
            sigmoid_arr = np.append(sigmoid_arr, sigmoid)
        return sigmoid_arr