2017-04-26 277 views
0

我具有恆定的2D雙矩陣mat1內。我也有一個2D單元陣列mat2,其中每個單元包含一個2D或3D雙重矩陣。這些雙矩陣具有與mat1相同的行數和列數。我需要在mat2內乘以(。*)mat1與每個雙重矩陣的每個切片。結果需要被另一單元陣列results與大小相同mat2,由此指含有雙矩陣必須等於的mat2雙矩陣規模而言。MATLAB:乘法2D矩陣與3D矩陣單元陣列

這裏是我的代碼來生成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 

回答

1

你可以使用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 

這將二維和三維矩陣,其中的行列數的數量是每個「片」的同樣的工作,所以應該在你的情況下工作。


您也不需要分開循環遍歷單元格數組的行和列。這個循環有迭代次數相同,但它是一個循環而不是兩個,所以代碼是多一點精簡:

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 
+0

你的代碼是完美的工作。非常感謝。 – Andi

+0

不用擔心,歡呼聲 – Wolfie

0

我想出的一個解決方案是將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 
1

我幾乎完全一樣的答案,莫扎特,但他打我給它。

無論如何,這裏是一個班輪,我認爲是輕微更好:

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)指定'UniformOutput''un')在arrayfun返回單元陣列所以results變量也是一個單元陣列,並且不需要被初始化(對比於使用循環)。

2)指標的尺寸決定的results尺寸的輸出,這樣他們可以匹配你喜歡什麼。

3)單線,可直接使用作爲輸入參數傳遞給函數。

缺點

1)Can run slower比使用for環路作爲莫扎特在評論指出。

+1

良好的答案/代碼雅各布,我沒有想過使用'arrayfun'!雖然也許值得注意一個*劣勢。我剛剛做了一些測試,看起來使用'arrayfun'比輸入的各種尺寸循環要慢。看到這個SO問題,最重要的答案是關於'arrayfun'的開銷和速度問題的一些深入:http://stackoverflow.com/questions/12522888/arrayfun-can-be-signedificantly-slower-than -an-explicit-loop-in-matlab-why – Wolfie

+0

@JacobD你的代碼也完美的工作,但是,我更喜歡Wolfie的解決方案。我的主要優點是代碼更易於閱讀和理解。但這是我個人的看法。 – Andi

+1

@Wolfie好點,我忘了用'arrayfun'添加一些關於速度/開銷的東西。對於小尺寸,它可能不是問題,但放大是的,肯定會浪費一些時間。我可以想象,在這種情況下使用'arrayfun'或'for'循環的速度差異將強烈依賴於'內部'和'外部'矩陣大小的比率(OP表示「單元格」與「時間序列」 )。 – JacobD