python - scipy.optimize.curve_fit:max_nfev 的默认值坏了?
问题描述
scipy.optimize.curve_fit
使用max_nfev
参数调用时,我遇到了意外行为。该文档指出,额外kwargs
的被传递给leastsq
formethod='lm'
和least_squares
other。此外,如果提供,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 KB) 中的数据集,您可以在此处下载。
在我的系统上,这个脚本的输出是
以 max_nfev = None 运行:
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} 下都遇到了这种情况。
解决方案
我希望第一个 (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]
。
基于此,您观察到的时间确实有意义。
推荐阅读
- javascript - Firebase:无法将电话号码与其他 AuthProviders javascript 链接
- java - Hibernate 和单表继承的问题
- next.js - 如何在 Next.js 中渲染 KaTex
- dafny - 在 Dafny 中删除特定索引处的元素失败
- scala - 如何使用 scalapb 在 proto 中描述 Option[FiniteDuration]
- ada - 如何在 Ada 中处理闰年
- linux - 使用 vcpkg 安装 ffmpeg
- while-loop - 如何创建生日计数器?
- list - 从包含列表的字典创建枚举列表
- html - 表格边框 CSS