Python Scipy余弦相似性与sklearn余弦相似性

Python Scipy余弦相似性与sklearn余弦相似性,python,scikit-learn,scipy,cosine-similarity,Python,Scikit Learn,Scipy,Cosine Similarity,我注意到scipy和sklearn都有余弦相似性/余弦距离函数。我想测试每对向量的速度: setup1=“将numpy作为np导入;arrs1=[np.random.rand(400)表示范围(60)];arrs2=[np.random.rand(400)表示范围(60)]” setup2=“将numpy作为np导入;arrs1=[np.random.rand(400)表示范围(60)];arrs2=[np.random.rand(400)表示范围(60)]” import1=“来自sklear

我注意到
scipy
sklearn
都有余弦相似性/余弦距离函数。我想测试每对向量的速度:

setup1=“将numpy作为np导入;arrs1=[np.random.rand(400)表示范围(60)];arrs2=[np.random.rand(400)表示范围(60)]”
setup2=“将numpy作为np导入;arrs1=[np.random.rand(400)表示范围(60)];arrs2=[np.random.rand(400)表示范围(60)]”
import1=“来自sklearn.metrics.pairwise import cosine\u相似度”
stmt1=“[arr1的浮点(余弦_相似性(arr1.整形(1,-1),arr2.整形(1,-1)),压缩中的arr2(arrs1,arrs2)]”
import2=“从scipy.spatial.distance导入余弦”
stmt2=“[1-余弦(arr1,arr2)]用于拉链中的arr1,arr2(arrs1,arrs2)]”
导入时间信息
打印(“sklearn:,timeit.timeit(stmt1,setup=import1+”;“+setup1,number=1000))
打印(“scipy:,timeit.timeit(stmt2,setup=import2+”;“+setup2,number=1000))

sklearn
的运行速度几乎是
scipy
的10倍(即使您删除了sklearn示例中的数组整形,并生成了已经处于正确形状的数据)。我无法想象为什么一个比另一个慢很多?

如评论部分所述,我认为比较不公平,主要是因为
sklearn.metrics.pairwise.cosine\u similarity
设计用于比较给定输入二维数组中样本的成对距离/相似性。另一方面,
scipy.space.distance.cosine
设计用于计算两个一维阵列的余弦距离

也许更公平的比较是使用
scipy.space.distance.cdist
sklearn.metrics.pairwise.cosine\u相似性
,两者都计算给定数组中样本的成对距离。然而,令我惊讶的是,这表明sklearn实现比scipy实现快得多(我目前没有对此的解释!)。以下是实验:

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from scipy.spatial.distance import cdist

x = np.random.rand(1000,1000)
y = np.random.rand(1000,1000)

def sklearn_cosine():
    return cosine_similarity(x, y)

def scipy_cosine():
    return 1. - cdist(x, y, 'cosine')

# Make sure their result is the same.
assert np.allclose(sklearn_cosine(), scipy_cosine())
下面是计时结果:

%timeit sklearn_cosine()
10 loops, best of 3: 74 ms per loop

%timeit scipy_cosine()
1 loop, best of 3: 752 ms per loop

我不熟悉
sklearn
scipy
的内部工作原理;然而,除了在一个实验中重塑数组而不是在另一个实验中重塑数组这一事实之外,我认为这不是一个公平的比较,因为
cosine\u相似度
计算两个输入数组中所有样本的成对余弦距离(尽管在一个样本的数组中调用它),但是
scipy
中的
cosine
函数只在1D数组上工作,因此可能有更高效的实现。@今天,即使您放弃了数组整形(使用
np.random.rand(1400)
而不是
np.random.rand(400)
创建数组以防止整形),学习还是比较慢。我怀疑sklearn是为2d阵列设计的这一事实可能与此有关,但性能差异仍然很大。
%timeit sklearn_cosine()
10 loops, best of 3: 74 ms per loop

%timeit scipy_cosine()
1 loop, best of 3: 752 ms per loop