首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python中的矢量化余弦相似度计算

Python中的矢量化余弦相似度计算
EN

Stack Overflow用户
提问于 2015-12-03 23:48:23
回答 2查看 6.7K关注 0票数 6

我有两个大的向量集合,ABA的每个元素都是一个长度为400的一维向量,浮点值在-10到10之间。对于A中的每个向量,我尝试计算与B中所有向量的余弦相似度,以便找到B中最匹配给定A向量的前5个向量。现在,我循环遍历所有的A,循环遍历所有的B,使用SciPy的spatial.distance.cosine(a, b)逐一计算余弦相似性。有没有更快的方法来做这件事?也许是用矩阵?

EN

回答 2

Stack Overflow用户

发布于 2015-12-04 00:05:27

您可以首先在单位向量中变换每个向量(通过将其除以其长度)。然后,距离公式简化为

代码语言:javascript
复制
 d = 1 - e_v * e_w

 with e_v = v / ||v||_2 , e_w = w / ||v||_2 

它的计算速度更快。

使用scipy.spatial.distance.cdist(XA, XB, 'cosine')可能会更快。您需要从向量集合(伪代码)构建一个矩阵:

代码语言:javascript
复制
XA=np.array([vecA1,vecA2,...,vecA400])
XB=np.array([vecB1,vecB2,...,vecB400])
distances = scipy.spatial.distance.cdist(XA, XB, 'cosine')
票数 6
EN

Stack Overflow用户

发布于 2015-12-04 00:45:31

这是一个朴素的无循环,没有开销(?)实现您所需的功能...

代码语言:javascript
复制
from np.linalg import norm
res = 1 - np.dot(A/norm(A, axis=1)[...,None],(B/norm(B,axis=1)[...,None]).T)

你能在你的数据子集上对它进行基准测试,让我们知道它是否比scipy的余弦距离更快?

上面的ps,axis=1是基于这样的假设:向量是按行存储的,

代码语言:javascript
复制
print A
# [[1 2 3 4 5 6 7 8 ... 400]
#  [2 3 4 5 6 7 8 9 ... 401]

评论

代码语言:javascript
复制
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]: 

上面的部分是为了解释归一化过程,当我们有归一化矩阵A‘和B’时,我们取点积(当然我们必须转置B‘矩阵),结果是一个矩阵,其元素j, j是归一化向量A_i和B_j的点积,我们从1减去这个矩阵,我们得到一个余弦距离矩阵。或者我希望..。

测试和基准测试

代码语言:javascript
复制
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]: 
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34070278

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档