相同的稀疏矩阵,不同的对象大小
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
,而op2
是dgCMatrix
。 dsCMatrix
是对称矩阵的 class,因此它只需要存储上半部分加上对角线(大约是整个矩阵数据量的一半)。
将稠密矩阵转换为稀疏矩阵的 Matrix
语句足够聪明,可以为对称矩阵选择对称 class,从而实现节省。您可以在函数 Matrix
的代码中看到这一点,它明确执行测试 isSym <- isSymmetric(data)
。
另一方面,%*%
针对速度进行了优化,不执行此检查。
我在创建一些邻接矩阵时偶然发现了一个奇怪的问题。
我有一个全是 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
,而op2
是dgCMatrix
。 dsCMatrix
是对称矩阵的 class,因此它只需要存储上半部分加上对角线(大约是整个矩阵数据量的一半)。
将稠密矩阵转换为稀疏矩阵的 Matrix
语句足够聪明,可以为对称矩阵选择对称 class,从而实现节省。您可以在函数 Matrix
的代码中看到这一点,它明确执行测试 isSym <- isSymmetric(data)
。
%*%
针对速度进行了优化,不执行此检查。