【问题标题】:Exponential regression function Python指数回归函数 Python
【发布时间】:2018-06-05 17:46:26
【问题描述】:

我正在尝试实现指数回归函数。 sp 代表同情。我使用 numpy 和 sympy。首先,在 func_exp 我尝试使用 np.exp 但它产生了一个错误(属性错误),所以我决定使用 sympy 代替。嗯,这就是代码

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)

我尝试执行:

  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)

我得到:

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.

怎么了?提前致谢!

【问题讨论】:

  • 你为什么要引入 sympy?
  • @user2357112 因为当我使用 sympy 时,我得到了 np.array([np.exp(x)*x]) Traceback(最近一次调用最后一次):文件“",第 1 行,在 np.array([np.exp(x)*x]) AttributeError: 'Symbol' object has no attribute 'exp'
  • 如果没有引入 sympy 就不会出现这个问题。
  • 你确定它不要求a * np.exp(b * x) + c吗?为此,您得到了很好的拟合,但是如何才能很好地拟合您的功能呢?它永远不会通过 (0, 0)。
  • 提示:使用真正的指数数据集而不是您拥有的数据集来测试您的拟合函数。

标签: python numpy regression sympy exponential


【解决方案1】:

这里有一个最小的例子,让您的 fit 函数尽可能接近您的代码,但删除所有不必要的元素。您可以轻松删除 c 以满足您的要求:

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)

输出c = 0:

c != 0 的输出:

主要变化说明:

  1. 删除sympy - 它与拟合程序无关。
  2. 指数拟合函数的定义放在exponential_regression之外,因此可以从脚本的其他部分访问。它使用np.exp,因为您在 scipy 中使用 numpy 数组。
  3. 添加了parameter p0,其中包含对参数的初始猜测。由于局部极值,拟合函数通常对这种初始猜测很敏感。
  4. 使用*popt 解包变量,使其更灵活地处理不同数量的变量。 a = popt[0]b = popt[1]
  5. 删除了不必要的导入。 Keep your namespace free from clutter.

【讨论】:

  • 酷!两个问题: (1) 你是如何确定 p0 = (-1, 0.01, 1) 的? (2)我以为这个数据集有双曲线的最佳拟合,但是现在,有了常数c……原来指数更好?
  • (1) 猜测。从 (0, 0) 我们可以得出结论 a + c = 0。形状告诉我们 a
  • 是的,看起来是这样,所以这就是我开始怀疑的原因......谢谢
猜你喜欢
  • 1970-01-01
  • 2022-07-27
  • 2016-05-10
  • 2016-06-30
  • 1970-01-01
  • 2015-02-25
相关资源
最近更新 更多