由於您使用的是餘弦相似度,因此應該有幾何解釋爲a
和b
。 (餘弦相似性是找到兩個向量之間角度的餘弦)。
長度爲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.4,0.9]'是否類似於[0.4,0.9,10 ** 6]?它是否類似於[[0.4,10 ** 6,0.9]]? – unutbu
這些數字是向量(術語頻率)。 [0.4,0.9]代表一個文本文檔,與其他代碼一樣。要回答你的問題,根據10 ** 6的權重,[0.4,0.9]可能與[0.4,0.9,10 ** 6]類似。 – Tiger1
問題是,當矩陣對齊時,即[0.4,0.9]和[0.8,0.3],可以計算它們的相似度。但是當任何一個陣列中的矢量比另一箇中的矢量[0.4,0.9]和[0.8,0.3,0.7]更多時,就會出現對齊問題。 – Tiger1