Python 如何用scipy精确计算局部极小值?

Python 如何用scipy精确计算局部极小值?,python,scipy,mathematical-optimization,Python,Scipy,Mathematical Optimization,我们要计算函数的局部极小值 f = lambda x: x*x 使用python的scipy: scipy.optimize.minimize(f,-10,method='powell',options={'xtol':1e-50}) 我明白了 局部最小点1.0658141036401503e-14不够好。我的问题是: 既然我已经把xtol设为1e-50,这意味着相对误差的阈值,为什么我的结果仍然是顺序1e-14?,正如约翰·兹温克、泽尔和乔恩·卡斯特指出的那样:数字已经用完了。为了证明这一

我们要计算函数的局部极小值

f = lambda x: x*x
使用python的scipy:

scipy.optimize.minimize(f,-10,method='powell',options={'xtol':1e-50})
我明白了

局部最小点
1.0658141036401503e-14
不够好。我的问题是:

既然我已经把xtol设为1e-50,这意味着相对误差的阈值,为什么我的结果仍然是顺序
1e-14

,正如约翰·兹温克、泽尔和乔恩·卡斯特指出的那样:数字已经用完了。为了证明这一点,让我们替换为
x=zz[0]+zz[1]*1e-8
,因此
f(x)=x*x=zz[0]*zz[0]+2*zz[0]*zz[1]*1e-8+zz[1]*1e-16
,这将产生以下代码:

import scipy.optimize as sopt
import numpy as np

f = lambda zz: zz[0]*zz[0] + 2*zz[0]*zz[1]*1e-8 + zz[1]*zz[1]*1e-16

zz0 = np.array([-10, 0])
rr = sopt.minimize(f, zz0, method='powell')
print("argmin(x**2) = {}".format(rr.x[0] + rr.x[1]*1e-8))
# Output: argmin(x**2) = -1.22858775101e-25
通常,人们会认为二维问题的收敛性比行为良好的一维问题差。在这里,第二个维度增加了有效位数。我选择
1e-8
作为
2.2e-16
的机器ε的平方根。改变这一因素,表明鲍威尔算法的这种实现显然在小浮点数方面存在问题


正如已经在评论中写到的:更聪明的方法是使用更适合的解算器。如果需要大量数字,请退出。

如果将
方法更改为
SLSQP
,则会得到准确的结果(0)。“那有用吗?”约翰。谢谢我用f(x)=x*x作为一个非常简单的例子。我猜SLSQP只适用于两次连续可微函数?这很公平。我怀疑您在这里遇到了64位浮点精度的限制,但我不知道在实现中具体发生了什么。请参阅。
Powell
方法同时允许
ftol
xtol
。尝试将两者都降低到10^-50。如果这不起作用,我同意约翰·兹温克的评论。还有,你的机器epsilon是什么?@Curt F。如果我把ftol和'op.minimize(F,-10,method='powell',options={'xtol':1e-50,'ftol':1e-50}')放在一起,结果与只使用xtol的结果完全相同。我的马赫数是2.22e-16。
import scipy.optimize as sopt
import numpy as np

f = lambda zz: zz[0]*zz[0] + 2*zz[0]*zz[1]*1e-8 + zz[1]*zz[1]*1e-16

zz0 = np.array([-10, 0])
rr = sopt.minimize(f, zz0, method='powell')
print("argmin(x**2) = {}".format(rr.x[0] + rr.x[1]*1e-8))
# Output: argmin(x**2) = -1.22858775101e-25