Search code examples
pythonnumpyscipycurve-fittingscientific-computing

How to fit the following function using curve_fit


I have the following function I need to solve:

np.exp((1-Y)/Y) = np.exp(c) -b*x

I defined the function as:

def function(x, b, c):

    np.exp((1-Y)/Y) = np.exp(c) -b*x
    return y

def function_solve(y, b, c):

    x = (np.exp(c)-np.exp((1-Y)/Y))/b
    return x

then I used:

x_data = [4, 6, 8, 10]

y_data = [0.86, 0.73, 0.53, 0.3] 

popt, pcov = curve_fit(function, x_data, y_data,(28.14,-0.25))
answer = function_solve(0.5, popt[0], popt[1])

I tried running the code and the error was:

can't assign to function call

The function I'm trying to solve is y = 1/ c*exp(-b*x) in the linear form. I have bunch of y_data and x_data, I want to get optimal values for c and b.


Solution

  • Some problems with your code have already been pointed out. Here is a solution:

    First, you need to get the correct logarithmic expression of your original function:

    y = 1 / (c * exp(-b * x))
    y = exp(b * x) / c
    ln(y) = b * x + ln(1/c)
    ln(y) = b * x - ln(c)
    

    If you want to use that in curve_fit, you need to define your function as follows:

    def f_log(x, b, c_ln):
        return b * x - c_ln
    

    I now show you the outcome for some randomly generated data (using b = 0.08 and c = 100.5) using the original function and then also the output for the data you provided:

    [  8.17260899e-02   1.17566291e+02]
    

    enter image description here

    As you can see the fitted values are close to the original ones and the fit describes the data very well.

    For your data it looks as follows:

    [-0.094 -1.263]
    

    enter image description here

    Here is the code:

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.optimize import curve_fit
    
    
    def f(x, b, c):
        return 1. / (c * np.exp(-b * x))
    
    
    def f_log(x, b, c_ln):
        return b * x - c_ln
    
    # some random data
    b_org = 0.08
    c_org = 100.5
    x_data = np.linspace(0.01, 100., 50)
    y_data = f(x_data, b_org, c_org) + np.random.normal(0, 0.5, len(x_data))
    
    # fit the data
    popt, pcov = curve_fit(f, x_data, y_data, p0=(0.1, 50))
    print popt
    
    # plot the data
    xnew = np.linspace(0.01, 100., 5000)
    plt.plot(x_data, y_data, 'bo')
    plt.plot(xnew, f(xnew, *popt), 'r')
    plt.show()
    
    # your data
    x_data = np.array([4, 6, 8, 10])
    y_data = np.array([0.86, 0.73, 0.53, 0.3])
    
    # fit the data
    popt_log, pcov_log = curve_fit(f_log, x_data, y_data)
    print popt_log
    
    # plot the data
    xnew = np.linspace(4, 10., 500)
    plt.plot(x_data, y_data, 'bo')
    plt.plot(xnew, f_log(xnew, *popt_log), 'r')
    plt.show()