簡體   English   中英

Numpy數組比列表慢得多

[英]Numpy array is much slower than list

給定兩個矩陣X1(N,3136)和X2(M,3136)(其中每行中的每個元素都是二進制數)我試圖計算漢明距離,以便將X1中的每個元素與X2中的所有行進行比較,結果矩陣是(N,M)。

我為它寫了兩個函數(第一個是numpy的幫助,另一個沒有numpy):

def hamming_distance(X, X_train):
    array = np.array([np.sum(np.logical_xor(x, X_train), axis=1) for x in X])

    return array



def hamming_distance2(X, X_train):
    a = len(X[:,0])
    b = len(X_train[:,0])

    hamming_distance = np.zeros(shape=(a, b))

    for i in range(0, a):
        for j in range(0, b):
            hamming_distance[i,j] = np.count_nonzero(X[i,:] != X_train[j,:])

    return hamming_distance

我的問題是上部函數比下部函數慢得多,我使用兩個for循環 是否可以改進第一個功能,以便我只使用一個循環?

PS。 對不起我的英語,這不是我的第一語言,雖然我努力做到最好!

Numpy只會讓你的代碼更快,如果你用它來矢量化你的工作。 在您的情況下,您可以使用數組廣播來矢量化您的問題:比較您的兩個數組並創建一個形狀(N,M,K)的輔助數組,您可以沿其第三維求和:

hamming_distance = (X[:,None,:] != X_train).sum(axis=-1)

我們在第一個數組中注入單個維度以使其形狀(N,1,K) ,第二個數組與形狀(1,M,K)隱式兼容,因此可以執行操作。

在評論中@ayhan注意到這將為大MN創建一個巨大的輔助數組,這是非常正確的。 這是矢量化的代價:你以內存為代價獲得CPU時間。 如果你有足夠的內存使上面工作,它將非常快。 如果不這樣做,則必須縮小矢量化的范圍,並循環使用MN (或兩者;這將是您當前的方法)。 但這並不涉及numpy本身,這是關於在可用資源和性能之間取得平衡。

你在做什么與點積非常相似。 考慮這兩個二進制數組:

1 0 1 0 1 1 0 0
0 0 1 1 0 1 0 1

我們試圖找到不同對的數量。 如果您直接使用點積,它會給出(1,1)對的數量。 但是,如果你否定其中一個,它將計算不同的一個。 例如, a1.dot(1-a2)計數(1,0)對。 由於我們還需要(0,1)對的數量,我們將添加a2.dot(1-a1) 點積的好處在於它非常快。 但是, 正如Divakar指出的那樣 ,您需要首先將數組轉換為浮點數。

這是一個演示:

prng = np.random.RandomState(0)
arr1 = prng.binomial(1, 0.3, (1000, 3136))
arr2 = prng.binomial(1, 0.3, (2000, 3136))
res1 = hamming_distance2(arr1, arr2)
arr1 = arr1.astype('float32'); arr2 = arr2.astype('float32')
res2 = (1-arr1).dot(arr2.T) + arr1.dot(1-arr2.T)

np.allclose(res1, res2)
Out: True

和時間:

%timeit hamming_distance(arr1, arr2)
1 loop, best of 3: 13.9 s per loop

%timeit hamming_distance2(arr1, arr2)
1 loop, best of 3: 5.01 s per loop

%timeit (1-arr1).dot(arr2.T) + arr1.dot(1-arr2.T)
10 loops, best of 3: 93.1 ms per loop

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM