pythonscipycurve-fitting

Why does curve_fit not fit 3d curve


I'm trying to fit a multiveriable curve to the function y**2*(y**2/4 - a*y/3 + b/2) - x**2*(x**2/4 - a*x/3 + b/2) but it seams that curve_fit doesn't fit to the generated data. The pcov values are all inf and the a and b outputs remain the same as the guesses.

Here is my code:

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


def func(X, a, b):
    x,y = X
    return y**2*(y**2/4 - a*y/3 + b/2) - x**2*(x**2/4 - a*x/3 + b/2)


# some artificially noisy data to fit

x = np.arange(0,5,0.1)
y = np.arange(0,5,0.1)
a = 6
b = 9
z = func((x,y), a, b)


# initial guesses for a,b:

popt, pcov = curve_fit(func, [x,y], z, p0=[10,8])

print(popt)
print(pcov)
print("a = ",popt[0] ," +/- ", np.sqrt(pcov[0,0]))
print("b = ",popt[1] ," +/- ", np.sqrt(pcov[1,1]))


#surface plot

ax = plt.axes(projection="3d")
x_data = np.arange(0,5,0.1)
y_data = np.arange(0,5,0.1)
X, Y = np.meshgrid(x_data,y_data)


Z = func((X,Y), popt[0], popt[1])
ax.scatter(X, Y, Z)
plt.show()

The code works for other functions but not this one.


Solution

  • When you increase the dimensionnality, you also have to sample correctly in all dimension. In your MCVE you are only sampling over a single line instead of sampling in the plane.

    The following sampling spreads over the plane:

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy import optimize
    
    def model(x, a, b):
        return x[1] ** 2 *(x[1] ** 2 / 4 - a * x[1] / 3 + b / 2) - x[0] ** 2 *(x[0] ** 2 / 4 - a * x[0] / 3 + b / 2)
    
    x = np.arange(0, 5, 0.1)
    y = np.arange(0, 5, 0.1)
    X, Y = np.meshgrid(x, y)
    
    a = 6
    b = 9
    x = (X.ravel(), Y.ravel())
    
    z = model(x, a, b)
    
    popt, pcov = optimize.curve_fit(model, x, z, p0=[10,8])
    #(array([6., 9.]),
    # array([[6.78893023e-33, 2.09471226e-32],
    #        [2.09471226e-32, 6.64942515e-32]]))
    

    And fits properly.

    The following figure shows your sampling and the plane sampling with surface:

    enter image description here

    Also notice, than your original sampling lies exactly on single isopleth:

    enter image description here