python SciPy curve_fit с np.exp возвращает с pcov = inf - PullRequest
0 голосов
/ 27 апреля 2020

Я пытаюсь оптимизировать экспоненциальную подгонку с помощью scipy.optimize.curve_fit. Но результат не очень хороший. Мой код:

def func(x, a, b, c):
  return a * np.exp(-b * x) + c

# xdata and data is obtain from another dataframe and their type is nparray

xdata =[36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70 ,71,72]
ydata = [4,4,4,6,6,13,22,22,26,28,38,48,55,65,65,92,112,134,171,210,267,307,353,436,669,669,818,1029,1219,1405,1617,1791,2032,2032,2182,2298,2389]

popt, pcov = curve_fit(func, xdata, ydata)
plt.plot(xdata, func(xdata, *popt), 'r-', label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt))

plt.scatter(xdata, ydata, s=1)
plt.show()

Тогда я получил такой результат:

введите описание изображения здесь

результат показал, что:

pcov = [[inf inf inf] [inf inf inf] [inf inf inf]]
popt = [1  1  611.83784]

Я не знаю, как правильно подогнать мою кривую. Ты можешь меня приветствовать? Спасибо!

Ответы [ 2 ]

1 голос
/ 27 апреля 2020

Подгонка к экспоненциальным функциям чрезвычайно сложна, потому что крошечные изменения в показателе степени могут иметь большие различия в результате. Оптимизатор выполняет оптимизацию по многим порядкам, и ошибки около начала координат не одинаково взвешиваются по сравнению с ошибками, расположенными выше по кривой.

Самый простой способ справиться с этим - преобразовать ваши экспоненциальные данные в строку, используя преобразование:

y' = np.log(y)

Тогда вместо того, чтобы использовать более изящный (и более медленный) Curve_fit, вы можете просто использовать функцию полифита numpy и подгонять линию. Если вы sh, вы можете преобразовать данные обратно в линейное пространство для анализа. Здесь я отредактировал ваш код, чтобы выполнить подбор с помощью np.polyfit, и вы увидите, что подгонка разумна.

import numpy as np
import matplotlib.pyplot as plt
# from scipy.optimize import curve_fit

# def func(x, a, b, c):
#   return a * np.exp(-b * x) + c

# xdata and data is obtain from another dataframe and their type is nparray

xdata = np.array([36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70 ,71,72])
ydata = np.array([4,4,4,6,6,13,22,22,26,28,38,48,55,65,65,92,112,134,171,210,267,307,353,436,669,669,818,1029,1219,1405,1617,1791,2032,2032,2182,2298,2389])

# popt, pcov = curve_fit(func, xdata, ydata)
# plt.plot(xdata, func(xdata, *popt), 'r-', label='fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt))

# Fit a line (deg=1)
P, pcov = np.polyfit(xdata, np.log(ydata), deg=1, cov=True)
print(pcov)
plt.scatter(xdata, ydata, s=1)
plt.plot(xdata, np.exp(P[0]*xdata + P[1]), 'r-')

plt.legend()
plt.show()

enter image description here

0 голосов
/ 27 апреля 2020

Метод не находит оптимальную точку. Попробуйте изменить первоначальное предположение так, чтобы b начиналось с отрицательного значения, поскольку из ваших данных видно, что b должно быть отрицательным, так что func соответствует ему прилично. Кроме того, из документов curve_fit начальное предположение по умолчанию равно 1, если не указано иное. Хорошее первоначальное предположение:

popt, pcov = curve_fit(func, xdata, ydata, p0=[1, -0.05, 1])

, что дает

popt                                                                                                                                                                                                      
array([ 1.90782987e+00, -1.01639857e-01, -1.73633728e+02])

pcov                                                                                                                                                                                                           
array([[ 1.08960274e+00,  7.93580944e-03, -5.24526701e+01],
       [ 7.93580944e-03,  5.79450721e-05, -3.74693994e-01],
       [-5.24526701e+01, -3.74693994e-01,  3.34388178e+03]])

И сюжет

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...