I want to fit an exponential function y=x ** pw
with a constant pw
to fit through two datapoints. The scipy
curve_fit
function should optimise adj1
and adj2
. I have tried with the code below but couldn't get it to work. The curve does not go through the datapoints. How can I fix it?
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def func(x, adj1,adj2):
return np.round(((x+adj1) ** pw) * adj2, 2)
x = [0.5,0.85] # two given datapoints to which the exponential function with power pw should fit
y = [0.02,4]
pw=15
popt, pcov = curve_fit(func, x, y)
xf=np.linspace(0,1,50)
plt.figure()
plt.plot(x, y, 'ko', label="Original Data")
plt.plot(xf, func(xf, *popt), 'r-', label="Fitted Curve")
plt.show()
y = e(ax)*e(b) where a ,b are coefficients of that exponential equation. We would also use numpy. polyfit() method for fitting the curve. This function takes on three parameters x, y and the polynomial degree(n) returns coefficients of nth degree polynomial.
The SciPy open source library provides the curve_fit() function for curve fitting via nonlinear least squares. The function takes the same input and output data as arguments, as well as the name of the mapping function to use. The mapping function must take examples of input data and some number of arguments.
If you have two points, (x1, y1) and (x2, y2), you can define the exponential function that passes through these points by substituting them in the equation y = abx and solving for a and b. In general, you have to solve this pair of equations: y1 = abx1 and y2 = abx2, .
If you want to find the two parameters in your objective function from only two data points, this isn't necessarily a problem for least-squares fitting: just solve the simultaneous equations y1 = b(x1+a)^p and y2 = b(x2+a)^p for the parameters a
and b
:
import numpy as np
import matplotlib.pyplot as plt
def func(x, adj1,adj2):
return ((x+adj1) ** pw) * adj2
x = [0.5,0.85] # two given datapoints to which the exponential function with power pw should fit
y = [0.02,4]
pw = 15
A = np.exp(np.log(y[0]/y[1])/pw)
a = (x[0] - x[1]*A)/(A-1)
b = y[0]/(x[0]+a)**pw
xf=np.linspace(0,1,50)
plt.figure()
plt.plot(x, y, 'ko', label="Original Data")
plt.plot(xf, func(xf, a, b), 'r-', label="Fitted Curve")
plt.show()
The resulting function will pass through both points exactly, of course.
It's just because the round method is killing curve_fit's ability to search the space. Small perturbations of p0 will always give an equal result, so it stops searching immediatly and will always return whatever you give it as a starting point (by default p0 = [1.,1.]). The solution is to simply remove np.round from your function.
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
def func(x, adj1,adj2):
return ((x+adj1) ** pw) * adj2
x = [0.5,0.85] # two given datapoints to which the exponential function with power pw should fit
y = [0.02,4]
pw=15
popt, pcov = curve_fit(func, x, y)
xf=np.linspace(0,1,50)
plt.figure()
plt.plot(x, y, 'ko', label="Original Data")
plt.plot(xf, func(xf, *popt), 'r-', label="Fitted Curve")
plt.show()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With