2017-09-01 104 views
2

我有一個非常稀疏的矢量df(超過95%零)的數據集,我正在測量另一個稀疏矢量sample之間的距離。稀疏向量中的歐幾里得距離與餘弦距離 - 歐幾里德如何表現更好?

現在,由於我處理的是非常稀疏的矢量,我假定餘弦距離的計算速度比歐幾里得快得多,但似乎並不是這樣。

這是正常的行爲嗎?或者我做錯了什麼?或者,餘弦距離在稀疏矢量中更有效甚至不是真的?

all_distances包括多種類型的距離,但我們在這裏談論的,僅僅是scipy.spatial.distance.euclideanscipy.spatial.distance.cosine

我的代碼

for d_name, d_func in all_distances.items(): 

    tot_time = [] 
    for i in range(100): 
     start_time = time() 
     df['distance'] = df.apply(d_func, axis=1, args=(sample,)) 
     df.sort_values(by='distance', ascending=True, inplace=True) 
     df.drop('distance', axis=1, inplace=True) 
     df = df.reset_index(drop=True) 
     tot_time.append(time() - start_time) 

    print("Mean time for {}: {}s".format(d_name, round(mean(tot_time), 4))) 

結果:

平均時間餘弦:0.8034s

Mean ti我要歐幾里德:0.708s

+0

解釋爲什麼你認爲應該更快(僅僅是因爲稀疏)。它看起來並不像你使用'scipy''稀疏'矩陣。 – hpaulj

+1

查看公式https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cosine.html#scipy.spatial.distance.cosine我可以看到,元素不需要計算在兩個矢量中的任何一個矢量都爲零,所以我相信餘弦中的迭代應該快得多,因爲在相同索引中的兩個元素中的任何一個的95+前綴將是零。 – bluesummers

+0

不,我沒有使用'scipy.sparse'我實際上從來沒有碰過它,如果它會提高餘弦性能,我很樂意聽到我在這個用例中使用它 – bluesummers

回答

1

餘弦相似既需要輸入向量的規範,以及它們之間的點積:

cos(theta) = dot(a,b)/(norm(a) * norm(b)) 

所以,即使積僅積當兩個a[i]b[i]非零,你仍然需要積累ab的標準,這本身就像積累歐幾里得距離一樣多。

大部分工作都是在迭代稀疏矢量 - 注意它們之間的性能沒有太大的差別。然而,這種差異的合理解釋是餘弦計算需要做更多的算術運算。

+0

當然,有一種方法可以避免計算規範,如果點是零..不是嗎? – bluesummers

+0

的確如此,但這並不能爲您節省很多時間 - 因爲大部分工作都是通過稀疏向量迭代的。然後,如果點*不是*零,則需要再次重新遍歷稀疏向量以計算規範,這將幾乎使所需時間加倍。如果你正在寫'scipy.spatial.distance.cosine',你會接受這個賭注嗎? – comingstorm

+0

顯然不是,但看着他們的文檔,我找不到稀疏相關模塊中的任何東西。這是越來越少的話題,但任何已知的稀疏向量數學解決方案?我的意思是,我看到scipy稀疏庫,距離是非常基本的,它不在那裏 – bluesummers