В вашем примере есть две проблемы.
Тривиальная задача
curve_fit
ожидает значения независимой переменной в качестве второго аргумента , в то время как приведенный выше код дает list(range(len(data))
, что даст целочисленные значения x от 0 до длинных data
. Вы заметите, что ваш точечный график указывает только go до ~ 50. Я предполагаю, что именно поэтому.
Вместо этого вы должны дать список значений независимой переменной в точках, где наблюдалось data
. В зависимости от того, как data
генерируется / собирается (вы не предоставляете эту информацию в своем вопросе), это может быть xdata
.
Я также немного запутался относительно того, как вписывается второй график с первым. Шкала y, кажется, не совпадает с синей линией. Я предполагаю, что графики были сгенерированы из разных примеров для разных значений параметров. Я их проигнорирую.
Реальная проблема
Не все методы оптимизации одинаково подходят для всех задач. curve_fit
может использовать 3 метода: 'lm
, 'trf'
и 'dogbox'
. По умолчанию это lm
, для метода Левенберга – Марквардта , , если не указаны границы , в этом случае вместо него используется 'trf'
, то есть метод Trust Region .
Немного поиграв с примером, я обнаружил, что 'lm'
работает хорошо, а 'trf'
- нет.
Например, возьмем следующий код:
import math
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
def first_deriv(xlist, L, k, x0):
return [k*L*(math.e**(-k*(x+x0)))/(1+math.e**(-k*(x+x0)))**2 for x in xlist]
xdata = list(np.linspace(-100, 100, 2000))
real_parameters = (320000.0, 0.1, -30.0)
fakedata = first_deriv(xdata, *real_parameters)
plt.plot(xdata, fakedata)
Который дает кривую в вашем примере выше (i sh):
Сравнение 3 методов подтверждает, что 'lm'
ищет best и восстанавливает исходные параметры:
lm_parameters = curve_fit(first_deriv, xdata, fakedata)[0]
trf_parameters = curve_fit(first_deriv, xdata, fakedata, method='trf')[0]
dogbox_parameters = curve_fit(first_deriv, xdata, fakedata, method='dogbox')[0]
plt.scatter(xdata, first_deriv(xdata, *lm_parameters), s=1, label='lm')
plt.scatter(xdata, first_deriv(xdata, *trf_parameters), s=1, label='trf')
plt.scatter(xdata, first_deriv(xdata, *dogbox_parameters), s=1, label='dogbox')
plt.legend()
Интересный вопрос (который, возможно, заслуживает отдельного поста) состоит в том, почему это так. Хотя я и не могу дать точного математического аргумента, игра с параметрами вашей функции предлагает некоторые грубые идеи.
Например, «расширение пика» вашей функции, кажется, позволяет всем методам работать хорошо.
Без сомнения, изменение параметров изменило «ландшафт пригодности» таким образом, чтобы позволить методам области доверия успешно работать.
Также возможно, что некоторые параметры самих методов 'trf'
и 'dogbox'
могут дать лучшие результаты. Это потребовало бы более глубокого знания методов.
Сказав, что 'lm'
, кажется, лучший метод для этой конкретной проблемы. Всегда важно знать, какой метод вы используете, и экспериментировать с различными для каждой новой проблемы, особенно если вы получаете плохие результаты.