MATLAB:将单元阵列的元素与另一个矩阵相乘,以创建由产品组成的新单元阵列

时间:2013-04-04 11:01:55

标签: matlab vectorization matrix-multiplication cells

我有一个由多个(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的大小(只要它们是可乘的)?

3 个答案:

答案 0 :(得分:4)

我可以想到几个方法。首先,我通过

生成一些虚假数据
A = cellfun(@(~)rand(2,1), cell(1000), 'uni', false);
B = rand(2);

Cellfun

正如你所说,这是你想要避免的。在任何情况下,我都会将其包含在此处进行比较:

C = cellfun(@(x)B*x, A, 'UniformOutput',false);

由于涉及匿名功能,因此速度很慢。具有内置字符串函数的Cellfun(参见help cellfun)正在快速发展,但是,匿名函数强制执行在每次迭代时由Matlab解释器传递。虽然JIT可以在一定程度上提高效率,但它远非最优化。

细胞扩增,num2细胞,重塑

想法:将单元格扩展为2x1000矩阵,执行乘法运算,并将结果转换回正确大小的单元格数组。虽然原则上很优雅,但在实践中它会变得有点混乱:

C = reshape( num2cell(B*[A{:}],1), size(A) );

请注意,从内存占用的角度来看,中间2x1000临时性有点浪费......同样,传递num2cell(非内置)和'无用'{{1减慢执行速度。

For loop

循环最简单易读,实现起来最简单。占用内存小,适合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循环的严重影响。

或者您可以像提示一样使用此答案。 我希望这会有所帮助。