2013-05-02 122 views
0

給定每個數據點的兩個數據序列(等長)和質量值,我想根據給定的評分矩陣計算相似度分數。numpy索引與多個陣列

什麼是向量化下面的循環最有效的方式:

score = 0 
for i in xrange(len(seq1)): 
    score += similarity[seq1[i], seq2[i], qual1[i], qual2[i]] 

​​是4維float數組,形狀=(32,32,100,100); seq1,seq2,qual1qual2是長度相等(1000-40000)的一維int數組。

回答

3

不應該只是工作(tm)?

>>> score = 0 
>>> for i in xrange(len(seq1)): 
     score += similarity[seq1[i], seq2[i], qual1[i], qual2[i]] 
...  
>>> score 
498.71792400493433 
>>> similarity[seq1,seq2, qual1, qual2].sum() 
498.71792400493433 

代碼:

import numpy as np 

similarity = np.random.random((32, 32, 100, 100)) 
n = 1000 
seq1, seq2, qual1, qual2 = [np.random.randint(0, s, n) for s in similarity.shape] 

def slow(): 
    score = 0 
    for i in xrange(len(seq1)): 
     score += similarity[seq1[i], seq2[i], qual1[i], qual2[i]] 
    return score 

def fast(): 
    return similarity[seq1, seq2, qual1, qual2].sum() 

給出:

>>> timeit slow() 
100 loops, best of 3: 3.59 ms per loop 
>>> timeit fast() 
10000 loops, best of 3: 143 us per loop 
>>> np.allclose(slow(),fast()) 
True 
+0

那真是太好了。我喜歡這個比我自己的回答更好(儘管我可能只是爲了對比而離開我)。 +1。 – 2013-05-02 15:32:56

+0

這是一個我不知道的「numpy」功能。 – GWW 2013-05-02 15:33:47

+0

謝謝! - 在我的機器上的計時(包括John Zwinck的答案爲'第三')1000次迭代10000: 慢速:17.1289219856,快速:0.61208987236,第三:15.7027080059 – 2013-05-02 17:05:00

0

這個怎麼樣?

score = numpy.sum(map(similarity.__getitem__, zip(seq1, seq2, qual1, qual2))) 

當然,你也可以試用itertools imap和izip。因爲__getitem__需要一個元組而不是四個數字,所以zip是必要的,也許可以通過在itertools模塊的較暗角落查找來改進。