Умножьте 3D матрицу с 2D матрицей

Если Вы готовы попробовать что-то немного различное, существует платформа ICE от ZeroC. Это - открытый исходный код и поддерживается на в значительной степени каждой ОС, о которой можно думать, а также поддержка языка наличия C++, C#, Java, Ruby, Python и PHP. Наконец, очень легко управлять (отображения языка адаптируются для установки естественно каждому языку). Это также быстро и эффективно. Существует даже усеченная версия для устройств.

25
задан Amro 1 August 2012 в 17:47
поделиться

6 ответов

Вы можете сделать это в одной строке, используя функции NUM2CELL , чтобы разбить матрицу X на массив ячеек и CELLFUN для работы с ячейками:

Z = cellfun(@(x) x*Y,num2cell(X,[1 2]),'UniformOutput',false);

Результат Z - это массив ячеек размером 1 на C , где каждая ячейка содержит матрицу A-by-D . Если вы хотите, чтобы Z было матрицей A-by-D-by-C , вы можете использовать функцию CAT :

Z = cat(3,Z{:});



ПРИМЕЧАНИЕ: Мое старое решение использовало MAT2CELL вместо NUM2CELL , что было не так лаконично:

[A,B,C] = size(X);
Z = cellfun(@(x) x*Y,mat2cell(X,A,B,ones(1,C)),'UniformOutput',false);
15
ответ дан 28 November 2019 в 20:54
поделиться

Вот однострочное решение (два, если вы хотите разделить на 3-е измерение):

A = 2;
B = 3;
C = 4;
D = 5;

X = rand(A,B,C);
Y = rand(B,D);

%# calculate result in one big matrix
Z = reshape(reshape(permute(X, [2 1 3]), [A B*C]), [B A*C])' * Y;

%'# split into third dimension
Z = permute(reshape(Z',[D A C]),[2 1 3]);

Отсюда теперь: Z (:,:, i) содержит результат X (:,:, i) * Y


Пояснение:

Вышеупомянутое может сбивать с толку, но идея проста. Сначала я возьму третье измерение X и проведу вертикальную конкатенацию по первому размеру:

XX = cat(1, X(:,:,1), X(:,:,2), ..., X(:,:,C))

... сложность заключалась в том, что C - это переменная, поэтому вы можете Не обобщайте это выражение с помощью cat или vertcat . Затем мы умножаем это на Y :

ZZ = XX * Y;

Наконец, я разделил его обратно на третье измерение:

Z(:,:,1) = ZZ(1:2, :);
Z(:,:,2) = ZZ(3:4, :);
Z(:,:,3) = ZZ(5:6, :);
Z(:,:,4) = ZZ(7:8, :);

Итак, вы можете видеть, что для этого требуется только одно матричное умножение, но вы должны изменить форму матрица до и после.

8
ответ дан 28 November 2019 в 20:54
поделиться

Нет. Есть несколько способов, но это всегда происходит в цикле, прямом или косвенном.

Просто чтобы удовлетворить мое любопытство, зачем вам это вообще?

1
ответ дан 28 November 2019 в 20:54
поделиться

Я бы подумал о рекурсии, но это единственный другой метод без цикла, который вы можете использовать

0
ответ дан 28 November 2019 в 20:54
поделиться

Вы можете "развернуть" цикл, т.е. последовательно выписать все умножения, которые произойдут в цикле

0
ответ дан 28 November 2019 в 20:54
поделиться

В качестве личного предпочтения я предпочитаю, чтобы мой код был как можно более кратким и читабельным.

Вот что я бы сделал, хотя это не соответствует вашим «безциклам». требование:

for m = 1:C

    Z(:,:,m) = X(:,:,m)*Y;

end

В результате получается матрица A x D x C Z .

И, конечно же, вы всегда можете предварительно выделить Z, чтобы ускорить процесс, используя Z = нули (A, D, C); .

17
ответ дан 28 November 2019 в 20:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: