-1

I am trying to fit a custom equation to a dataset with 1 dependent variable (y1 - 1D numpy float array with 45 entries) and two independent variables (x1 - 2D numpy float array with 45 entries). I am trying to get the optimized values of the parameters. What is wrong in the following code? This is the code I am using:

import numpy as np
from scipy.optimize import curve_fit

# Define your custom exponential equation
def custom_exponential_equation(X, param1, param2, param3):
    # X is a 2D array with shape (N, 2), where N is the number of data points
    # X[:, 0] corresponds to the first independent variable
    # X[:, 1] corresponds to the second independent variable
    y = param1 * np.exp(param2 * (X[:, 0]* (X[:, 1]**param3))
    return y
initial_params = [1.0, 1.0, 1.0]

# Perform the curve fitting
params, _ = curve_fit(custom_exponential_equation, x1, y1, p0=initial_params)

print(params)

The error message is:

Result from function call is not a proper array of floats.
Reinderien
  • 11,755
  • 5
  • 49
  • 77
Deep Roy
  • 7
  • 1

2 Answers2

0

It seems that you missed a closing parenthesis in the equation line.

import numpy as np
from scipy.optimize import curve_fit

# Define your custom exponential equation
def custom_exponential_equation(X, param1, param2, param3):
    # X is a 2D array with shape (N, 2), where N is the number of data points
    # X[:, 0] corresponds to the first independent variable
    # X[:, 1] corresponds to the second independent variable
    y = param1 * np.exp(param2 * (X[:, 0]* (X[:, 1]**param3)))
    return y

# Example data
x1 = np.random.random((45, 2))
y1 = np.random.random(45)

initial_params = [1.0, 1.0, 1.0]

# Perform the curve fitting
params, _ = curve_fit(custom_exponential_equation, x1, y1, p0=initial_params)

print(params)

I have also added example data for x1 and y1 since you didn't provide them. You should replace them with your actual data arrays before running the code.

Karo
  • 107
  • 8
0

Always add bounds. It's impossible to say whether the bounds I've demonstrated are appropriate because you haven't offered data.

With this form of function, unpack your two-dimensional array to separate variables instead of indexing. And choose better variable names.

import numpy as np
from numpy.random import default_rng
from scipy.optimize import curve_fit


def synthesize(a: float = 1.5, b: float = 1.9, c: float = 0.7, n: int = 45) -> tuple[np.ndarray, np.ndarray]:
    rand = default_rng(seed=0)
    xz = np.linspace(start=1.5, stop=2, num=n)[np.newaxis, :] + rand.uniform(low=-0.02, high=0.02, size=(2, n))
    x, z = xz
    y = (np.log(z/a) / b / x)**(1/c) * (1 + rand.uniform(low=-0.05, high=0.05, size=n))
    return np.vstack((x, y)), z


def exponential(xy: np.ndarray, a: float, b: float, c: float) -> np.ndarray:
    x, y = xy
    z = a * np.exp(b * x * y**c)
    return z


xy, z = synthesize()

params, _ = curve_fit(
    f=exponential,
    xdata=xy, ydata=z, p0=(1, 1, 1),
    bounds=(0.1, 10),
)
print(params)
assert np.allclose(params, (1.5, 1.9, 0.7), rtol=0, atol=0.1)
Reinderien
  • 11,755
  • 5
  • 49
  • 77