从稀疏数组中高效计算成对Jaccard相似度



我有一个如下的数组,每行是一个观察值,每列是一个特征:

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

对于每一对观测值(行),我想计算它们之间的Jaccard相似性——考虑到数组中的非零值意味着存在特征,而零值意味着不存在特征。因此,交集是指两个观测值都具有非零值的特征,而并集是指只有一个观测值具有非零值。两者均为零的特征将被忽略。

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

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

谢谢!Jack

准确地说,只要至少有一个条目为非零,它就应该计入并集。

不管怎样,你都必须进行O(n^2)比较。特别地,存在n(n-1)/2个可能的对。因此,任何加速都将来自于比较本身。

条目的值似乎对您的定义无关紧要,所以如果您转换为布尔值,事情会更快。假设X=my_sparse_array.astype('bool)'是大小为(200010000000)的稀疏布尔数组。您可以将ij行之间的交集和并集计算为:

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

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

最新更新