2016-05-14 106 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