我有一个2D numpy数组,有数十万行和一千个左右的列(假设它是一个N x P数组,N = 200,000,P = 1000)。这里的目标是计算每对行向量之间相同元素的数量,理想情况下使用numpy数组魔术,不需要我执行199,999 * 100,000个这样的对的循环。由于存储200,000×200,000阵列可能不可行,因此输出可能是Nx3稀疏坐标格式,例如,如果输入格式为:
5 12 14 200 0 45223
7 12 14 0 200 60000
7 6 23 0 0 45223
5 6 14 200 0 45223
得到的(密集的)NxN矩阵M将是(不关心对角线元素):
0 2 2 4
2 0 2 1
2 2 0 3
4 1 3 0
假设基于0的索引,Mij包含初始行i和初始行j之间的相同元素的数量。 因此,预期的稀疏输出等效值将是:
0 1 2
0 2 2
0 3 4
1 2 2
1 3 1
2 3 3
实现这一目标的一种天真,非常低效的方式是:
import itertools
import numpy as np
def pairwise_identical_elements(small_matrix):
n, p = small_matrix.shape
coordinates = itertools.combinations(range(n), 2)
sparse_coordinate_matrix = []
for row1, row2 in itertools.combinations(small_matrix, 2):
idx1, idx2 = next(coordinates)
count = p - np.count_nonzero(row1 - row2)
sparse_coordinate_matrix.append([idx1, idx2, count])
return sparse_coordinate_matrix
我已经研究了距离度量实现,例如scipy和sklearn中的Jaccard相似性,但它们都假设输入行向量必须是二进制的。我还尝试添加第三个维度以使条目成为二进制(例如,条目'9'成为零的向量,在第9个位置具有1)但是存在明显的内存问题(条目'45223'将需要第三维伸展那么多元素。)
是否存在一种高效,可扩展和/或pythonic的解决方案,使用numpy或scipy以我错过的方式?
编辑:在进一步研究scipy后,我发现了一些与我正在尝试的内容非常匹配的东西,即scipy.sparse.distance.pdist和Hamming指标。然而,它以“压缩”的形式返回输出,并且由于我们试图避免转换为完全密集的数组以节省内存,因此问题可能变成:如何将压缩距离矩阵转换为稀疏矩阵?
答案 0 :(得分:0)
如评论中所述,考虑到空间和CPU时间,scipy的pdist带有'汉明'是解决此问题的最简单有效的方法。
您将无法获得比其condensed output更高效的内存。
确实,与“ (N*(N-1)/2, 3)
返回的N*(N-1)/2
向量相比,以“稀疏”格式写入数据时,需要一个pdist
矩阵。