问题
I am trying to implement a exponential regression function. sp stands for sympy. I use numpy and sympy. Firstly, in func_exp I tried to use np.exp but it generated an error (attribute error), so I decided to use sympy instead. Well, this is the code
import numpy as np
from numpy.linalg import matrix_rank
import scipy
import scipy.integrate
import random
import matplotlib.pyplot as plt
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
from sympy import integrate
import sympy as sp
x, y = sp.symbols('x, y')
sp.init_printing(use_unicode=True,use_latex='mathjax')
def exponential_regression (x_data, y_data):
def func_exp(x, a, b):
return a*sp.exp(b*x)
popt, pcov = scipy.optimize.curve_fit(func_exp, x_data, y_data)
a = popt[0] # componente a, Parámetro ÓPTimo (popt).
b = popt[1] # componente b, Parámetro ÓPTimo (popt).
plt.figure()
puntos = plt.plot(x_data, y_data, 'x', color='xkcd:maroon')
curva_regresion = plt.plot(x_data, func_exp(x_data, a, b), color='xkcd:teal')
plt.show(puntos, curva_regresion)
return func_exp(x, a, b)
I try to execute:
x_data = np.arange(0, 51) # Crea un array de 0 a 50.
y_data = np.array([0.001, 0.199, 0.394, 0.556, 0.797, 0.891, 1.171, 1.128, 1.437,
1.525, 1.720, 1.703, 1.895, 2.003, 2.108, 2.408, 2.424,2.537,
2.647, 2.740, 2.957, 2.58, 3.156, 3.051, 3.043, 3.353, 3.400,
3.606, 3.659, 3.671, 3.750, 3.827, 3.902, 3.976, 4.048, 4.018,
4.286, 4.353, 4.418, 4.382, 4.444, 4.485, 4.465, 4.600, 4.681,
4.737, 4.792, 4.845, 4.909, 4.919, 5.100])
exponential_regression(x_data, y_data)
And I get:
exponential_regression(x_data, y_data)
TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'
Traceback (most recent call last):
File "<ipython-input-122-ee7c243ae4b0>", line 1, in <module>
exponential_regression(x_data, y_data)
File "/Volumes/TOSHIBA/spline.py", line 35, in exponential_regression
popt, pcov = scipy.optimize.curve_fit(func_exp, x_data, y_data)
File "/Applications/anaconda3/lib/python3.6/site-packages/scipy/optimize/minpack.py", line 742, in curve_fit
res = leastsq(func, p0, Dfun=jac, full_output=1, **kwargs)
File "/Applications/anaconda3/lib/python3.6/site-packages/scipy/optimize/minpack.py", line 387, in leastsq
gtol, maxfev, epsfcn, factor, diag)
error: Result from function call is not a proper array of floats.
What is wrong? Thanks in advance!
回答1:
Here is a minimal example for your fit function as close as possible to your code but removing all unnecessary elements. You can easily remove c
to adhere to your requirements:
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
def func_exp(x, a, b, c):
#c = 0
return a * np.exp(b * x) + c
def exponential_regression (x_data, y_data):
popt, pcov = curve_fit(func_exp, x_data, y_data, p0 = (-1, 0.01, 1))
print(popt)
puntos = plt.plot(x_data, y_data, 'x', color='xkcd:maroon', label = "data")
curva_regresion = plt.plot(x_data, func_exp(x_data, *popt), color='xkcd:teal', label = "fit: {:.3f}, {:.3f}, {:.3f}".format(*popt))
plt.legend()
plt.show()
return func_exp(x_data, *popt)
x_data = np.arange(0, 51)
y_data = np.array([0.001, 0.199, 0.394, 0.556, 0.797, 0.891, 1.171, 1.128, 1.437,
1.525, 1.720, 1.703, 1.895, 2.003, 2.108, 2.408, 2.424,2.537,
2.647, 2.740, 2.957, 2.58, 3.156, 3.051, 3.043, 3.353, 3.400,
3.606, 3.659, 3.671, 3.750, 3.827, 3.902, 3.976, 4.048, 4.018,
4.286, 4.353, 4.418, 4.382, 4.444, 4.485, 4.465, 4.600, 4.681,
4.737, 4.792, 4.845, 4.909, 4.919, 5.100])
exponential_regression(x_data, y_data)
Output with c = 0
:
Output with c != 0
:
Main changes explained:
- Removed
sympy
- it has nothing to do with the fitting procedure. - The definition of the exponential fit function is placed outside
exponential_regression
, so it can be accessed from other parts of the script. It usesnp.exp
because you work with numpy arrays in scipy. - Added the parameter p0 which contains the initial guesses for the parameters. Fit functions are often sensitive to this initial guess because of local extrema.
- Unpack variables with
*popt
to make it more flexible for different numbers of variables.a = popt[0]
,b = popt[1]
, etc. - Removed unnecessary imports. Keep your namespace free from clutter.
来源:https://stackoverflow.com/questions/50706092/exponential-regression-function-python