【发布时间】:2011-09-09 19:36:57
【问题描述】:
Ax=b 类型问题中使用了一个大矩阵。 A 是对称的。有什么算法可以让我们只保存一半的矩阵,然后在上面做x=A\b这样的操作吗?
【问题讨论】:
标签: matlab matrix large-data
Ax=b 类型问题中使用了一个大矩阵。 A 是对称的。有什么算法可以让我们只保存一半的矩阵,然后在上面做x=A\b这样的操作吗?
【问题讨论】:
标签: matlab matrix large-data
您只会节省一半的内存,但您可以通过创建矩阵的平面版本来做到这一点,将其保存,然后将其展开。请注意,所需的额外时间可能并不值得节省:
% 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'))';
【讨论】:
如果提取上三角部分并转换为稀疏矩阵,应该可以节省内存。这种技术相当快。
% 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(:)))
【讨论】:
whos A B。 B 实际上比 A 占用更多空间。
B 占用的内存少于 A。 (在 R2011a 和 R2010b 上测试。)对于非常大的矩阵,它接近 A 的内存占用量的 3/4。也许你忘了取上三角部分。
这是一个想法,但我还没有测试过。如果您的对称矩阵是正定的,请对对称矩阵 A 进行 Cholesky 分解,得到 A = U*U'。如果您使用 MATLAB 的内置稀疏矩阵将 U 存储为稀疏矩阵,则您拥有所需的一切,并且使用了大约一半的内存。由于它使用了 MATLAB 的稀疏矩阵类型,因此您已经使用标准 MATLAB 函数对其进行了操作,只要您记住 A = U*U'
例如,要计算 A*x = b,请使用 x = U'\U\b。与其他提议的解决方案不同,MATLAB 永远不会在内部实际使用完整矩阵,甚至会使用加速求解器,这将利用您仅使用三角形求解的事实。代价是要解决单个系统,您实际上已经运行了两次反斜杠运算符(见上文)。然而,这就是您从不实例化整个矩阵所付出的代价。
【讨论】: