Умножить столбцы матрицы с 2-мерными срезами матрицы 3d-матрицы в MatLab - PullRequest
4 голосов
/ 02 января 2012

По сути, я хочу выполнить следующие вычисления:

    G is m x n x k
    S is n x k

    Answer=zeros(m,d)
    for Index=1:k
        Answer(:,Index)=G(:,:,Index)*S(:,Index)
    end

Итак, ответ - это матрица, столбцы которой являются результатом умножения каждого слоя 3d-матрицы на столбец другой матрицы.

Это действительно похоже на простой тип операции, и я надеялся выяснить, существует ли собственный или векторизованный (или, по крайней мере, >> более быстрый) способ выполнения этого типа вычислений в Matlab.Спасибо.

Ответы [ 3 ]

2 голосов
/ 02 января 2012

Попробуйте использовать mtimesx из Matlab File Exchange . Это лучший (быстрый / эффективный) инструмент, который я нашел на сегодняшний день для такого рода умножения n-мерных массивов, поскольку он использует mex. Я думаю вы также можете использовать bsxfun, но моего Matlab-fu недостаточно для такого рода вещей.

У вас есть m x n x k и m x k, и вы хотите произвести n x k.

mtimesx умножает входные данные, такие как i x j x k и j x r x k, чтобы получить i x r x k.

Чтобы поместить вашу проблему в форму mtimesx, пусть G будет m x n x k, а расширение S будет n x 1 x k. Тогда mtimesx(G,S) будет m x 1 x k, который затем можно будет сплющить до m x k.

m=3; 
n=4; 
k=2;
G=rand(m,n,k);
S=rand(n,k);

% reshape S
S2=reshape(S,n,1,k);

% do multiplication and flatten mx1xk to mxk
Ans_mtimesx = reshape(mtimesx(G,S2),m,k)

% try loop method to compare
Answer=zeros(m,k);
for Index=1:k
    Answer(:,Index)=G(:,:,Index)*S(:,Index);
end

% compare
norm(Ans_mtimesx-Answer)
% returns 0.

Итак, если вы хотите однострочник, вы можете сделать:

Ans = reshape(mtimesx(G,reshape(S,n,1,k)),m,k)

Кстати, если вы опубликуете свой вопрос на форумах Matlab Newsreader , будет много гуру, которые будут соревноваться, чтобы дать вам ответы более элегантные или эффективные, чем мои!

1 голос
/ 16 августа 2013

Вот версия bsxfun (). Если A является матрицей размером m на n, а x является вектором размером 1 на 1 тогда A * x может быть вычислено как

sum(bsxfun(@times, A, x'), 2)

Операция permute (S, [3 1 2]) возьмет столбцы S и распределит их по 3-му измерению в виде строк. [3 1 2] является перестановкой размеров S.

Таким образом, сумма (bsxfun (@times, G, перестановка (S, [3 1 2])), 2) достигает ответа, но оставляет результат в 3-м измерении. Чтобы получить его в нужной форме требуется еще одна перестановка.

permute(sum(bsxfun(@times, G, permute(S, [3 1 2])), 2), [1 3 2])
0 голосов
/ 02 января 2012

Одна вещь, которую вы можете сделать, это представить вашу 3d-матрицу в виде 2-мерной диагональной матрицы, где каждый слой является диагональным блоком. В этом случае двумерная матрица должна быть представлена ​​в виде вектора, содержащего сложенные столбцы. если матрица большая, объявите ее как разреженную матрицу.

...