zep*_*hyr 2 python algorithm minimize scipy
给定2D点p
,我试图计算该点与功能曲线之间的最小距离,即找到曲线上的点,该点给出最小距离p
,然后计算该距离.我正在使用的示例函数是
f(x) = 2*sin(x)
Run Code Online (Sandbox Code Playgroud)
我的距离函数用于某个点p
和提供的函数之间的距离
def dist(p, x, func):
x = np.append(x, func(x))
return sum([[i - j]**2 for i,j in zip(x,p)])
Run Code Online (Sandbox Code Playgroud)
它作为输入,点p
,x
函数上的位置和函数句柄func
.注意这是一个平方欧几里德距离(因为欧几里德空间中的最小化与平方欧几里德空间中的最小化相同).
这个的关键部分是我希望能够为我的函数提供边界,所以我真的找到了与函数段最近的距离.对于这个例子,我的界限是
bounds = [0, 2*np.pi]
Run Code Online (Sandbox Code Playgroud)
我正在使用该scipy.optimize.minimize
函数来最小化我的距离函数,使用边界.上述过程的结果如下图所示.
这是显示距sin函数的距离的等高线图.请注意轮廓中是否存在不连续性.为方便起见,我在不连续点和它们映射到的曲线上的"壁橱"点上绘制了几个点.
这里实际发生的是scipy函数是找到局部最小值(给出一些初始猜测),但不是全局函数,这导致了不连续性.我知道找到任何函数的全局最小值是不可能的,但我正在寻找一种更可靠的方法来找到全局最小值.
找到全局最小值的可能方法是
有关最佳方法的任何建议,或可能解决这个问题的有用功能的方向都会很棒!
正如评论中建议的那样,您可以尝试全局优化算法,例如scipy.optimize.differential_evolution
.但是,在这种情况下,如果您具有明确且易于分析的目标函数,则可以采用半分析方法,充分利用一阶必要条件.
在下文中,第一个函数是距离度量,第二个函数是其导数wrt(的分子)x
,如果在某个函数中出现最小值,则该函数应为零0<x<2*np.pi
.
import numpy as np
def d(x, p):
return np.sum((p-np.array([x,2*np.sin(x)]))**2)
def diff_d(x, p):
return -2 * p[0] + 2 * x - 4 * p[1] * np.cos(x) + 4 * np.sin(2*x)
Run Code Online (Sandbox Code Playgroud)
现在,给定一点p
,唯一可能的最小化d(x,p)
是diff_d(x,p)
(如果有的话)的根,以及边界点x=0
和x=2*np.pi
.事实证明,diff_d
可能有多个根.注意到导数是一个连续函数,pychebfun库提供了一种非常有效的方法来查找所有根,避免了基于scipy
根查找算法的繁琐方法.
以下函数提供d(x, p)
给定点的最小值p
:
import pychebfun
def min_dist(p):
f_cheb = pychebfun.Chebfun.from_function(lambda x: diff_d(x, p), domain = (0,2*np.pi))
potential_minimizers = np.r_[0, f_cheb.roots(), 2*np.pi]
return np.min([d(x, p) for x in potential_minimizers])
Run Code Online (Sandbox Code Playgroud)
结果如下: