计算大型稀疏矩阵的幂和

问题描述

给定一个查询向量(one-hot-vector)q,大小为50000x1一个大的稀疏矩阵A,大小为50000 x 50000,nnz为{{ 1}} 是 A 亿,我想计算 0.3(通常是 r=(A + A^2 + ... + A^S)q)。

我可以使用循环迭代上述方程

4 <= S <=6

但我想要更快速方法

首先想到的是 r = np.zeros((50000,1)) for i in range(S): q = A.dot(q) r += q 可以是对称的,所以 eigen decomposition would help for compute power of A。但由于 A 是大型稀疏矩阵,分解后会生成A 相同大小的稠密矩阵,从而导致性能下降(在内存和速度方面)。

还考虑了低秩近似。但是 A 又大又稀疏,所以不确定哪个排名 A 合适。

预先计算一些东西是完全没问题的,比如 r。但我希望最后一次计算会很快:计算 A + A^2 + ... + A^S = B 小于 40 毫秒。

是否有任何参考或论文或技巧?

解决方法

即使矩阵不是稀疏的,迭代方法也是可行的方法。

乘以 A.dot(q) 的复杂度为 O(N^2),而计算 A.dot(A^i) 的复杂度为 O(N^3)。

q 是稀疏的(确实比 A 稀疏得多)这一事实可能会有所帮助。 对于第一次迭代,A*q 可以计算为 A[q_hot_index,:].T

对于第二次迭代,A @ q 的预期密度与 A 的预期密度相同(大约 10%),因此稀疏地进行仍然是好的。

对于之后的第三次迭代,A^i @ q 将是密集的。

由于您正在累积结果,因此您的 r 不是稀疏的,它可以防止索引操作。 有 several 种不同的方式来存储稀疏矩阵。我自己不能说我对所有这些都了解得深入,但我认为 csr_matrixcsc_matrix 是通用稀疏矩阵中最紧凑的。

当您需要计算 P(A) 时,特征分解是好的,为了计算 P(A)*q,只有当 P(A) 具有 {{ 大小的数量级时,特征分解才变得有利1}}。特征分解的复杂度为A,矩阵向量乘积的复杂度为O(N^3),使用特征分解对O(N^2)次多项式P(A)的求值可以在{ {1}}。

编辑:回答评论中的问题

  1. “它可以防止索引操作”

假设您有一个稀疏矩阵 D。这可以描述为 O(N^3 + N*D)。现在假设您将 1 分配给一个元素,它变为 [0,2,7,0],现在表示为 ((3,2),(5,7))。赋值是通过插入数组来执行的,插入数组的复杂度为[0,1,0],其中nnz 是非零元素的个数。如果你有一个密集矩阵,你总是可以修改一个复杂度为 ((3,(4,1),7)) 的元素。

  1. 复杂度中的 N 是多少?

它是矩阵O(nnz)的行数或列数

  1. 关于特征分解,你想说值不值 可以在 O(N^3 +N*D) 而非 O(N^3 + N^2) 中实现计算 r

计算 O(1) 将具有复杂度 A(具有不同的常数),对于大矩阵,使用特征分解计算 P(A) 可能是最有效的。但是 O(N^3 * D) 具有 P(A) 复杂性,因此除非您有很大的 P(A)x O(N^2 * D),否则使用特征分解计算 P(A)x 可能不是一个好主意,当速度为担心。