简体   繁体   English

查找用户定义函数的局部最大值和最小值

[英]Finding local maxima and minima of user defined functions

What I want 我想要的是

I want to find a list of the stationary points, of their values and locations, and of whether they are minima or maxima. 我想找到固定点的列表,它们的值和位置以及它们是最小值还是最大值。

My function looks like: 我的功能看起来像:

import numpy as np

def func(x,y):
  return (np.cos(x*10))**2 + (np.sin(y*10))**2

Methods 方法

Here are methods that I am thinking of using: 这是我正在考虑使用的方法:

  1. I am actually already doing something like this on Mathematica. 我实际上已经在Mathematica上做了类似的事情。 I differentiate the function once and then twice. 我一次又一次地区分函数。 I look at the points where the first derivative is 0, compute their values and their locations. 我看一下一阶导数为0的点,计算它们的值和位置。 Then I take the second derivative at those locations and check whether they are minima or maxima. 然后,我在那些位置取二阶导数,并检查它们是最小值还是最大值。

  2. I am also wondering whether just making a 2D array of the values of the function in x and y, and find the maximum and minimum values of that array. 我还想知道是否仅对x和y中的函数值进行2D数组化,并找到该数组的最大值和最小值。 But this requires me to know how finely to define the x and y meshgrids to reliably capture the behaviour of the function 但这需要我知道如何精确地定义x和y网格,以可靠地捕获函数的行为

For the latter case I already found some ways like this one . 对于后一种情况下,我已经找到像某些方面这一个

I just wanted to know, which method makes more sense in terms of efficiency, speed, accuracy or even elegance in Python? 我只是想知道,哪种方法在效率,速度,准确性甚至Python的优雅方面更有意义?

find a list of the stationary points, of their values and locations, and of whether they are minima or maxima. 查找固定点的列表,它们的值和位置以及它们是最小值还是最大值。

This is in general an unsolvable problem. 通常,这是一个无法解决的问题。 Method 1 (symbolic) is appropriate for that, but for complicated functions there is no symbolic solution for stationary points (there is no method for solving a general system of two equations symbolically). 方法1(符号化)适用于此,但对于复杂函数,没有针对固定点的符号解(没有用于符号化求解两个方程组的通用系统的方法)。

Symbolic solution with SymPy SymPy的符号解决方案

For simple functions like your example, SymPy will work fine. 对于像您的示例这样的简单功能, SymPy可以正常工作。 Here is a complete example of finding the stationary points and classifying them by the eigenvalues of the Hessian. 这是找到固定点并将其按黑森州特征值分类的完整示例。

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)))

So far, Hessian is a symbolic matrix 2 by 2: [[200*sin(10*x)**2 - 200*cos(10*x)**2, 0], [0, -200*sin(10*y)**2 + 200*cos(10*y)**2]] . 到目前为止,Hessian是2的符号矩阵2: [[200*sin(10*x)**2 - 200*cos(10*x)**2, 0], [0, -200*sin(10*y)**2 + 200*cos(10*y)**2]] Next, we find the stationary points by equating gradient to zero, and plug them into Hessian one by one. 接下来,我们通过将gradient等于零来找到固定点,并将它们逐一插入到Hessian中。

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))

The last clause is necessary because when the Hessian is only semi definite, we cannot tell what kind of stationary point is that ( x**2 + y**4 and x**2 - y**4 have the same Hessian at (0, 0) but different behavior). 最后一个子句是必需的,因为当Hessian仅是定点时,我们不能说出( x**2 + y**4x**2 - y**4在( 0,0),但行为不同)。 The output: 输出:

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

Obviously, solve did not find all solutions (there are infinitely many of those). 显然, solve方案并没有找到所有解决方案(其中有无限多个)。 Consider solve vs solveset but in any case, handling infinitely many solutions is hard. 考虑解决方案vs解决方案集,但是在任何情况下,要无限地处理许多解决方案都很难。

Numeric optimization with SciPy 使用SciPy进行数值优化

SciPy offers a lot of numerical minimization routines , including brute force (which is your method 2; generally it's very very slow). SciPy提供了许多数值最小化例程 ,包括蛮力 (这是您的方法2;通常非常慢)。 These are powerful methods, but consider these points. 这些是有效的方法,但请考虑以下几点。

  1. Each run will only find one minimum. 每次运行只会找到一个最小值。
  2. Replacing f with -f you can also find a maximum. 用-f替换f,您还可以找到最大值。
  3. Changing the starting point of the search (argument x0 of minimize ) may yield another maximum or minimum. 改变搜索(的参数X0的开始点minimize )可产生另一最大值或最小值。 Still, you'll never know if there are other extrema that you have not seen yet. 不过,您永远不会知道您是否还没有看到其他极值。
  4. None of this will find saddle points. 这些都找不到鞍点。

Mixed strategy 混合策略

Using lambdify one can turn a symbolic expression into a Python function that can be passed to SciPy numeric solvers. 使用lambdify可以将符号表达式转换为Python函数,该函数可以传递给SciPy数字求解器。

from scipy.optimize import fsolve
grad = sym.lambdify((x, y), gradient)
fsolve(lambda v: grad(v[0], v[1]), (1, 2))

This returns some stationary point, [0.9424778 , 2.04203522] in this example. 这将返回一些固定点,在此示例中为[0.9424778 , 2.04203522] Which point it is depends on the initial guess, which was (1, 2). 它在哪一点取决于最初的猜测,即(1、2)。 Typically (but not always) you'll get a solution that's near the initial guess. 通常(但并非总是如此),您将获得接近最初猜测的解决方案。

This has an advantage over the direct minimization approach in that saddle points can be detected as well. 与直接最小化方法相比,这具有一个优势,即可以检测到鞍点。 Still, it is going to be hard to find all solutions, as each run of fsolve brings up only one. 尽管如此,要找到所有解决方案还是很困难的,因为每一次fsolve只会带来一个解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM