У меня неожиданное поведение при вызове scipy.optimize.curve_fit
с аргументом max_nfev
.В документации говорится, что дополнительные kwargs
передаются leastsq
для method='lm'
и least_squares
в противном случае.Кроме того, method
должно по умолчанию 'trf'
(т.е. не 'lm'
), если указано bounds
.Наконец, least_squares
принимает аргумент max_nfev
, который по умолчанию равен 100*len(x)
, если не предоставлен (или явно передан как max_nfev=None
), x
является одним из массивов, для которых выполняется подгонка кривой.
У меня есть набор данных (и функция сопоставления), в котором scipy.optimize.curve_fit
не удается.Время, необходимое для того, чтобы программа перестала работать, зависит от max_nfev
, как и ожидалось.Однако это время сильно отличается от указания max_nfev=100*len(x)
в вызове scipy.optimize.curve_fit
и вообще не передачи max_nfev
, что, кажется, идет вразрез с задокументированным поведением.
Вот скрипт, который демонстрирует это:
import time
import numpy as np
import scipy.optimize
x, y = np.loadtxt('data.txt', unpack=True)
# Attempt curve fit
initial_guess = (1, 0)
bounds = ([-np.inf, 0], [np.inf, 15])
for max_nfev in (None, 1*len(x), 10*len(x), 100*len(x)):
print('\nRunning with max_nfev = {}:'.format(max_nfev))
t0 = time.time()
try:
scipy.optimize.curve_fit(
lambda x, factor, exponent: factor*x**exponent,
x,
y,
initial_guess,
bounds=bounds,
ftol=1e-10,
maxfev=max_nfev,
)
deltat = time.time() - t0
print('Succeeded after', deltat, 's')
except RuntimeError:
deltat = time.time() - t0
print('Failed after', deltat, 's')
Скрипту нужен набор данных в data.txt
(24 КБ), который вы можете скачать здесь .
Вкл.В моей системе вывод этого сценария:
Запуск с max_nfev = Нет:
Ошибка после 0.10752344131469727 с
Запуск с max_nfev = 441:
Ошибка после 0.17525863647460938 с
Работа с max_nfev = 4410:
Ошибка после 1.732572078704834 с
Работа с max_nfev = 44100:
Ошибка после 17.796284437179565 с
Я ожидаюпервый (max_nfev=None
) и последний (max_nfev=100*len(x)
) вызовы занимают примерно одинаковое количество времени до сбоя.Чтобы добавить к тайне, кажется, что вместо передачи max_nfev
я мог бы также передать maxfev
, что не является допустимым аргументом least_squares
, но вместо maxfev
-эквивалентааргумент принят leastsq
.
Я что-то не так понял, или документация или реализация неверна?
Я испытываю это как в {SciPy 1.1.0, Python 3.6.5}, так и в {SciPy 1.2.0,Python 3.7.1}.