是否可以只保存对称矩阵的一半来节省内存?

Posted

技术标签:

【中文标题】是否可以只保存对称矩阵的一半来节省内存?【英文标题】:Is it possible to save only half of a symmetric matrix to save the memory? 【发布时间】:2011-09-09 19:36:57 【问题描述】:

Ax=b 类型问题中使用了一个大矩阵。 A 是对称的。有什么算法可以让我们只保存一半的矩阵,然后在上面做x=A\b这样的操作吗?

【问题讨论】:

【参考方案1】:

您只会节省一半的内存,但您可以通过创建矩阵的平面版本来做到这一点,将其保存,然后将其展开。请注意,所需的额外时间可能并不值得节省:

% pretend this is symettric...
A = rand(10, 10);

% store it as a flat list
flatA = [];
for k = 1:size(A,1)
    flatA = [flatA; A([1:k],k)];
end

save('flatA.mat', 'flatA');

% undo
N = (-1 + (1+4*2*length(flatA))^0.5)/2;
newA = NaN(N,N); 
cur = 1;
for k = 1:N
    len = k;
    newA(1:len, k) = flatA(cur:cur+len-1);
    cur = cur + len;
end
% real A cannot have NaNs or this trick fails
newA(isnan(newA)) = newA(isnan(newA'))';

【讨论】:

【参考方案2】:

如果提取上三角部分并转换为稀疏矩阵,应该可以节省内存。这种技术相当快。

% Create a symmetric matrix
A = rand(1000);
A = A + A';

% Extract the upper triangular part
B = sparse(triu(A))              % This is the important line, the rest is just checking.

% Undo
BB = full(B);
C = BB + BB' - diag(diag(BB));

% Check correct
assert(all(A(:) == C(:)));

% Save matrices
save('A.mat', 'A');
save('B.mat', 'B');

% Get file sizes
infoA = dir('A.mat'); infoA.bytes
infoB = dir('B.mat'); infoB.bytes

编辑以澄清木片的事情

上述解决方案演示了一种使用较少文件空间保存矩阵的方法。矩阵B 也比原始矩阵A 占用更少的内存。如果你想对B 进行线性代数运算,那效果很好。比较

b = rand(1000);
fullTriUA = triu(A);
sparseTriUA = sparse(fullTriUA);  %same as B above
fullResult = fullTriUA\b;
sparseResult = sparseTriUA\b;
assert(all(fullResult(:) == sparseResult(:)))

【讨论】:

是的,但是要使用矩阵,你强制用户转换回一个完整的矩阵,然后无论如何都要恢复整个矩阵!!!!!!这不仅不会节省内存,还会生成多个矩阵副本作为完整矩阵。它占用的内存是原始矩阵所需的数倍。 @woodchips:你误会了。矩阵的额外副本仅用于从文件中恢复。查看我的编辑。 是的。但是,当您恢复阵列时,您会创建该阵列的多个副本。存储阵列的磁盘空间很少会成为问题,但 RAM 通常会如此。我将这个问题解释为内存使用问题之一,因为用户仍然希望使用最小化数组来使用 A\b 之类的操作。如果是这样,那么制作大型数组的多个副本肯定会是一个问题。这里需要澄清一下。 只有当原始矩阵的非零元素少于三分之一时,稀疏矩阵才能节省内存。在这种情况下,它超过了一半。试试whos A BB 实际上比 A 占用更多空间。 @yuk: 对于 6x6 或更大的矩阵,B 占用的内存少于 A。 (在 R2011a 和 R2010b 上测试。)对于非常大的矩阵,它接近 A 的内存占用量的 3/4。也许你忘了取上三角部分。【参考方案3】:

这是一个想法,但我还没有测试过。如果您的对称矩阵是正定的,请对对称矩阵 A 进行 Cholesky 分解,得到 A = U*U'。如果您使用 MATLAB 的内置稀疏矩阵将 U 存储为稀疏矩阵,则您拥有所需的一切,并且使用了大约一半的内存。由于它使用了 MATLAB 的稀疏矩阵类型,因此您已经使用标准 MATLAB 函数对其进行了操作,只要您记住 A = U*U'

例如,要计算 A*x = b,请使用 x = U'\U\b。与其他提议的解决方案不同,MATLAB 永远不会在内部实际使用完整矩阵,甚至会使用加速求解器,这将利用您仅使用三角形求解的事实。代价是要解决单个系统,您实际上已经运行了两次反斜杠运算符(见上文)。然而,这就是您从不实例化整个矩阵所付出的代价。

【讨论】:

如果您对其进行测试,我会提供代表并提供MWE 以表明它有效!

以上是关于是否可以只保存对称矩阵的一半来节省内存?的主要内容,如果未能解决你的问题,请参考以下文章

是否有比 O(N²) 更好的算法来确定矩阵是否对称?

Numpy“智能”对称矩阵

Java数据结构之对称矩阵的压缩算法---

对称矩阵的存取

使用 Accelerate 框架的对称带矩阵的特征值

C++ 特殊矩阵的压缩存储算法