寻求与scipy上的optimize.fmin融合

时间:2015-01-27 10:00:18

标签: python optimization 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的所有内容,但仍然没有收敛。

4 个答案:

答案 0 :(得分:6)

实际上没有必要看到你的代码来解释发生了什么。我会一点一点地回答你。

  

我的问题是,当我开始最小化时,打印的值会减少   直到达到某一点(值46700222.800)。在那里   通过非常小的咬伤继续减少,例如,   46700222.797,46700222.765,46700222.745,46700222.699,46700222.688,46700222.678

请注意,最后2个值之间的差异为-0.009999997913837433,即大约1e-2。在最小化算法的约定中,您所谓的值通常标记为x。如果在n次迭代的同一时间遵守这两个条件,算法就会停止:

  • x上的收敛:x[n]与下一次迭代x[n+1]之间差异的绝对值小于xtol
  • f(x)上的收敛:f[n]f[n+1]之间差异的绝对值小于ftol

此外,如果达到最大迭代次数,算法也会停止。

现在请注意,xtol默认值为1e-4,比您的案例中显示的值100小约1e-2倍。然后算法不会停止,因为xtol上的第一个条件没有得到遵守,直到达到最大迭代次数。

  

我读到可以使用选项ftol但它绝对没有   对我的代码有影响。事实上,我甚至不知道要付出什么价值   FTOL。我尝试了从0.00001到10000的所有东西,但仍然没有   收敛。

这有助于你尊重ftol的第二个条件,但是第一个条件再也没有达到。

为达到目标,请同时增加xtol

在调试优化例程的收敛时,以下方法也可以帮助您更多。

  • 在要最小化的函数内,在返回之前打印x的值和f(x)的值。然后运行优化例程。通过这些打印,您可以为xtolftol确定合理的值。
  • 考虑对问题进行无量纲化。如果ftolxtol默认为1e-4,则有一个原因。他们希望您制定问题,以便xf(x)具有订单O(1)O(10),例如-100+100之间的数字。如果你执行无量纲化,你会处理一个更简单的问题,就像你经常知道期望什么值以及你所追求的容忍度一样。
  • 如果您对粗略计算感兴趣并且无法估算xtolftol的典型值,并且您知道(或者您希望)您的问题表现良好,即它会聚,您可以在fmin块中运行try,仅传递给fmin maxiter=20(例如),并捕获有关Maximum number of function evaluations has been exceeded的错误。< / LI>

答案 1 :(得分:1)

我花了三个小时挖掘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)
不过,这是我对开源软件的第一次调试。我刚在GitHub上创建了一个issue

2015年1月31日更新 - 1 : 我不认为我以前的更新是正确的。然而,这是使用原始代码的函数迭代的屏幕截图。 enter image description here

它为每次迭代打印sim和fsim变量的值。正如您所看到的,每次迭代的变化都小于xtol和ftol值,但它只是不停地继续运行。原始代码比较fsim [0]和其余fsim值之间的差异,即此处的值始终为87.63228689 - 87.61312213 = .01916476,大于ftol = 1e-2。

2015年1月31日更新 - 2 : 这是我用来重现以前结果的data and code。它包括两个数据文件和一个iPython Notebook文件。

答案 2 :(得分:0)

documentation看起来您想要更改ftol arg。

发布您的代码,以便我们查看您的进度。 编辑:尝试增加xtol

答案 3 :(得分:0)

你的问题有点含糊不清。您是打印功能的值还是打印它的评估点?

我对xtolftol的理解如下。迭代停止

  • 当迭代之间的函数值的变化小于ftol

  • 当连续迭代之间x的变化小于xtol

当您说&#34; ...接受参数的值...&#34;时,这表明您应该更改xtol