# scipy exp model fitting: prevent coefficients blowup

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:

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

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.

• 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. Commented Feb 27 at 8:37

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)