2014-09-16 3 views
5

Предположим, у меня есть матрица элементов следующим образом:эффективно вычислять 3D матрицу внешних продуктов - MATLAB

A = reshape(1:25, 5, 5) 

A = 

1  6 11 16 21 
2  7 12 17 22 
3  8 13 18 23 
4  9 14 19 24 
5 10 15 20 25 

Я хотел бы эффективно вычислять 3D матрицу внешних продуктов, так что я й срезом этой выходной матрицы является внешнее произведение столбца i thA с самим собой. Внешний продукт между двумя векторами u и v равен u*v.', если u и v являются обоими векторами-столбцами.

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

B(:,:,1) = A(:,1) * A(:,1).'; 
B(:,:,2) = A(:,2) * A(:,2).'; 
     ... 
     ... 
B(:,:,5) = A(:,5) * A(:,5).'; 

Мой текущий метод состоит в следующем. Я пытался делать это таким образом, используя arrayfun и cell2mat:

cellmatr = arrayfun(@(x) A(:,x) * A(:,x).', 1:size(A,2), 'uni', 0); 
out = reshape(cell2mat(cellmatr), size(A,1), size(A,1), size(A,2)); 

Я просто перебираем линейный массив индекса между 1 и столько же столбцов, которые мы имеем в A, и для каждого элемента в этом массиве, я получить доступ к соответствующей колонке и вычислить внешний продукт. Таким образом, выход будет давать 1D сетку ячеек, которые затем преобразуются обратно в 2D-матрицу, а затем преобразуются в трехмерную матрицу, чтобы найти 3D-матрицу внешних продуктов.

Однако для больших матриц это довольно медленно. Я также попытался заменить матричный продукт kron (т. Е. kron(A(:,x), A(:,x))) внутри моего вызова arrayfun, но это все еще довольно медленно для моих целей.


Кто-нибудь знает об эффективном способе вычисления этой 3D-матрицы внешних продуктов таким образом?

+0

вы смотрели в это: http://www.mathworks.com/matlabcentral/fileexchange/25977-mtimesx- быстро-матричная-многократная с-многомерная поддержка – bla

+0

@natan - я не, но спасибо за ссылку на FEX! – rayryeng

+0

Интересно, насколько эффективно это будет с ответом Дивакара ... – bla

ответ

8

Это лишь незначительное улучшение по сравнению с Divakar's answer. Это немного быстрее, потому что он заменяет переставлять 3D-массив с перестановочны 2D-массива:

B = bsxfun(@times, permute(A, [1 3 2]), permute(A, [3 1 2])); 
+1

Просто комментарий о времени - когда я ввел это в свой общий алгоритм, время, затраченное на завершение алгоритма с каждым решением, было следующим: «3125 x 3125»: Divakar: 0,403 секунды, Amro: 0,304 секунды, Luis Мендо: 0,244 секунды. Я провел 100 проб случайных данных и усреднил время. – rayryeng

+0

Только что проверил, чтобы убедиться. Это также вычислит комплексный «диагональный» (только соответствующий индекс) набор внешних произведений между векторами в двух отдельных матрицах. Замена второго 'A' на' conj (B) 'будет вычислять' для k = 1: n; С (:,:, к) = A (:, к) * B (:, к) '; конец; '. –

3

Это -

B = permute(bsxfun(@times,A,permute(A,[3 2 1])),[1 3 2]) 
+0

Я всегда борется с 'permute', поэтому мне пришлось разбить каждое утверждение по одному и посмотреть, что происходит на каждом шагу. Я действительно понимаю, что происходит сейчас, и мне жаль, что я не мог понять это сам!В любом случае, я думаю, что это был хороший вопрос, чтобы спросить :) – rayryeng

+2

Это кажется немного быстрее, поскольку он заменяет перестановку трехмерных массивов с помощью преобразования 2D-массива: 'B = bsxfun (@ times, permute (A, [ 1 3 2]), permute (A, [3 1 2])); ' –

+0

@LuisMendo - Ваша настройка в решении фактически превосходит цикл' for'. – rayryeng

7

Чтобы констатировать очевидное, вы пробовали просто для цикла:

[m,n] = size(A); 
B = zeros(m,m,n); 
for i=1:n 
    B(:,:,i) = A(:,i) * A(:,i).'; 
end 

Вы будете удивлены, насколько быстро конкурентно это.

+0

Я не рассматривал цикл 'for', потому что я не думал, что это действительно сработает. Я просто провел несколько тестов, и это на самом деле немного быстрее, чем 'permute/bsxfun'. Красиво сделано Амро. – rayryeng

+3

+1 amro, иногда очевидные потребности также упоминаются. Я также предпочитаю это над bsxfun, гораздо более читаемым ... – bla

+0

Это отличное решение! +1 BTW предварительное распределение с 'B (m, m, n) = 0;' можно было бы рассмотреть. – Divakar

Смежные вопросы