繁体   English   中英

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

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

我有一个恒定的二维双矩阵mat1 我也有一个2D单元阵列mat2 ,其中每个单元都包含一个2D或3D双矩阵。 这些双矩阵具有与mat1相同的行数和列mat1 我需要在mat2的每个双mat1矩阵的每个切片上点乘(。*) mat1 结果需要是另一个大小与mat2相同的单元格数组results ,因此,在大小上,有条件的双重矩阵必须等于mat2的双重矩阵。

这是我生成mat1mat2代码,用于说明目的。 我正在努力进行乘法。

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

你可以使用bsxfun删除需要您自定义函数multiply2D3D ,它的工作原理类似的方式! 更新的代码:

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

这将适用于2D和3D矩阵,其中每个“切片”中的行数和列数均相同,因此它应适用于您的情况。


您也不需要分别遍历单元格数组的行和列。 这个循环具有相同的迭代次数,但是它是一个循环而不是两个循环,因此代码更加精简了:

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

我得到的答案几乎与沃尔夫完全相同,但他击败了我。

无论如何,这是一个我认为稍微好一点的班轮:

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);

这使用arrayfun执行循环索引,并使用bsxfun进行乘法。


一些优点

1)在arrayfun指定'UniformOutput''un'arrayfun返回单元格数组,因此results变量也是单元格数组,不需要初始化(与使用循环相反)。

2)索引的维度确定输出results的维度,因此它们可以匹配您喜欢的维度。

3)单行可以直接用作函数的输入参数。

坏处

1)正如Wolfie在评论中指出的, 运行速度可能比使用for循环

我想到的一种解决方案是将2D与3D矩阵的乘法外包给一个函数。 但是,我很想知道这是否是解决此问题的最有效方法?

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