В дополнение к очень хорошим ответам из «Добро пожаловать в переполнение стека», что «не существует простого, универсального подхода и Джеймса Филлипса, что« дифференциальная эволюция часто помогает найти хорошие отправные точки (или даже хорошие решения!), Если они несколько медленнее, чем * 1001 »* ", позвольте мне дать отдельный ответ, который вам может пригодиться.
Во-первых, тот факт, что curve_fit()
по умолчанию принимает любые значения параметров, является душераздирающей плохой идеей. Нет никакого возможного оправдания для такого поведения, и вы, и все остальные должны рассматривать тот факт, что для параметров существуют значения по умолчанию, как серьезную ошибку при реализации curve_fit()
и делать вид, что этой ошибки не существует. НИКОГДА не считаю эти значения по умолчанию разумными.
Из простого графика данных должно быть очевидно, что a=1, b=1, c=1
являются очень, очень плохими начальными значениями. Функция затухает, поэтому b < 0
. На самом деле, если бы вы начали с a=1, b=-1, c=1
, вы бынашли правильное решение.
Возможно, это также помогло быnd по параметрам.Даже установление границ c
(-100, 100), возможно, помогло.Как и в случае знака b
, я думаю, что вы могли видеть эту границу из простого графика данных.Когда я пытаюсь сделать это для вашей проблемы, границы для c
не помогают, если начальное значение равно b=1
, но для b=0
или b=-5
.
Что еще более важно, хотя вы печатаетеНа графике лучше всего подходят параметры popt
. Вы не печатаете неопределенности или корреляции между переменными, содержащимися в pcov
, и, таким образом, ваша интерпретация результатов является неполной.Если бы вы посмотрели на эти значения, вы бы увидели, что начиная с b=1
приводит не только к плохим значениям, но также к огромной неопределенности параметров и очень, очень высокой корреляции.Это припадок говорит вам, что он нашел плохое решение.К сожалению, возврат pcov
из curve_fit
не очень легко распаковать.
Позвольте мне порекомендовать lmfit (https://lmfit.github.io/lmfit-py/) (отказ от ответственности: я ведущий разработчик). Среди других функцийэтот модуль вынуждает вас указывать начальные значения, отличные от заданных по умолчанию, и упростить составление более полного отчета. Для вашей проблемы даже запуск с a=1, b=1, c=1
дал бы более значимое указание на то, что что-то не так:
from lmfit import Model
mod = Model(func_powerlaw)
params = mod.make_params(a=1, b=1, c=1)
ret = mod.fit(test_Y[1:], params, x=test_X[1:])
print(ret.fit_report())
, который вывел бы:
[[Model]]
Model(func_powerlaw)
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 1318
# data points = 9
# variables = 3
chi-square = 0.03300395
reduced chi-square = 0.00550066
Akaike info crit = -44.4751740
Bayesian info crit = -43.8835003
[[Variables]]
a: -1319.16780 +/- 6892109.87 (522458.92%) (init = 1)
b: 2.0034e-04 +/- 1.04592341 (522076.12%) (init = 1)
c: 1320.73359 +/- 6892110.20 (521839.55%) (init = 1)
[[Correlations]] (unreported correlations are < 0.100)
C(a, c) = -1.000
C(b, c) = -1.000
C(a, b) = 1.000
То есть a = -1.3e3 +/- 6.8e6
- не очень хорошо определены! Кроме того, все параметры полностью коррелированы.
Изменение начального значения для b
-0,5:
params = mod.make_params(a=1, b=-0.5, c=1) ## Note !
ret = mod.fit(test_Y[1:], params, x=test_X[1:])
print(ret.fit_report())
дает
[[Model]]
Model(func_powerlaw)
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 31
# data points = 9
# variables = 3
chi-square = 4.9304e-32
reduced chi-square = 8.2173e-33
Akaike info crit = -662.560782
Bayesian info crit = -661.969108
[[Variables]]
a: 2.00000000 +/- 1.5579e-15 (0.00%) (init = 1)
b: -2.00000000 +/- 1.1989e-15 (0.00%) (init = -0.5)
c: 1.00000000 +/- 8.2926e-17 (0.00%) (init = 1)
[[Correlations]] (unreported correlations are < 0.100)
C(a, b) = -0.964
C(b, c) = -0.880
C(a, c) = 0.769
, что несколько лучше.
Короче, начальные значения всегда имеют значение, иВ результате получаются не только наиболее подходящие значения, но и неопределенности и корреляции.