Экспоненциальная функция регрессии Python

alienflow спросил: 12 мая 2018 в 04:06 в: python

Я пытаюсь реализовать функцию экспоненциальной регрессии. sp обозначает символ. Я использую numpy и sympy. Во-первых, в func_exp я попытался использовать np.exp, но он сгенерировал ошибку (ошибку атрибута), поэтому я решил использовать sympy. Ну, это код

import numpy as np
from numpy.linalg import matrix_rank
import scipy 
import scipy.integrateimport random import matplotlib.pyplot as plt
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3Dfrom sympy import integrate
import sympy as spx, 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.

Что не так? Спасибо заранее!

1 ответ

Есть решение
Mr. T ответил: 12 мая 2018 в 05:20

Вот минимальный пример для вашей подходящей функции как можно ближе к вашему коду, но удаление всех ненужных элементов. Вы можете легко удалить c, чтобы соответствовать вашим требованиям:

import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as pltdef func_exp(x, a, b, c):
        #c = 0
        return a * np.exp(b * x) + cdef 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:

Output с c != 0:

Основные изменения:

  1. Удалено sympy - это не имеет никакого отношения к процедуре подстановки.
  2. Определение функции экспоненциальной подгонки помещается вне exponential_regression, поэтому к ней можно получить доступ из других частей скрипта. Он использует np.exp, потому что вы работаете с массивами numpy в scipy.
  3. Добавлен параметр p0, который содержит начальные догадки для параметров. Пригодные функции часто чувствительны к этому первоначальному предположению из-за локальных экстремумов.
  4. Распакуйте переменные с помощью *popt, чтобы сделать его более гибким для разных чисел. a = popt[0], b = popt[1] и т. д.
  5. Удалены ненужные импорт. Храните пространство имен без помех.
alienflow ответил: 13 мая 2018 в 11:39
Круто! Два вопроса: (1) Как вы определили p0 = (-1, 0.01, 1)? (2) Я думал, что этот набор данных имеет гиперболический наилучший вариант, но теперь, с константой c ... получается, что экспоненциальная лучше?
Mr. T ответил: 13 мая 2018 в 02:48
(1) Guesstimates. Из (0, 0) можно заключить, что a + c = 0. Форма говорит нам, что a < 0. И b должно быть установлено в соответствии с формой с начальным параметром -0.1 - но, тем не менее, оно все равно сходилось. (2) Является ли это лучше, чем другая функция, неясна. Вы должны сравнить отклонение с помощью pcov, чтобы получить оценку, насколько хорошо подходит для каждой функции. Но он, безусловно, выглядит хорошо подогнанным.
alienflow ответил: 13 мая 2018 в 03:02
да это выглядит так, поэтому я начал сомневаться .. спасибо