Обобщенный матричный продукт - PullRequest
8 голосов
/ 09 ноября 2011

Я довольно новичок в MATLAB. Нормальное матричное умножение матрицы M x K на матрицу K x N - C = A * B - имеет c_ij = sum(a_ik * b_kj, k = 1:K). Что, если я хочу, чтобы это было вместо c_ij = sum(op(a_ik, b_kj), k = 1:K) для некоторой простой двоичной операции op? Есть ли хороший способ векторизовать это в MATLAB (или, может быть, даже встроенную функцию)?

РЕДАКТИРОВАТЬ: В настоящее время это лучшее, что я могу сделать.

% A is M x K, B is K x N
% op is min
C = zeros(M, N);
for i = 1:M:
    C(i, :) = sum(bsxfun(@min, A(i, :)', B));
end

Ответы [ 4 ]

2 голосов
/ 14 июня 2014

В этом посте приведен векторизованный подход, который сохраняется с bsxfun с использованием permute для создания одноэлементных измерений, необходимых bsxfun для разрешения singleton-expansionсделать свою работу и, таким образом, по существу, заменив цикл в исходном посте.Напоминаем, что bsxfun является реализацией, требующей большого объема памяти, поэтому ожидайте ускорения с ней только до тех пор, пока она не будет слишком растянута.Вот окончательный код решения -

op = @min;   %// Edit this with your own function/ operation
C = sum(bsxfun(op, permute(A,[1 3 2]),permute(B,[3 2 1])),3)

NB. - Приведенное выше решение было вдохновлено Удаление четырех вложенных циклов в Matlab .

1 голос
/ 09 ноября 2011

, если оператор может работать поэлементно (например, .*):

if(size(A,2)~=size(B,1))
    error(blah, blah, blah...);
end

C = zeros(size(A,1),size(B,2));
for i = 1:size(A,1)
    for j = 1:size(B,2)
        C(i,j) = sum(binaryOp(A(i,:)',B(:,j)));
    end
end
0 голосов
/ 14 июня 2014

В зависимости от ваших конкретных потребностей, вы можете использовать bsxfun в 3D для обмана двоичного оператора.См. Этот ответ для получения дополнительной информации: https://stackoverflow.com/a/23808285/1121352 Другой альтернативой может быть использование cellfun с пользовательской функцией: http://matlabgeeks.com/tips-tutorials/computation-using-cellfun/

0 голосов
/ 09 ноября 2011

Вы всегда можете написать циклы самостоятельно:

A = rand(2,3);
B = rand(3,4);

op = @times;            %# use your own function here
C = zeros(size(A,1),size(B,2));
for i=1:size(A,1)
    for j=1:size(B,2)
        for k=1:size(A,2)
            C(i,j) = C(i,j) + op(A(i,k),B(k,j));
        end
    end
end

isequal(C,A*B)
...