【问题标题】:seeking convergence with optimize.fmin on scipy在 scipy 上寻求与 optimize.fmin 的收敛
【发布时间】:2015-01-27 10:00:17
【问题描述】:

我想用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 的所有值,但仍然没有收敛。

【问题讨论】:

  • 如 seth 所述,请发布代码,否则我们只能发送更多指向文档的链接。
  • 我可以将我的问题改写如下:有人知道 ftol 和 xtol 必须如何使用吗?有没有人知道当达到一定程度的非进化时如何强制收敛?这完全独立于任何代码。
  • 我在使用 Scipy 时遇到了完全相同的问题。我感到非常沮丧,以至于我将所有内容都翻译成 Matlab,与 Python 相比,它的代码对用户非常不友好,但它也遇到了同样的问题。也许优化器在某些情况下只是忽略了 xtol 和 ftol。
  • @Titanic,优化器不会忽略xtolftol,但需要停止对它们的两个约束。看我的回答。

标签: python optimization scipy


【解决方案1】:

实际上没有必要查看您的代码来解释正在发生的事情。引用你的话,我会逐点回答。

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

请注意,最后 2 个值之间的差异是 -0.009999997913837433,即大约 1e-2。在最小化算法的约定中,您所说的值通常标记为x。如果在n-th 迭代中同时满足这两个条件,则算法停止:

  • 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 的典型值,并且您知道(或希望)您的问题表现良好,即它会收敛,您可以在try 块中运行fmin,仅传递给fmin maxiter=20(比如说),并捕获有关Maximum number of function evaluations has been exceeded 的错误。

【讨论】:

  • 感谢您的帮助,现在我知道必须满足两个条件(xtol 和 ftol)才能停止该过程。请注意,这绝对不能从文档中理解。最后感谢您的提示,我当然知道我可以抓住错误,但我真的很想了解一次所有这些 xtol/ftol 的奥秘。我不得不说,我觉得这两个条件都需要在科学上非常奇怪。
  • 我同意文档可以写得更好,但并没有错:他们谈到了 x 和 ftol 的收敛中可接受的错误,这表明两者的收敛是必需的。至于为什么它们都被强制执行,算法策略默认情况下尽可能保守,并且会导致更少的误报,让您通过设置大的xtolftol 来放松对任一条件的约束.
【解决方案2】:

我只花了三个小时研究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

更新 01/31/15 - 1: 我不认为我之前的更新是正确的。然而,这是使用原始代码的函数迭代的屏幕截图。

它为每次迭代打印 sim 和 fsim 变量的值。如您所见,每次迭代的变化都小于 xtol 和 ftol 值,但它一直在不停地前进。原始代码比较了 fsim[0] 和其余 fsim 值的差异,即这里的值始终为 87.63228689 - 87.61312213 = .01916476,大于 ftol=1e-2。

更新 01/31/15 - 2: 这是我用来重现之前结果的data and code。它包括两个数据文件和一个 iPython Notebook 文件。

【讨论】:

  • 关于第一部分,请提供一个示例代码,其中fsim[0] 不会随时间变化。在您提到的循环结束时,fsim 实际上已更新,请参阅this 行。关于更新,我看不出在这种情况下删除 abs 有什么意义。
  • 稍后我会进一步研究。但是你自己试试,效果很好。
  • 1) 你怎么只有代码? OP没有发布任何代码。 2) 为什么在blp() 的代码中减少全局变量Delta?您不能更改 blp() 内的全局变量。如果你真的想的话,你可以读取blp() 中的一个全局变量。这就是为什么你有fmin这种奇怪的行为。
  • 天啊! @gg349,你成就了我的一天!我花了很多时间试图找出造成这种情况的原因。这是全局变量的问题。为了回答您的问题,1. OP 没有发布任何示例代码,我遇到的问题与 OP 完全相同,因此我发布了自己的代码,用于一个众所周知的经济学模型。
  • 2.在该模型中,对于每个 theta 值,需要找到适合该模型的 Delta 值。为了使其更快,将给定每个 theta 的 Delta 的初始值设置为给定前一个 theta 的 Delta 值。我减少它只是为了使 Delta_New 和 Delta 具有不同的初始值,以便 while 循环开始工作。我肯定需要更多地研究全局变量的工作原理。
【解决方案3】:

documentation 看来,您确实想更改 ftol 参数。

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

【讨论】:

  • 正如我在帖子中所说,我尝试更改 arg ftol 但它没有帮助。事实上,它对收敛完全没有影响。我什至不知道它是否是一个介于 0 和 1 之间的常数。
【解决方案4】:

你的问题有点模棱两可。您是在打印函数的值,还是在计算它的点?

我对@9​​87654321@和ftol的理解如下。迭代停止

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

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

当您说“...接受参数的值...”时,这表明您应该更改xtol

【讨论】:

  • 抱歉含糊不清。每次评估时,我都会打印函数的值。我希望算法在函数值变化小于某个值时接受参数。所以我绝对应该使用 ftol。事实是,这个 ftol 根本不起作用,因为当我将 ftol 从 0.000001 变为 1000000 时,这个过程绝对没有区别。根据您的理解,如果我输入 ftol = 10000000,算法应该立即接受我的参数。但事实并非如此。
  • @FuzzyDuck,这个答案是错误的。必须同时满足这两个条件才能使算法停止。
  • 感谢您的澄清。答案已修改。
猜你喜欢
  • 1970-01-01
  • 2011-04-24
  • 2019-09-01
  • 2019-03-12
  • 2019-06-06
  • 2021-10-16
  • 2012-07-07
  • 1970-01-01
  • 2013-10-04
相关资源
最近更新 更多