稀疏矩阵的 R 内部处理

R internal handling of sparse matrices

我一直在比较 Python 和 R 的几个 PCA 实现的性能,并注意到一个有趣的行为:
虽然在 Python 中计算稀疏矩阵的 PCA 似乎是不可能的(唯一的方法是 scikit-learn's TruncatedSVD,但它不支持等效于 PCA 的协方差解所需的均值居中. 他们的论点是,它会破坏矩阵的稀疏性 属性。出于类似原因,Facebook 的 PCA 算法或 scikit 学习中的 PCA/randomPCA 方法等其他实现不支持稀疏矩阵。

虽然所有这些对我来说都很有意义,但一些 R 包,如 irlba、rsvd 等,能够处理稀疏矩阵(例如用 rsparsematrix 生成),甚至允许对于特定的 center=True 个参数。

我的问题是,R 如何在内部处理这个问题,因为它似乎比可比较的 Python 实现效率高得多。 R 是否仍然通过执行绝对缩放来保持稀疏性(理论上这会伪造结果,但至少保持稀疏性)? 或者有什么方法可以显式存储零值的均值,并且只存储一次(而不是分别存储每个值)?

要推迟: R 如何在不增加 RAM 使用量的情况下在内部存储具有均值居中的矩阵。 希望足够简洁....

这里的关键是部分 SVD (restarted Lanczos bidiagonalization C code) 的底层实现不存储矩阵。您改为记录矩阵中线性运算的结果 应用于从上一次迭代中获得的一小组向量。

而不是解释在相当高级的 c 代码中使用的具体方法(描述见 paper),我将用一个更简单的算法来解释它,该算法在如何捕获关键思想方面为了保持稀疏性的效率:幂方法(或子空间迭代方法,用于将其推广到多个特征值)。该算法 returns 矩阵 A 的最大特征值通过迭代应用线性运算符,然后归一化(或正交化一小组向量,在子空间迭代的情况下)

你在每次迭代中所做的是

v=A*v
v=v/norm(v)

矩阵乘法步骤是关键步骤,所以让我们看看当我们对居中 A 尝试相同操作时会发生什么。居中 A 的矩阵公式(以 center 作为具有均值列的向量值和 ones 作为 1 的向量)是:

A_center=A-ones*transpose(center)

因此,如果我们将迭代算法应用于这个新矩阵,我们将得到

v=A*v-dotproduct(center,v)*ones

由于 A 是稀疏的,我们可以在 (A,v) 上使用稀疏矩阵向量积,-dotproduct(center,v)*ones 只需从维度上线性的结果向量中减去中心和 v 的点积A.