экспоненциальный распад с помощью scipy просто дает ступенчатую функцию

#plot #scipy #curve-fitting #scipy-optimize

#график #scipy #подгонка кривой #scipy-оптимизировать

Вопрос:

Я пытаюсь выполнить экспоненциальную подгонку с набором данных:

 import matplotlib.pyplot as plt
import numpy as np
import scipy.optimize as opt


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


epr_data = np.loadtxt('T2_text', skiprows=1)

time = epr_data[:, 1]
intensity = epr_data[:, 2]


optimizedParameters, pcov = opt.curve_fit(func, time, intensity)
print(optimizedParameters)
plt.plot(time, intensity, func(time, *optimizedParameters), label="fit")

plt.show()
 

но я просто получаю эту ступенчатую функцию и эти параметры:

[1.88476367e 05 1.00000000e 00 6.49563230e 03]

график с «подгонкой»
график с quot;подгонкойquot;

а также это сообщение об ошибке:

 OptimizeWarning: Covariance of the parameters could not be estimated
  warnings.warn('Covariance of the parameters could not be estimated'
 

Редактировать:

https://pastebin.com/GTTGf0ed

я хочу построить график времени и первой строки с интенсивностью

график после вашего предложения график после вашего предложения

редактировать 2:

 import matplotlib.pyplot as plt
import numpy as np
import scipy.optimize as opt


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


epr_data = np.loadtxt('T2_text', skiprows=1)

time = epr_data[:, 1]
intensity = epr_data[:, 2]

c0 = np.mean(intensity[-10:])
a0 = intensity[0]-c0
th = time[np.searchsorted(-intensity c0, -0.5*a0)]
b0 = th / np.log(2)

optimizedParameters, pcov = opt.curve_fit(func, time, intensity, p0=(a0, b0, c0))
print(optimizedParameters)
plt.plot(time, intensity, label='data')
plt.plot(time, func(time, *optimizedParameters), label="fit")
plt.legend()

plt.show()
 

Ответ №1:

Во-первых, исправьте plot вызов вашей функции. Чтобы построить две кривые с помощью одного вызова, вы должны указать значения x и y для каждой кривой:

 plt.plot(time, intensity, time, func(time, *optimizedParameters), label="fit")
 

Для маркировки может быть проще вызвать plot дважды:

 plt.plot(time, intensity, label="data")
plt.plot(time, func(time, *optimizedParameters), label="fit")
 

Было бы проще устранить предупреждение, сгенерированное, curve_fit если бы у нас были ваши данные. Однако опыт показывает, что, скорее всего, начальное предположение по умолчанию о параметрах, используемых curve_fit (которое составляет все единицы), является просто очень плохим предположением.

Попробуйте помочь curve_fit , предоставив ему лучшую отправную точку для его процедуры численной оптимизации. Следующий фрагмент кода показывает, как вы можете вычислить грубые предположения для a , b и c . Передайте их curve_fit с аргументом p0=(a0, b0, c0) .

 # Assume that the time series is long enough that the tail
# has flattened out to approximately random noise around c.
c0 = np.mean(intensity[-10:])

# This assumes time[0] is 0.
a0 = intensity[0] - c0

# Rough guess of the half-life.
th = time[np.searchsorted(-intensity c0, -0.5*a0)]
b0 = th / np.log(2)
 

Комментарии:

1. Спасибо за ответ. Данные находятся в редактировании. График изменился после того, как я изменил вызов функции plot, но даже после лучших отправных точек это снова просто ступенчатая функция. Я добавлю изображение в исходное сообщение.

2. Вы пробовали это снова с a0 , b0 и c0 , как показано выше?

3. Да, я это сделал. Я прикрепил график в исходном сообщении. Я использовал переменную time для x в вашем небольшом фрагменте кода (в переменной xh), это правильно?

4. Ах, извините, я исправлю это, чтобы соответствовать вашему исходному коду.

5. В основе curve_fit лежит алгоритм численной минимизации. Такие алгоритмы почти всегда работают лучше всего, когда дается разумное предположение о решении. Предположение по умолчанию p0 для in curve_fit равно (1, 1, 1), что для ваших данных является ужасным предположением. Ваши значения времени варьируются от 0 до 200000, а b = 1 все значения exp(-time/b) underflow, кроме двух, равны 0, поэтому алгоритм просто не может вычислить правильные значения функции, которую нужно минимизировать.