Python 为什么scipy.optimize.root使用初始值调用回调函数四次?
我正在玩Python 为什么scipy.optimize.root使用初始值调用回调函数四次?,python,scipy,equation-solving,Python,Scipy,Equation Solving,我正在玩scipy.optimize.root,我试图了解它的功能和工作原理 我的示例代码如下: import numpy as np from scipy.optimize import root def func(x): """ test function x + 2 * np.cos(x) = 0 """ f = x + 2 * np.cos(x) print x,f return f def main(): sol = root(fun
scipy.optimize.root
,我试图了解它的功能和工作原理
我的示例代码如下:
import numpy as np
from scipy.optimize import root
def func(x):
""" test function x + 2 * np.cos(x) = 0 """
f = x + 2 * np.cos(x)
print x,f
return f
def main():
sol = root(func, 0.3)
if __name__ == "__main__":
main()
使用func中的print语句,我得到以下输出:
[ 0.3] [ 2.21067298]
[ 0.3] [ 2.21067298]
[ 0.3] [ 2.21067298]
[ 0.3] [ 2.21067298]
[-5.10560121] [-4.33928627]
[-1.52444136] [-1.43176461]
[-0.80729233] [ 0.57562174]
[-1.01293614] [ 0.0458079]
[-1.03071618] [-0.0023067]
[-1.02986377] [ 7.49624786e-06]
[-1.02986653] [ 1.20746968e-09]
[-1.02986653] [ -6.66133815e-16]
到目前为止还不错。我现在想知道为什么它会用初始值调用四次?多谢各位 它们实际上是不一样的。一个潜在的方法是改变这个问题 从那时起输出
[0.3] [2.210672978251212]
[0.3] [2.210672978251212]
[0.3] [2.210672978251212]
[0.300000004470348] [2.210672980079404]
...
在这种情况下,我们很幸运:ε变化可能仍然低于我们的机器精度,我们什么也看不到
编辑
答案是用fortran语言。
通过在源代码中搜索“call fcn(n,x)”,它看起来像函数是:
nprint>0
请求时调用,以启用迭代的打印If随后表示,现在已“打开”迭代打印,并开始雅可比矩阵的数值(和打印)估计。您没有提供雅可比矩阵信息,因此使用了so。因此调用
func
的次数高于内部迭代计数
这也意味着,第一个x值不相同,但接近机器精度。将numpy的printoptions更改为precision=15
不足以观察到这一点
默认的优化器是,文档说:
每股收益:浮动
雅可比矩阵正向差分近似的合适步长(对于fprime=None)。如果eps小于机器精度,则假定函数中的相对误差为机器精度的数量级
编辑:看来我错了!
print(x,f)
print('hash x: ', hash(x[0].item()))
输出:
这些看起来确实是相同的数字(如果在
散列中没有隐藏的魔力)!如果需要一些不缓存的设置(scipy.optimize cache x-arguments的某些部分),可能需要查看内部结构.根查找例程首先将调用一个函数,该函数将调用以初始值传入的函数。(第一次求值)
然后默认值(即您正在使用的)将调用其内部MINPACK例程,该例程将在开始时计算一次(在初始值处进行第二次计算)。然后hybrd
调用以查找此位置处的近似雅可比数。这需要两次计算,一次在值本身(第三次!),另一个在前面一步,这是第四个电话,有一个稍微不同的论点,正如卡纳克的回答所解释的
编辑:当调用函数的成本很高时,重复的回调求值可能是非常不可取的。如果是这种情况,则可以对函数进行修改,从而避免使用相同的输入重复求值,而无需打开数值例程的黑盒。对于纯函数,记忆可以很好地工作(即无副作用的函数),这在将数值函数传递到根查找或最小化例程时通常是如此。虽然我不反对@Kanak,但我不会说“它们显然超过8”@AGNGazer.是的。我不是一个以英语为母语的人。对我来说,尽可能清楚地表达出来是很费劲的。抱歉。你可以通过计算7./3-4./3-1
来获得机器精度。好吧,现在我们可以看到初始值只重复了三次。但问题仍然存在:为什么是三次?为什么?它只是显示了比t更高的值他需要(离散地)计算出更改的精度优于我们的机器精度。@卡纳克什么?哈希将使用该浮点的所有字节。如果有一位不同,则应该在输出中看到它(很有可能).我必须承认我没有检查浮点的散列impl,但在中,我不认为它们在进行取整或做任何这些事情。是的。我知道。这就是我所说的。数字确实是一样的。但理论上它们是不同的。提高机器精度会表明这一点。也许你比我更了解内部。但是使用a-priori set eps,它会导致向量的1:1位副本应该被缓存或动态调整(没有信息增益)。现在可能有这样的原因,但可能实现缺少这一点。你有最好的主意:首先查看源代码。+1
print(x,f)
print('hash x: ', hash(x[0].item()))
[0.3] [2.21067298]
hash x: 691752902764108160
[0.3] [2.21067298]
hash x: 691752902764108160
[0.3] [2.21067298]
hash x: 691752902764108160
[0.3] [2.21067298]
hash x: 691752913072029696