Finding local maxima and minima of user defined functions
我想找到一个固定点的列表,它们的值和位置,以及它们是最小值还是最大值。
我的功能如下:
1 2 3 4 | import numpy as np def func(x,y): return (np.cos(x*10))**2 + (np.sin(y*10))**2 |
方法
以下是我想使用的方法:
实际上我已经在Mathematica上做了类似的事情。我将函数分一次,然后再分两次。我看一阶导数为0的点,计算它们的值和位置。然后在这些位置取二阶导数,检查它们是极小值还是极大值。
我还想知道,是否只制作一个以x和y为单位的函数值的二维数组,并找到该数组的最大值和最小值。但这需要我知道如何精确地定义x和y网格,以便可靠地捕获函数的行为。
对于后一种情况,我已经找到了类似这样的方法。
我只是想知道,在Python中,哪种方法在效率、速度、准确性甚至优雅方面更有意义?
find a list of the stationary points, of their values and locations, and of whether they are minima or maxima.
号
这通常是一个无法解决的问题。方法1(符号)适用于此,但对于复杂的函数,不存在静止点的符号解(没有符号解两个方程的一般系统的方法)。
符号解与辛对于像您的示例这样的简单函数,sympy可以正常工作。这是一个完整的例子,找到了平稳点,并根据黑森特征值对其进行分类。
1 2 3 4 5 | import sympy as sym x, y = sym.symbols("x y") f = sym.cos(x*10)**2 + sym.sin(y*10)**2 gradient = sym.derive_by_array(f, (x, y)) hessian = sym.Matrix(2, 2, sym.derive_by_array(gradient, (x, y))) |
到目前为止,Hessian是一个符号矩阵2:
1 2 3 4 5 6 7 8 9 10 11 12 13 | stationary_points = sym.solve(gradient, (x, y)) for p in stationary_points: value = f.subs({x: p[0], y: p[1]}) hess = hessian.subs({x: p[0], y: p[1]}) eigenvals = hess.eigenvals() if all(ev > 0 for ev in eigenvals): print("Local minimum at {} with value {}".format(p, value)) elif all(ev < 0 for ev in eigenvals): print("Local maximum at {} with value {}".format(p, value)) elif any(ev > 0 for ev in eigenvals) and any(ev < 0 for ev in eigenvals): print("Saddle point at {} with value {}".format(p, value)) else: print("Could not classify the stationary point at {} with value {}".format(p, value)) |
号
最后一个条款是必要的,因为当hessian只是半定的时候,我们不知道什么样的固定点是(
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Saddle point at (0, 0) with value 1 Local maximum at (0, pi/20) with value 2 Saddle point at (0, pi/10) with value 1 Local maximum at (0, 3*pi/20) with value 2 Local minimum at (pi/20, 0) with value 0 Saddle point at (pi/20, pi/20) with value 1 Local minimum at (pi/20, pi/10) with value 0 Saddle point at (pi/20, 3*pi/20) with value 1 Saddle point at (pi/10, 0) with value 1 Local maximum at (pi/10, pi/20) with value 2 Saddle point at (pi/10, pi/10) with value 1 Local maximum at (pi/10, 3*pi/20) with value 2 Local minimum at (3*pi/20, 0) with value 0 Saddle point at (3*pi/20, pi/20) with value 1 Local minimum at (3*pi/20, pi/10) with value 0 Saddle point at (3*pi/20, 3*pi/20) with value 1 |
显然,
Scipy提供了很多数值最小化的程序,包括蛮力(这是您的方法2;通常非常慢)。这些方法很有效,但要考虑这些要点。
混合策略
使用
1 2 3 | from scipy.optimize import fsolve grad = sym.lambdify((x, y), gradient) fsolve(lambda v: grad(v[0], v[1]), (1, 2)) |
。
这将返回一个固定点,在本例中是
与直接最小化方法相比,这有一个优点,即可以检测鞍点。不过,很难找到所有的解决方案,因为每次运行