0
$\begingroup$

I'm trying to fit a few X-Y points that look like exponential.

I used the following scipy code:

import numpy as np
import scipy
import scipy.optimize

def custom_exponential(x, k, h):
    return np.exp(k * x) / h

x_data = np.array([10, 20, 30, 40, 50, 60, 70, 80, 90, 99])
y_data = np.array([6, 25, 88, 243, 560, 1177, 2296, 4191, 7210, 11163])

params, covariance = scipy.optimize.curve_fit(custom_exponential, x_data, y_data)

k_fit, h_fit = params

print("Fitted parameters:")
print("k =", k_fit)
print("h =", h_fit)

but got the result:

Fitted parameters: k = 0.7294449661802176 h = -1.601884017897473e+35

which is nonsense (negative, 10^35...).

By fiddling numbers on an excel sheet I got to the very rough solution y = exp(0.05*x)/0.012 which doesn't look terrible on plot:

enter image description here

How to get a better solution (with scipy or something else)?

$\endgroup$

2 Answers 2

3
$\begingroup$

Just take the log of your y-data, $Y=\log(y)$ and do a linear fit. Then from the coefficients of

$Y=A\,x+B$

you get $k\!=\!A$ and $h\!=\!e^{-B}$, so that

$\log(y) = k\,x - \log(h)$

If you fit your original data with least sum squared, you will always have a bad fit at low values.

$\endgroup$
1
  • $\begingroup$ That almost did the trick. After the log operation original data was not linear, so I used polynomial (n=2) regression instead of linear regression, and that worked very good. $\endgroup$
    – mastican
    Commented Feb 27 at 8:37
2
$\begingroup$

My solution using polynomial regression, after using Konstantinos trick:

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

def poly_curve(x, *params):
    return np.polyval(params, x)

x_data = np.array([10, 20, 30, 40, 50, 60, 70, 80, 90, 99])
y_data = np.array([6, 25, 88, 243, 560, 1177, 2296, 4191, 7210, 11163])

log_y_data = np.log(y_data)

initial_params = np.ones(3)

params, covariance = curve_fit(poly_curve, x_data, log_y_data, p0=initial_params)

full_model_y = np.exp(poly_curve(x_data, *params))

plt.scatter(x_data, y_data, label='Original Data')
plt.plot(x_data, full_model_y, label='Fitted Curve', color='red')
plt.xlabel('X Data')
plt.ylabel('Y Data')
plt.legend()
plt.show()

print('Fitted Parameters:', params)

# y(x) = np.exp(-0.0005717 * x^2 + 0.14437781 * x + 0.52960452)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.