相同的稀疏矩阵,不同的对象大小

Same sparse matrix, different object sizes

我在创建一些邻接矩阵时偶然发现了一个奇怪的问题。

我有一个全是 1 和 0 的矩阵。我想将它的转置乘以它 (t(X) %*% X),然后 运行 一些其他的东西。由于例程开始变得非常慢,我将其转换为稀疏矩阵,显然速度更快。

但是,稀疏矩阵的大小会增加一倍,具体取决于我何时将矩阵转换为稀疏格式。

这是 运行 进入同一问题的一些通用示例

set.seed(666)
nr = 10000
nc = 1000

bb = matrix(rnorm(nc *nr), ncol = nc, nrow = nr)
bb = apply(bb, 2, function(x) x = as.numeric(x > 0))

# Slow and unintelligent method
op1  = t(bb) %*% bb
op1  = Matrix(op1, sparse = TRUE) 

# Fast method
B   = Matrix(bb, sparse = TRUE) 
op2 = t(B) %*% B

# weird
identical(op1, op2) # returns FALSE
object.size(op2)
#12005424 bytes
object.size(op1) # almost half the size
#6011632 bytes

# now it works...
ott1 = as.matrix(op1)
ott2 = as.matrix(op2)

identical(ott1, ott2) # returns TRUE

然后我就好奇了。有人知道为什么会这样吗?

op1的class是dsCMatrix,而op2dgCMatrixdsCMatrix 是对称矩阵的 class,因此它只需要存储上半部分加上对角线(大约是整个矩阵数据量的一半)。

将稠密矩阵转换为稀疏矩阵的 Matrix 语句足够聪明,可以为对称矩阵选择对称 class,从而实现节省。您可以在函数 Matrix 的代码中看到这一点,它明确执行测试 isSym <- isSymmetric(data)

另一方面,

%*% 针对速度进行了优化,不执行此检查。