从稀疏数组有效计算成对的Jaccard相似度

时间:2018-12-25 21:34:15

标签: python performance numpy scipy sparse-matrix

我有一个类似于以下的数组,每一行都是一个观察值,每一列都是一个特征:

import scipy
my_sparse_array = scipy.sparse.random(2000, 10000000, density=0.01, format='csr')

对于每对观察(行),我想计算它们之间的Jaccard相似度-考虑到数组中的非零值表示存在特征,而零值表示不存在特征。因此,交集将是两个观测值均具有一个非零值的地方,而联合则是其中只有一个观测值具有非零值的地方。都为零的要素将被忽略。

进行成对计算的最有效方法是什么。我的计划是使所有对的组合为0-1999,将两行作为子集,删除具有非零列的任何列,然后进行计算,但这似乎效率很低,因为它需要进行大量的拼接。

所需的输出是带有Jaccard索引的2000 x 2000矩阵。一个额外的好处是使一个4列数组居中,并具有观察索引1,观察索引2,交集和并集。

谢谢! 杰克

1 个答案:

答案 0 :(得分:1)

准确地说,只要至少一项不为零,就应计入并集。

无论如何,您都必须进行O(n ^ 2)个比较。特别地,存在n(n-1)/ 2个可能的对。因此,任何提速都将来自比较本身。

看来条目的值对您的定义并不重要,因此如果转换为布尔值,事情会更快。假设X=my_sparse_array.astype('bool)'是您的稀疏布尔数组,大小为(2000,10000000)。您可以按以下方式计算行ij之间的交集和并集:

intersection = scipy.sum(X[i].multiply(X[j]))
union = scipy.sum(X[i]+X[j])

乘法函数是逐点作用的,因此,如果kX[i].multiply(X[j])的第k个条目都为1,则X[i]的第X[j]个条目为1为1,否则为0。因此,它充当逻辑和操作。同样,+充当逻辑或运算。总和只是给出一行中非零条目的数量。