在 scipy 上寻求与 optimize.fmin 的融合
seeking convergence with optimize.fmin on scipy
我有一个函数想用 scipy.optimize.fmin
最小化。请注意,我在计算函数时强制使用 print
。
我的问题是,当我开始最小化时,打印的值会减少,直到达到某个点(值 46700222.800)。在那里它继续减少非常小的咬合,例如 46700222.797,46700222.765,46700222.745,46700222.699,46700222.688,46700222.678
所以直觉上,我觉得我已经达到了最小值,因为每一步的长度都减去 1。但是算法保持 运行 直到我得到一个“Maximum number of function evaluations has been exceeded
”错误。
我的问题是:当函数评估达到一个不再真正进化的值时,我如何强制我的算法接受参数值(假设,我在之后获得的收益不超过 1一次迭代)。我读到选项 ftol
可以使用,但它对我的代码绝对没有影响。事实上,我什至不知道 ftol
的值是多少。我尝试了从 0.00001 到 10000 的一切,仍然没有收敛。
从 documentation 看来您确实想要更改 ftol
参数。
Post 您的代码,以便我们查看您的进度。
编辑:也尝试增加 xtol
。
你的问题有点模棱两可。您是打印函数的值还是计算函数的点?
我对xtol
和ftol
的理解如下。迭代停止
- 当迭代之间函数值的变化小于
ftol
和
- 当连续迭代之间
x
的变化小于 xtol
当您说“...接受参数的值...”时,这表明您应该更改 xtol
。
我刚刚花了三个小时深入研究 scipy.minimize 的源代码。其中,函数“_minimize_neldermead”中的"while"循环处理收敛规则:
if (numpy.max(numpy.ravel(numpy.abs(sim[1:] - sim[0]))) <= xtol and
numpy.max(numpy.abs(fsim[0] - fsim[1:])) <= ftol):
break"
"fsim" 是存储功能评估结果的变量。但是,我发现 fsim[0] = f(x0) 是初始值的函数评估,并且在 "while" 循环期间它永远不会改变。 fsim[1:] 一直在自我更新。 while 循环的第二个条件永远不会满足。这可能是一个错误。但是我的数学优化知识远远不足以判断它。
我目前的解决方案:设计自己的系统来控制收敛。将此添加到您的函数中:
global x_old, Q_old
if (np.absolute(x_old-x).sum() <= 1e-4) and (np.absolute(Q_old-Q).sum() <= 1e-4):
return None
x_old = x; Q_old = Q
这里Q=f(x)。不要忘记给它们一个初始值。
2015 年 1 月 30 日更新:
我知道了!这应该是 if 函数第二行的正确代码(即删除 numpy.absolute):
numpy.max(fsim[0] - fsim[1:]) <= ftol)
btw,这是我第一次调试开源软件。我刚刚在 GitHub 上创建了一个 issue。
2015 年 1 月 31 日更新 - 1:
我认为我之前的更新不正确。尽管如此,这是使用原始代码迭代函数的屏幕截图。
它为每次迭代打印 sim 和 fsim 变量的值。正如您所看到的,每次迭代的变化都小于 xtol 和 ftol 值,但它一直在继续,没有停止。原始代码比较 fsim[0] 与其余 fsim 值之间的差异,即此处的值始终为 87.63228689 - 87.61312213 = .01916476,大于 ftol=1e-2。
2015 年 1 月 31 日更新 - 2:
这是我用来重现以前结果的 data and code。它包括两个数据文件和一个 iPython 笔记本文件。
实际上不需要看你的代码来解释发生了什么。我会引用你的话逐条回答。
My problem is, when I start the minimization, the value printed decreases
untill it reaches a certain point (the value 46700222.800). There it
continues to decrease by very small bites, e.g.,
46700222.797,46700222.765,46700222.745,46700222.699,46700222.688,46700222.678
请注意,最后两个值之间的差异是 -0.009999997913837433
,即大约 1e-2
。在最小化算法的约定中,你所说的值通常被标记为x
。如果在第 n
次迭代中同时满足这两个条件,算法将停止:
- 收敛于
x
:x[n]
与下一次迭代x[n+1]
的差值绝对值小于xtol
- 收敛于
f(x)
:f[n]
与f[n+1]
的差值绝对值小于ftol
.
此外,如果达到最大迭代次数,算法也会停止。
现在请注意,xtol
默认值为 1e-4
,比您的案例显示的值 1e-2
小 100
倍。然后算法不会停止,因为 xtol
上的第一个条件没有得到遵守,直到达到最大迭代次数。
I read that the options ftol could be used but it has absolutely no
effect on my code. In fact, I don't even know what value to put for
ftol. I tried everything from 0.00001 to 10000 and there is still no
convergence.
这帮助您满足 ftol
上的第二个条件,但同样从未达到第一个条件。
为了达到你的目标,还要增加 xtol
。
在调试优化例程的收敛性时,以下方法也将在一般情况下为您提供更多帮助。
- 在你想要最小化的函数中,在返回之前打印
x
的值和f(x)
的值。然后 运行 优化例程。从这些印刷品中,您可以确定 xtol
和 ftol
. 的合理值
- 考虑将问题无量纲化。
ftol
和 xtol
都默认为 1e-4
是有原因的。他们希望您制定问题,使 x
和 f(x)
的顺序为 O(1)
或 O(10)
,比如 -100
和 +100
之间的数字。如果您执行无量纲化,您会处理一个更简单的问题,因为您通常知道期望值是什么以及您所追求的公差是多少。
- 如果您只对粗略计算感兴趣而无法估计
xtol
和 ftol
的典型值,并且您知道(或希望)您的问题表现良好,即它会收敛,你可以 运行 fmin
在 try
块中,仅传递给 fmin
maxiter=20
(例如),并捕获有关 Maximum number of function evaluations has been exceeded
.
我有一个函数想用 scipy.optimize.fmin
最小化。请注意,我在计算函数时强制使用 print
。
我的问题是,当我开始最小化时,打印的值会减少,直到达到某个点(值 46700222.800)。在那里它继续减少非常小的咬合,例如 46700222.797,46700222.765,46700222.745,46700222.699,46700222.688,46700222.678
所以直觉上,我觉得我已经达到了最小值,因为每一步的长度都减去 1。但是算法保持 运行 直到我得到一个“Maximum number of function evaluations has been exceeded
”错误。
我的问题是:当函数评估达到一个不再真正进化的值时,我如何强制我的算法接受参数值(假设,我在之后获得的收益不超过 1一次迭代)。我读到选项 ftol
可以使用,但它对我的代码绝对没有影响。事实上,我什至不知道 ftol
的值是多少。我尝试了从 0.00001 到 10000 的一切,仍然没有收敛。
从 documentation 看来您确实想要更改 ftol
参数。
Post 您的代码,以便我们查看您的进度。
编辑:也尝试增加 xtol
。
你的问题有点模棱两可。您是打印函数的值还是计算函数的点?
我对xtol
和ftol
的理解如下。迭代停止
- 当迭代之间函数值的变化小于
ftol
和
- 当连续迭代之间
x
的变化小于xtol
当您说“...接受参数的值...”时,这表明您应该更改 xtol
。
我刚刚花了三个小时深入研究 scipy.minimize 的源代码。其中,函数“_minimize_neldermead”中的"while"循环处理收敛规则:
if (numpy.max(numpy.ravel(numpy.abs(sim[1:] - sim[0]))) <= xtol and
numpy.max(numpy.abs(fsim[0] - fsim[1:])) <= ftol):
break"
"fsim" 是存储功能评估结果的变量。但是,我发现 fsim[0] = f(x0) 是初始值的函数评估,并且在 "while" 循环期间它永远不会改变。 fsim[1:] 一直在自我更新。 while 循环的第二个条件永远不会满足。这可能是一个错误。但是我的数学优化知识远远不足以判断它。
我目前的解决方案:设计自己的系统来控制收敛。将此添加到您的函数中:
global x_old, Q_old
if (np.absolute(x_old-x).sum() <= 1e-4) and (np.absolute(Q_old-Q).sum() <= 1e-4):
return None
x_old = x; Q_old = Q
这里Q=f(x)。不要忘记给它们一个初始值。
2015 年 1 月 30 日更新: 我知道了!这应该是 if 函数第二行的正确代码(即删除 numpy.absolute):
numpy.max(fsim[0] - fsim[1:]) <= ftol)
btw,这是我第一次调试开源软件。我刚刚在 GitHub 上创建了一个 issue。
2015 年 1 月 31 日更新 - 1:
我认为我之前的更新不正确。尽管如此,这是使用原始代码迭代函数的屏幕截图。
它为每次迭代打印 sim 和 fsim 变量的值。正如您所看到的,每次迭代的变化都小于 xtol 和 ftol 值,但它一直在继续,没有停止。原始代码比较 fsim[0] 与其余 fsim 值之间的差异,即此处的值始终为 87.63228689 - 87.61312213 = .01916476,大于 ftol=1e-2。
2015 年 1 月 31 日更新 - 2: 这是我用来重现以前结果的 data and code。它包括两个数据文件和一个 iPython 笔记本文件。
实际上不需要看你的代码来解释发生了什么。我会引用你的话逐条回答。
My problem is, when I start the minimization, the value printed decreases untill it reaches a certain point (the value 46700222.800). There it continues to decrease by very small bites, e.g., 46700222.797,46700222.765,46700222.745,46700222.699,46700222.688,46700222.678
请注意,最后两个值之间的差异是 -0.009999997913837433
,即大约 1e-2
。在最小化算法的约定中,你所说的值通常被标记为x
。如果在第 n
次迭代中同时满足这两个条件,算法将停止:
- 收敛于
x
:x[n]
与下一次迭代x[n+1]
的差值绝对值小于xtol
- 收敛于
f(x)
:f[n]
与f[n+1]
的差值绝对值小于ftol
.
此外,如果达到最大迭代次数,算法也会停止。
现在请注意,xtol
默认值为 1e-4
,比您的案例显示的值 1e-2
小 100
倍。然后算法不会停止,因为 xtol
上的第一个条件没有得到遵守,直到达到最大迭代次数。
I read that the options ftol could be used but it has absolutely no effect on my code. In fact, I don't even know what value to put for ftol. I tried everything from 0.00001 to 10000 and there is still no convergence.
这帮助您满足 ftol
上的第二个条件,但同样从未达到第一个条件。
为了达到你的目标,还要增加 xtol
。
在调试优化例程的收敛性时,以下方法也将在一般情况下为您提供更多帮助。
- 在你想要最小化的函数中,在返回之前打印
x
的值和f(x)
的值。然后 运行 优化例程。从这些印刷品中,您可以确定xtol
和ftol
. 的合理值
- 考虑将问题无量纲化。
ftol
和xtol
都默认为1e-4
是有原因的。他们希望您制定问题,使x
和f(x)
的顺序为O(1)
或O(10)
,比如-100
和+100
之间的数字。如果您执行无量纲化,您会处理一个更简单的问题,因为您通常知道期望值是什么以及您所追求的公差是多少。 - 如果您只对粗略计算感兴趣而无法估计
xtol
和ftol
的典型值,并且您知道(或希望)您的问题表现良好,即它会收敛,你可以 运行fmin
在try
块中,仅传递给fmin
maxiter=20
(例如),并捕获有关Maximum number of function evaluations has been exceeded
.