我有一个由多个(2x1)矩阵组成的单元阵列A. 我有另一个矩阵B(2x2),我打算与单元格A的每个元素相乘。换句话说,数组A中的每个矩阵必须与B相乘以生成另一个单元格数组C(与A相同) 2x1矩阵。
在视觉上,
B*|A{1,1} A{1,2} ... A{1,n}| = |C{1,1} C{1,2} ... C{1,n}|
|::::::::::::::::::::::::| |::::::::::::::::::::::::|
|A{m,1} A{m,2} ... A{m,n}| |C{m,1} C{m,2} ... C{m,n}|
这里,C {i,j} = B * A {i,j}
使用 cellfun 执行此操作非常慢。 有没有办法在不使用显式循环的情况下对其进行矢量化并加速操作,而不管A和B的大小(只要它们是可乘的)?
答案 0 :(得分:4)
我可以想到几个方法。首先,我通过
生成一些虚假数据A = cellfun(@(~)rand(2,1), cell(1000), 'uni', false);
B = rand(2);
正如你所说,这是你想要避免的。在任何情况下,我都会将其包含在此处进行比较:
C = cellfun(@(x)B*x, A, 'UniformOutput',false);
由于涉及匿名功能,因此速度很慢。具有内置字符串函数的Cellfun(参见help cellfun
)正在快速发展,但是,匿名函数强制执行在每次迭代时由Matlab解释器传递。虽然JIT可以在一定程度上提高效率,但它远非最优化。
想法:将单元格扩展为2x1000矩阵,执行乘法运算,并将结果转换回正确大小的单元格数组。虽然原则上很优雅,但在实践中它会变得有点混乱:
C = reshape( num2cell(B*[A{:}],1), size(A) );
请注意,从内存占用的角度来看,中间2x1000临时性有点浪费......同样,传递num2cell
(非内置)和'无用'{{1减慢执行速度。
循环最简单易读,实现起来最简单。占用内存小,适合JIT加速等。
reshape
唯一的缺点是它的坏名声 :)
现在对于踢球者:哪一个最快?
C = cell(size(A));
for ii = 1:numel(A)
C{ii} = B*A{ii};
end
结果:
tic
C = cellfun(@(x)B*x, A, 'uni',false);
toc
tic
C = reshape( num2cell(B*[A{:}],1), size(A) );
toc
tic
C = cell(size(A));
for ii = 1:numel(A)
C{ii} = B*A{ii};
end
toc
结论:自从R2008引入JIT编译以来,循环不再邪恶;不要试图默认避免它们。
答案 1 :(得分:2)
您可以使用mat2cell
/ cell2mat
A = rand(2, 10);
B = rand(2, 2);
Ac = mat2cell(A, 2, repmat(1, size(A, 2), 1)); % Convert to cell to generate your initial data
Amat = cell2mat(Ac); % Now it's a matrix
Cmat = B * Amat;
C = mat2cell(Cmat, 2, repmat(1, size(A, 2), 1)); % Now it's a cell array again
答案 2 :(得分:0)
我刚试过这个,我希望你能找到它:
clc,clear all,close all
clc,clear all,close all
A = cell(10,2);
for jj = 1:numel(A)
A{jj} = rand(2,1);
end
B = rand(2,2);
C = cat(3,A{:});
D = cell(size(A));
for ii = 1:size(C,3)
D{ii} = B*C(:,:,ii);
end
它包含一个显式的for
循环(我知道),但在最新的MATLAB版本中,性能不应该受到调用for
循环的严重影响。
或者您可以像提示一样使用此答案。 我希望这会有所帮助。