2013-03-21 55 views
1

我有一個算法,其中:Python的雙變量搜索算法

  • 採用兩個輸入(X,Y),其中,x和y是在兩個獨立的泊松分佈(http://en.wikipedia.org/wiki/Poisson_distribution#Definition
  • 所述的lambda'變量
  • 計算泊松矢量用於每個x和y的,
  • 計算兩個泊松的矩陣乘積矢量
  • 返回[總和(upper_quadrant),總和(lower_quadrant),總和(對角線)]

所以:

import math, random 

def poisson(m, n): 
    p=math.exp(-m) 
    r=[p] 
    for i in range(1, n): 
     p*=m/float(i) 
     r.append(p) 
    return r 

def simulate(mx, my, n): 
    r=[0.0 for i in range(3)] 
    px, py = (poisson(mx, n), 
       poisson(my, n)) 
    for i in range(n): 
     for j in range(n): 
      if i > j: 
       k=0 
      elif i < j: 
       k=1 
      else: 
       k=2 
      r[k]+=px[i]*py[j] 
    return r 

現在,我需要解決的X和Y,給出一組特定的輸出。我已經砍死在一起下列求解器功能:

def solve(p, n, generations, decay, tolerance): 
    def rms_error(X, Y): 
     return (sum([(x-y)**2 
        for x, y in zip(X, Y)])/float(len(X)))**0.5 
    def calc_error(x, y, n, target): 
     guess=simulate(x, y, n) 
     return rms_error(target, guess)  
    q=[0, 0] 
    err=calc_error(math.exp(q[0]), math.exp(q[1]), n, p) 
    bestq, besterr = q, err 
    for i in range(generations): 
     if besterr < tolerance: 
      break 
     q=list(bestq) 
     if random.random() < 0.5: 
      j=0 
     else: 
      j=1 
     fac=((generations-i+1)/float(generations))**decay 
     q[j]+=random.gauss(0, 1)*fac 
     err=calc_error(math.exp(q[0]), math.exp(q[1]), n, p) 
     if err < besterr: 
      bestq, besterr = q, err 
      # print (i, bestq, besterr) 
    q, err = [math.exp(q) for q in bestq], besterr 
    return (i, q, err) 

其作品,但似乎需要比較大量的嘗試返回一個不是非常優化的響應:

if __name__=="__main__": 
    p, n = [0.5, 0.2, 0.3], 10 
    q, err = solve_match_odds(p, n, 
           generations=1000, 
           decay=2, 
           tolerance=1e-5) 
    print q 
    print simulate_match_odds(q[0], q[1], n) 
    print (i, err) 

和:

[email protected]ad-X220:~/work/$ python solve.py 
[0.5, 0.2, 0.3] 
[0.5000246335218251, 0.20006624338256798, 0.29990837191131686] 
(999, 6.680993630511076e-05) 
[email protected]:~/work/$ 

我不是CS專業,我覺得我錯過了這裏所有的搜索文獻。有人可以提出一個更好的方法來搜索像這樣的二維空間中的變量嗎?

謝謝。

回答

0

您可以使用scipy.optimize庫來解決這個問題:

import math, random 

def poisson(m, n): 
    p=math.exp(-m) 
    r=[p] 
    for i in range(1, n): 
     p*=m/float(i) 
     r.append(p) 
    return r 

def simulate(mx, my, n): 
    r=[0.0 for i in range(3)] 
    px, py = (poisson(mx, n), 
       poisson(my, n)) 
    for i in range(n): 
     for j in range(n): 
      if i > j: 
       k=0 
      elif i < j: 
       k=1 
      else: 
       k=2 
      r[k]+=px[i]*py[j] 
    return r 

from scipy import optimize 

Target, N = [0.5, 0.2, 0.3], 10 

def error(p, target, n): 
    r = simulate(p[0], p[1], n) 
    return np.sum(np.subtract(target, r)**2) 

r = optimize.fmin(error, (0, 0), args=(Target, N)) 
print simulate(r[0], r[1], n) 

輸出:

Optimization terminated successfully. 
     Current function value: 0.000000 
     Iterations: 67 
     Function evaluations: 125 
[0.49999812501285623, 0.20000418001288445, 0.2999969464616799] 
+0

不錯,但我應該補充說,它需要在AppEngine上https://developers.google工作。 com/appengine/docs/python/tools/libraries27 – Justin 2013-03-21 08:01:52

+0

您可以找到optimize.fmin()[here](http://www.mech.uq.edu.au/)使用的Nelder-Mead方法的Python源代碼實現。課程/ mech2700/python-code/nelmin.py),雖然我沒有親自測試過它。 – Simon 2013-03-21 08:48:44

+0

我仔細看了一下,你將不得不修改我稍微鏈接的代碼,以將額外的參數'n'和'target'傳遞給目標函數,但這不會有什麼大不了的,爲更少的功能評估提供更高精度的好處。 – Simon 2013-03-21 08:57:05