【发布时间】:2018-03-02 15:28:53
【问题描述】:
我有一个包含数十万行和一千左右列的二维 numpy 数组(假设它是一个 N x P 数组,N = 200,000,P = 1000)。这里的目标是计算每对行向量之间相同元素的数量,理想情况下使用 numpy 数组魔法,不需要我对 199,999 * 100,000 个这样的对执行循环。由于存储 200,000 x 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
使得 Mij 包含初始行 i 和初始行 j 之间相同元素的数量,假设基于 0 的索引。 因此,预期的稀疏输出等效为:
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”需要第三维拉伸那么多元素)。
是否有一种我错过的使用 numpy 或 scipy 的高效、可扩展和/或 Pythonic 解决方案?
编辑:在进一步研究 scipy 之后,我发现一些与我正在尝试做的事情非常匹配的东西,即 scipy.sparse.distance.pdist 与 Hamming 指标。然而,它以“压缩”形式返回输出,并且由于我们试图避免转换为全密集数组以节省内存,因此问题可能变成:如何将压缩距离矩阵转换为稀疏矩阵?
【问题讨论】:
-
请诱导一些代码来启发我们更多你打算做什么
-
当然,我添加了一个小sn-p,它以一种天真的方式实现了我想要做的事情。假设输入是标准的 numpy 数组。
-
那么这里的赌注在哪里?空间复杂性?还是时间?
-
内存是一个明显的问题(因为 python 在处理太多对象时往往会崩溃),但任何运行时间都与 scipy.sparse.distance 模块中的上述 pdist 函数处于同一数量级很好。
-
@lurena 您能否解释一下问题中的示例,因为将您的函数运行到示例输入会产生不同的输出
标签: python arrays numpy scipy sparse-matrix