Bol*_*ain 6 python matrix cosine-similarity
我有两大组向量,A和B. 中的每个元素A是长度400的1维向量,用-10和10之间的浮点值对于每个向量A,我试图以计算余弦相似性的所有向量B,以便找到前5矢量在B该最佳匹配给定的A向量。现在,我正在遍历所有A,并遍历所有B,与 SciPy 的spatial.distance.cosine(a, b). 有没有更快的方法来做到这一点?也许与矩阵?
您可以首先在其单位向量中转换每个向量(通过将其除以其长度)。然后距离公式简化为
d = 1 - e_v * e_w
with e_v = v / ||v||_2 , e_w = w / ||v||_2
Run Code Online (Sandbox Code Playgroud)
计算速度更快。
使用scipy.spatial.distance.cdist(XA, XB, 'cosine'). 您需要从向量集(伪代码)构建一个矩阵:
XA=np.array([vecA1,vecA2,...,vecA400])
XB=np.array([vecB1,vecB2,...,vecB400])
distances = scipy.spatial.distance.cdist(XA, XB, 'cosine')
Run Code Online (Sandbox Code Playgroud)
这是一个天真的无循环,没有你需要的开销(?)实现......
from np.linalg import norm
res = 1 - np.dot(A/norm(A, axis=1)[...,None],(B/norm(B,axis=1)[...,None]).T)
Run Code Online (Sandbox Code Playgroud)
您能否在您的数据子集上对其进行基准测试,并让我们知道它是否比 scipy 的余弦距离快?
ps,axis=1以上是基于您的向量按行存储的假设,
print A
# [[1 2 3 4 5 6 7 8 ... 400]
# [2 3 4 5 6 7 8 9 ... 401]
Run Code Online (Sandbox Code Playgroud)
等等
In [79]: A = np.random.random((2,5))
In [80]: A
Out[80]:
array([[ 0.2917865 , 0.89617367, 0.27118045, 0.58596817, 0.05154168],
[ 0.61131638, 0.2859271 , 0.09411264, 0.57995386, 0.09829525]])
In [81]: norm(A,axis=1)
Out[81]: array([ 1.14359988, 0.90018201])
In [82]: norm(A,axis=1)[...,None]
Out[82]:
array([[ 1.14359988],
[ 0.90018201]])
In [83]: A/norm(A,axis=1)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-83-707fa10dc673> in <module>()
----> 1 A/norm(A,axis=1)
ValueError: operands could not be broadcast together with shapes (2,5) (2,)
In [84]: A/norm(A,axis=1)[...,None]
Out[84]:
array([[ 0.25514737, 0.78364267, 0.23712878, 0.51238915, 0.04506968],
[ 0.67910309, 0.31763254, 0.10454846, 0.64426289, 0.10919486]])
In [85]: norm(A/norm(A,axis=1)[...,None], axis=1)
Out[85]: array([ 1., 1.])
In [86]:
Run Code Online (Sandbox Code Playgroud)
上面的会话是为了解释归一化过程,当我们有归一化矩阵 A' 和 B' 时,我们取点积(当然我们必须转置 B' 矩阵),结果是一个矩阵,其元素j, j
是点积归一化向量 A_i 和 B_j,我们从1这个矩阵中减去,我们有一个余弦距离矩阵。或者我希望...
In [1]: import numpy as np
In [2]: from numpy.linalg import norm as n
In [3]: from scipy.spatial.distance import cosine
In [4]: A = np.random.random((100,400))
In [5]: B = np.random.random((100,400))
In [6]: C = np.array([[cosine(a,b) for b in B] for a in A])
In [7]: c = 1.0 - np.dot(A/n(A,axis=1)[:,None],(B/n(B,axis=1)[:,None]).T)
In [8]: np.max(C-c)
Out[8]: 8.8817841970012523e-16
In [9]: np.min(C-c)
Out[9]: -8.8817841970012523e-16
In [10]: %timeit [[cosine(a,b) for b in B] for a in A];
1 loops, best of 3: 1.3 s per loop
In [11]: %timeit 1.0 - np.dot(A/n(A,axis=1)[:,None],(B/n(B,axis=1)[:,None]).T)
100 loops, best of 3: 9.28 ms per loop
In [12]:
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6289 次 |
| 最近记录: |