[英]seeking convergence with optimize.fmin on scipy
我有一个我想用scipy.optimize.fmin
最小化的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的所有内容,但仍然没有收敛。
实际上没有必要看到你的代码来解释发生了什么。 我会一点一点地回答你。
我的问题是,当我开始最小化时,打印的值会减少,直到达到某个点(值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
,比您的案例中显示的值1e-2
小约100
倍。 然后算法不会停止,因为xtol
上的第一个条件没有得到遵守,直到达到最大迭代次数。
我读到可以使用选项ftol,但它对我的代码完全没有影响。 事实上,我甚至不知道为ftol提供什么价值。 我尝试了从0.00001到10000的所有内容,但仍然没有收敛。
这有助于你尊重ftol
的第二个条件,但是从来没有达到第一个条件。
为了达到你的目标,也增加xtol
。
在调试优化例程的收敛时,以下方法也将对您有所帮助。
x
的值和f(x)
的值。 然后运行优化例程。 从这些打印中,您可以确定xtol
和ftol
合理值。 ftol
和xtol
默认为1e-4
则有一个原因。 他们希望你制定问题,使x
和f(x)
的顺序为O(1)
或O(10)
,比如介于-100
和+100
之间。 如果你执行无量纲化,你会遇到一个更简单的问题,就像你经常知道期望什么值以及你所遵循的容差一样。 xtol
和ftol
典型值,并且您知道(或者您希望)您的问题表现良好,即它会收敛,您可以在try
块中运行fmin
,传递给fmin
只有maxiter=20
(比如说),并且捕获了有关Maximum number of function evaluations has been exceeded
的错误。 我花了三个小时挖掘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上创建了一个问题 。
2015年1月31日更新 - 1 :我不认为我以前的更新是正确的。 然而,这是使用原始代码的函数迭代的屏幕截图。
它为每次迭代打印sim和fsim变量的值。 正如您所看到的,每次迭代的变化都小于xtol和ftol值,但它只是不停地继续运行。 原始代码比较fsim [0]和其余fsim值之间的差异,即此处的值始终为87.63228689 - 87.61312213 = .01916476,大于ftol = 1e-2。
2015年1月31日更新 - 2 :这是我用来重现以前结果的数据和代码 。 它包括两个数据文件和一个iPython Notebook文件。
从文档中看起来你想要改变ftol
arg。
发布您的代码,以便我们查看您的进度。 编辑:尝试增加xtol
。
你的问题有点含糊不清。 您是打印功能的值还是打印它的评估点?
我对xtol
和ftol
理解如下。 迭代停止
ftol
和
x
变化小于xtol
当你说“...接受参数的值...”时,这表明你应该改变xtol
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.