I need to fit some data with a two-term exponential following the equation a*exp(b*x)+c*exp(d*x)
. In matlab, it's as easy as changing the 1 to a 2 in polyfit to go from a one-term exponential to a two-term. I haven't found a simple solution to do it in python and was wondering if there even was one? I tried using curve_fit but it is giving me lots of trouble and after scouring the internet I still haven't found anything useful. Any help is appreciated!
Asked
Active
Viewed 9,468 times
2
-
What's `curve_fit`? Are you using a third party library? – Kevin May 20 '15 at 17:35
-
Presumably you're using SciPy? Can you post the code that gave you trouble? – xnx May 20 '15 at 17:38
2 Answers
4
Yes you can use curve_fit
from scipy
. Here is an example for your specific fit function.
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
x = np.linspace(0,4,50) # Example data
def func(x, a, b, c, d):
return a * np.exp(b * x) + c * np.exp(d * x)
y = func(x, 2.5, 1.3, 0.5, 0.5) # Example exponential data
# Here you give the initial parameters for a,b,c which Python then iterates over
# to find the best fit
popt, pcov = curve_fit(func,x,y,p0=(1.0,1.0,1.0,1.0))
print(popt) # This contains your three best fit parameters
p1 = popt[0] # This is your a
p2 = popt[1] # This is your b
p3 = popt[2] # This is your c
p4 = popt[3] # This is your d
residuals = y - func(x,p1,p2,p3,p4)
fres = sum( (residuals**2)/func(x,p1,p2,p3,p4) ) # The chi-sqaure of your fit
print(fres)
""" Now if you need to plot, perform the code below """
curvey = func(x,p1,p2,p3,p4) # This is your y axis fit-line
plt.plot(x, curvey, 'red', label='The best-fit line')
plt.scatter(x,y, c='b',label='The data points')
plt.legend(loc='best')
plt.xlabel('x')
plt.ylabel('y')
plt.show()

Srivatsan
- 9,225
- 13
- 58
- 83
1
You can do it with leastsq. Something like:
from numpy import log, exp
from scipy.optimize.minpack import leastsq
## regression function
def _exp(a, b, c, d):
"""
Exponential function y = a * exp(b * x) + c * exp(d * x)
"""
return lambda x: a * exp(b * x) + c * exp(d * x)
## interpolation
def interpolate(x, df, fun=_exp):
"""
Interpolate Y from X based on df, a dataframe with columns 'x' and 'y'.
"""
resid = lambda p, x, y: y - fun(*p)(x)
ls = leastsq(resid, [1.0, 1.0, 1.0, 1.0], args=(df['x'], df['y']))
a, b, c, d = ls[0]
y = fun(a, b, c, d)(x)
return y

mattexx
- 6,456
- 3
- 36
- 47