簡體   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