简体   繁体   English

MATLAB:在单元阵列中将2D矩阵与3D矩阵相乘

[英]MATLAB: Multiply 2D matrix with 3D matrix within cell arrays

I have a constant 2D double matrix mat1 . 我有一个恒定的二维双矩阵mat1 I also have a 2D cell array mat2 where every cell contains a 2D or 3D double matrix. 我也有一个2D单元阵列mat2 ,其中每个单元都包含一个2D或3D双矩阵。 These double matrices have the same number of rows and columns as mat1 . 这些双矩阵具有与mat1相同的行数和列mat1 I need to dot multiply (.*) mat1 with every slice of each double matrix within mat2 . 我需要在mat2的每个双mat1矩阵的每个切片上点乘(。*) mat1 The result needs to be another cell array results with the same size as mat2 , whereby the contatining double matrices must equal the double matrices of mat2 in terms of size. 结果需要是另一个大小与mat2相同的单元格数组results ,因此,在大小上,有条件的双重矩阵必须等于mat2的双重矩阵。

Here's my code to generate mat1 and mat2 for illustrating purposes. 这是我生成mat1mat2代码,用于说明目的。 I am struggling at the point where the multiplication should take place. 我正在努力进行乘法。

rowCells = 5;
colCells = 3;
rowTimeSeries = 300;
colTimeSeries = 5;
slices = [1;10];

% Create 2D double matrix
mat1 = rand(rowTimeSeries, colTimeSeries);

% Create 2D cell matrix comprisiong 2D and/or 3D double matrices
mat2 = cell(rowCells,colCells);

for c = 1:colCells
    for r = 1:rowCells
        slice = randsample(slices, 1, true);
        mat2{r,c} = rand(rowTimeSeries, colTimeSeries, slice);
    end
end

% Multiply (.*) mat1 with mat2 (every slice)

results = cell(rowCells,colCells);

for c = 1:colCells
    for r = 1:rowCells
        results{r,c} = ... % I am struggling here!!!
    end
end

You could use bsxfun to remove the need for your custom function multiply2D3D , it works in a similar way! 你可以使用bsxfun删除需要您自定义函数multiply2D3D ,它的工作原理类似的方式! Updated code: 更新的代码:

results = cell(rowCells,colCells);
for c = 1:colCells
    for r = 1:rowCells
        results{r,c} = bsxfun(@times, mat1, mat2{r,c});
    end
end

This will work for 2D and 3D matrices where the number of rows and cols is the same in each of your "slices", so it should work in your case. 这将适用于2D和3D矩阵,其中每个“切片”中的行数和列数均相同,因此它应适用于您的情况。


You also don't need to loop over the rows and the columns of your cell array separately. 您也不需要分别遍历单元格数组的行和列。 This loop has the same number of iterations, but it is one loop not two, so the code is a little more streamlined: 这个循环具有相同的迭代次数,但是它是一个循环而不是两个循环,因此代码更加精简了:

results = cell(size(mat2));
for n = 1:numel(mat2)   % Loop over every element of mat2. numel(mat2) = rowCells*colCells
    results{n} = bsxfun(@times, mat1, mat2{n});
end

I had almost the exact same answer as Wolfie but he beat me to it. 我得到的答案几乎与沃尔夫完全相同,但他击败了我。

Anyway, here is a one liner that I think is slightly nicer: 无论如何,这是一个我认为稍微好一点的班轮:

nR = rowCells; % Number of Rows
nC = colCells; % Number of Cols
results = arrayfun(@(I) bsxfun(@times, mat1, mat2{I}), reshape(1:nR*nC,[],nC), 'un',0);

This uses arrayfun to perform the loop indexing and bsxfun for the multiplications. 这使用arrayfun执行循环索引,并使用bsxfun进行乘法。


A few advantages 一些优点

1) Specifying 'UniformOutput' ( 'un' ) in arrayfun returns a cell array so the results variable is also a cell array and doesn't need to be initialised (in contrast to using loops). 1)在arrayfun指定'UniformOutput''un'arrayfun返回单元格数组,因此results变量也是单元格数组,不需要初始化(与使用循环相反)。

2) The dimensions of the indexes determine the dimensions of results at the output, so they can match what you like. 2)索引的维度确定输出results的维度,因此它们可以匹配您喜欢的维度。

3) The single line can be used directly as an input argument to a function. 3)单行可以直接用作函数的输入参数。

Disadvantage 坏处

1) Can run slower than using for loops as Wolfie pointed out in the comments. 1)正如Wolfie在评论中指出的, 运行速度可能比使用for循环

One solution I came up with is to outsource the multiplication of a 2D with a 3D matrix into a function. 我想到的一种解决方案是将2D与3D矩阵的乘法外包给一个函数。 However, I am curious to know whether this is the most efficient way to solve this problem? 但是,我很想知道这是否是解决此问题的最有效方法?

rowCells = 5;
colCells = 3;
rowTimeSeries = 300;
colTimeSeries = 5;
slices = [1;10];

% Create 2D double matrix
mat1 = rand(rowTimeSeries, colTimeSeries);

% Create 2D cell matrix comprisiong 2D and/or 3D double matrices
mat2 = cell(rowCells,colCells);

for c = 1:colCells
    for r = 1:rowCells
        slice = randsample(slices, 1, true);
        mat2{r,c} = rand(rowTimeSeries, colTimeSeries, slice);
    end
end

% Multiply (.*) mat1 with mat2 (every slice)

results = cell(rowCells,colCells);

for c = 1:colCells
    for r = 1:rowCells
        results{r,c} = multiply2D3D(mat1, mat2{r,c});
    end
end


function vout = multiply2D3D(mat2D, mat3D)
%MULTIPLY2D3D multiplies a 2D double matrix with every slice of a 3D
% double matrix.
%
% INPUTs:
%   mat2D:
%   2D double matrix
%
%   mat3D:
%   3D double matrix where the third dimension is equal or greater than 1.
%
% OUTPUT:
%   vout:
%   3D double matrix with the same size as mat3D. Every slice in vout
%   is the result of a multiplication of mat2D with every individual slice
%   of mat3D.

[rows, cols,  slices] = size(mat3D);
vout = zeros(rows, cols, slices);

for s = 1 : slices
    vout(:,:,s) = mat2D .* mat3D(:,:,s);
end

end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM