我有一个类似于以下的数组,每一行都是一个观察值,每一列都是一个特征:
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,交集和并集。
谢谢! 杰克
答案 0 :(得分:1)
准确地说,只要至少一项不为零,就应计入并集。
无论如何,您都必须进行O(n ^ 2)个比较。特别地,存在n(n-1)/ 2个可能的对。因此,任何提速都将来自比较本身。
看来条目的值对您的定义并不重要,因此如果转换为布尔值,事情会更快。假设X=my_sparse_array.astype('bool)'
是您的稀疏布尔数组,大小为(2000,10000000)。您可以按以下方式计算行i
和j
之间的交集和并集:
intersection = scipy.sum(X[i].multiply(X[j]))
union = scipy.sum(X[i]+X[j])
乘法函数是逐点作用的,因此,如果k
和X[i].multiply(X[j])
的第k
个条目都为1,则X[i]
的第X[j]
个条目为1为1,否则为0。因此,它充当逻辑和操作。同样,+
充当逻辑或运算。总和只是给出一行中非零条目的数量。