2013-07-30 35 views
1

我有以下數組(矢量): l = [[0.483,0.923],[0.781,0.1818],[0.446,0.564,0.796] ]如何在處理不同形狀的數組時處理矩陣

我寫了下面幾行代碼來計算向量之間的餘弦相似度,並得到了這個錯誤信息:ValueError:矩陣沒有對齊。

import numpy as np 
import numpy.linalg as LA 
l=[[0.483, 0.923], [0.781, 0.188], [0.446, 0.564, 0.796]] 
cx = lambda a, b : round(np.inner(a, b)/(LA.norm(a)*LA.norm(b)), 2) 
for v in l: 
    for y in l: 
    cosine=cx(v,y) 
    print cosine 

在調節所述陣列以相等的長度(L = [[0.483,0.923],[0.781,0.188],[0.446,0.564]]),我的代碼工作得很好。

現在的問題是如何在不調整數組形狀的情況下使代碼工作? (即如何對齊矩陣)。感謝您的任何建議。

+1

這些數字代表什麼? '[0.4,0.9]'是否類似於[0.4,0.9,10 ** 6]?它是否類似於[[0.4,10 ** 6,0.9]]? – unutbu

+0

這些數字是向量(術語頻率)。 [0.4,0.9]代表一個文本文檔,與其他代碼一樣。要回答你的問題,根據10 ** 6的權重,[0.4,0.9]可能與[0.4,0.9,10 ** 6]類似。 – Tiger1

+0

問題是,當矩陣對齊時,即[0.4,0.9]和[0.8,0.3],可以計算它們的相似度。但是當任何一個陣列中的矢量比另一箇中的矢量[0.4,0.9]和[0.8,0.3,0.7]更多時,就會出現對齊問題。 – Tiger1

回答

3

由於您使用的是餘弦相似度,因此應該有幾何解釋爲ab。 (餘弦相似性是找到兩個向量之間角度的餘弦)。

長度爲2的矢量可以被認爲存在於xy-plane中,並且長度爲3的矢量可以被認爲存在於xyz-space中。 因此,平面中的矢量[0.4, 0.9]可以被認爲是xyz-space中的3維矢量[0.4, 0.9, 0]

如果這是合理的,那麼在2D矢量和3D矢量之間取內積就相當於在簡單地丟棄第三個成分(因爲0乘以任何東西)爲0之後取內積。

因此,你可以定義cx這樣:

def cx(a, b) : 
    a, b = (a, b) if len(a) < len(b) else (b, a) 
    b = b[:len(a)] 
    try: 
     assert any(a) 
     assert any(b) 
    except AssertionError: 
     print('either a or b is zero') 
     # return 0 or 
     # raise 
    return round(np.inner(a, b)/(LA.norm(a)*LA.norm(b)), 2) 

你會通過在l因此它可以製作成與NumPy陣列缺失值填補獲得更好的性能。那麼你可以申請NumPy的操作整個陣列一次和消除雙Python的for-loops

def cosine_similarity(l): 
    inner = np.einsum('ij,kj -> ik', l, l) 
    norm = np.sqrt(np.einsum('ij -> i', l*l)) 
    return inner/(norm*norm[:, np.newaxis]) 

def to_3d(l): 
    return np.array([row+[0]*(3-len(row)) for row in l]) 

np.set_printoptions(precision=2) 
print(cosine_similarity(to_3d(l))) 

產生

[[ 1. 0.66 0.66] 
[ 0.66 1. 0.53] 
[ 0.66 0.53 1. ]] 

def cx(a, b) : 
    a, b = (a, b) if len(a) < len(b) else (b, a) 
    b = b[:len(a)] 
    return round(np.inner(a, b)/(LA.norm(a)*LA.norm(b)), 2) 

def using_cx(): 
    for v in l: 
     for y in l: 
     cosine=cx(v,y) 

timeit相比顯示了11倍增長速度:

In [90]: %timeit using_cx() 
1000 loops, best of 3: 380 us per loop 

In [91]: %timeit cosine_similarity(to_3d(l)) 
10000 loops, best of 3: 32.6 us per loop 

計算仍然是二次的 - 如果您想比較l中的每對可能的行,它總是會是。但是速度更快,因爲NumPy函數是用C語言編寫的,這往往比Python循環中調用Python函數的等效代碼快。

+0

非常感謝你。你的解釋是現貨,現在代碼工作正常。但是,當我在更大的數據集上嘗試它時,在輸出之間,我收到了以下消息:RuntimeWarning:除以零中遇到的差異。 – Tiger1

+0

這意味着'a'或'b'必須是零向量。我將在代碼中進行檢查以幫助您調試/處理問題。 – unutbu

+0

謝謝你的去污。我目前遇到的問題是計算是二次的。我嘗試了100個向量(文檔)的數據集上的代碼,輸出爲100 x 100 = 10,0000個值(餘弦距離)。我實際上期待100個值。 – Tiger1