2016-05-14 392 views
2

给定一个二维点p,我试图计算该点和功能曲线之间的最小距离,即找到曲线上的点,它使我得到最小的距离p,然后计算该距离。我使用的示例函数是使用scipy.optimize.minimize查找全局最小值

f(x) = 2*sin(x) 

一些点p和提供功能之间的距离我的距离函数是

def dist(p, x, func): 
    x = np.append(x, func(x)) 
    return sum([[i - j]**2 for i,j in zip(x,p)]) 

它输入,点p,位置x在功能上,以及功能手柄func。请注意,这是一个平方欧几里得距离(因为欧几里得空间的最小化与平方欧几里德空间的最小化相同)。

这个关键部分是我希望能够为我的功能提供界限,所以我真的找到离功能段最近的距离。在这个例子中我的边界是

bounds = [0, 2*np.pi] 

我使用的scipy.optimize.minimize功能,以尽量减少我的距离函数,使用的范围。上述过程的结果如下图所示。

Contour plot of distance

是表示从sin函数距离的等高线图。注意轮廓中似乎存在不连续性。为了方便起见,我已经绘制了这些不连续点的几个点以及它们映射到的曲线上的“壁橱”点。

这里实际发生的事情是,scipy函数正在寻找一个局部最小值(给出一些初始猜测),但不是全局函数,并且这导致了不连续性。我知道找到任何函数的全局最小值是不可能的,但我正在寻找一种更可靠的方法来找到全局最小值。

查找全球最小的可能方法将是

  1. 选择一个聪明的初始猜测,但如果全球最小的是开始,这是使用问题的解决方案来解决这相当于知道约它。
  2. 使用多个初始猜测并选择达到最佳最小值的答案。然而,这似乎是一个糟糕的选择,特别是当我的功能变得更复杂(和更高维度)时。
  3. 找到最小值,然后扰动解,并再次找到最小值,希望我可能已经将其敲入更好的最小值。我希望也许有一些方法可以做到这一点,而不会引发一些复杂的MCMC算法或类似的东西。速度为这个过程计数。

任何有关如何去解决这个问题的最佳方法,或者可能的解决方法,都可以解决这个问题。

+0

4.使用模拟退火算法动机(或任何其他Metaheuristic)。也许将您的优化调用限制为非常低的迭代次数,获取解决方案并让SA决定是否接受此解决方案。再次优化5.使用不同的优化算法(随机选择或并行或竞争)。 6.尝试像ipopt,bonmin,couenne(最后一个是全球求解器) – sascha

回答

5

正如评论中的建议,您可以尝试全局优化算法,如scipy.optimize.differential_evolution。然而,在这种情况下,如果您有一个定义明确且易于分析的目标函数,则可以采用半分析方法,利用最小的一阶必要条件。

在下面,第一个函数是距离度量,第二个函数是它的导数w.r.t的(的分子)。 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) 

现在,给定一个点pd(x,p)唯一潜在极小是diff_d(x,p)根(如果有的话),以及边界点x=0x=2*np.pi。事实证明,diff_d可能有多个根。注意到衍生物是一个连续函数,pychebfun库提供了一种非常有效的方法来查找所有根,避免基于scipy根查找算法的繁琐方法。

下面的函数对于给定的点p提供最小的d(x, 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]) 

下面是结果:

enter image description here