2016-06-28 86 views
3

我在學習工作中實現了一個基本的最近鄰居搜索。 事實上,基本的numpy實現運行良好,但只是添加'@jit'裝飾器(在Numba中編譯),輸出是不同的(它由於某些未知原因而複製了一些鄰居......)numba輸出的差異

這是基本的算法:

import numpy as np 
from numba import jit 

@jit(nopython=True) 
def knn(p, points, k): 
    '''Find the k nearest neighbors (brute force) of the point p 
    in the list points (each row is a point)''' 

    n = p.size # Lenght of the points 
    M = points.shape[0] # Number of points 
    neighbors = np.zeros((k,n)) 
    distances = 1e6*np.ones(k) 

    for i in xrange(M): 
     d = 0 
     pt = points[i, :] # Point to compare 
     for r in xrange(n): # For each coordinate 
      aux = p[r] - pt[r] 
      d += aux * aux 
     if d < distances[k-1]: # We find a new neighbor 
      pos = k-1 
      while pos>0 and d<distances[pos-1]: # Find the position 
       pos -= 1 
      pt = points[i, :] 
      # Insert neighbor and distance: 
      neighbors[pos+1:, :] = neighbors[pos:-1, :] 
      neighbors[pos, :] = pt 
      distances[pos+1:] = distances[pos:-1] 
      distances[pos] = d 

    return neighbors, distances 

來進行測試:

p = np.random.rand(10) 
points = np.random.rand(250, 10) 
k = 5 
neighbors = knn(p, points, k) 

沒有@jit裝飾,可以得到正確的答案:

In [1]: distances 
Out[1]: array([ 0.3933974 , 0.44754336, 0.54548715, 0.55619749, 0.5657846 ]) 

但Numba編譯給人怪異的輸出:

Out[2]: distances 
Out[2]: array([ 0.3933974 , 0.44754336, 0.54548715, 0.54548715, 0.54548715]) 

有人能幫忙嗎?我不知道爲什麼會發生...

謝謝你。

+0

你可能有興趣在SciPy的[KDTree](http://docs.scipy.org/doc/scipy/ reference/generated/scipy.spatial.cKDTree.html)實現。 – Daniel

+0

@Ophion感謝您的提示。我一直在玩sklearn的KDTree實現(我猜它們是相似的),它們對預處理未來多個查詢點的數據非常有用。在我的工作中,我需要找到鄰居總是改變點列表(在圖像處理中),而這種實現變得太慢了。而且,當空間維數很大(例如大於25)時,似乎KDTree的實現並不比蠻力更好。 –

回答

1

我相信問題在於Numba正在處理將一個片段寫入另一個片段,當這些片段重疊時與不存在時重疊。我不熟悉numpy的內部,但也許有特殊的邏輯來處理像這樣的易失性內存操作,這在Numba中是不存在的。更改以下行,結果與JIT裝飾成爲純Python版本一致:

neighbors[pos+1:, :] = neighbors[pos:-1, :].copy() 
... 
distances[pos+1:] = distances[pos:-1].copy() 
+0

謝謝@JoshAdel! 這適用於我。我之前驗證過,Numpy中的這個重疊切片不會導致問題,但由於某些原因,Numba將它轉換爲另一種算法... 在所有情況下,它只是重複一些鄰居而不是其他人... 再次感謝! PD:我是python的粉絲,但這樣的事情讓我認真思考學習Julia ...... –

+0

@MarioGonzález我鼓勵你在Numba github問題跟蹤器上發佈你的例子作爲問題。開發團隊通常非常敏感,並且想知道錯誤或意外行爲。 – JoshAdel

+0

感謝@JoshAdel的建議。它發佈在[這裏](https://github.com/numba/numba/issues/1960)。 –