使用max_nfev
参数调用scipy.optimize.curve_fit
时,我遇到了意外的行为。该文档指出,多余的kwargs
将传递给method='lm'
的{{3}},否则传递给leastsq
。另外,如果提供了method
,则'trf'
应该默认为'lm'
(即不是bounds
)。最后,least_squares
采用max_nfev
参数,如果未提供(或显式传递为100*len(x)
,则默认为max_nfev=None
,x
是数组上的数组之一进行曲线拟合。
我有一个least_squares
失败的数据集(和匹配函数)。如预期的那样,例程放弃之前所花费的时间与max_nfev
线性相关。但是,这次在调用scipy.optimize.curve_fit
中指定max_nfev=100*len(x)
与根本不传递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 KB)中的数据集,您可以下载scipy.optimize.curve_fit
。
在我的系统上,此脚本的输出为
使用max_nfev =无运行:
0.10752344131469727 s后失败以max_nfev = 441运行:
0.17525863647460938 s后失败以max_nfev = 4410运行:
1.732572078704834 s后失败以max_nfev = 44100运行:
17.796284437179565 s后失败
我希望第一个(max_nfev=None
)和最后一个(max_nfev=100*len(x)
)调用花费的时间大致相同。更令人难以置信的是,似乎我不愿传递max_nfev
而不是传递maxfev
,它不是here的有效参数,而是maxfev
-least_squares
的等效参数。
我误解了什么,还是文档或实现错误?
我在{SciPy 1.1.0,Python 3.6.5}和{SciPy 1.2.0,Python 3.7.1}下都遇到了这个问题。
答案 0 :(得分:2)
我希望第一个(max_nfev = None)和最后一个(max_nfev = 100 * len(x))调用花费的时间大致相同
在scipy.optimize._lsq.trf.py的第250行设置一个断点:
if max_nfev is None:
max_nfev = x0.size * 100
此时x0
只有两个元素,因此传入None
的呼叫可以等效地传入200。x0
来自p0
,默认为[1 0]
。
基于此,您观察到的时间安排做到有意义。