2016-07-17 4 views
1

У меня возникают проблемы с векторизацией части моего кода. У меня есть тензор (n, n, m), и я хочу умножить каждый срез в m на вторую (n на n) матрицу (NOT element wise).Векторизация матричного умножения внутри тензора

Вот как это выглядит, как для цикла:

Tensor=zeros(2,2,3); 
Matrix = [1,2; 3,4]; 

for j=1:n 
    Matrices_Multiplied = Tensor(:,:,j)*Matrix; 
    Recursive_Matrix=Recursive_Matrix + Tensor(:,:,j)/trace(Matrices_Multiplied); 
end 

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

ответ

1

Bsxfunning и используя efficient matrix-multiplication, мы могли бы сделать -

% Calculate trace values using matrix-multiplication 
T = reshape(Matrix.',1,[])*reshape(Tensor,[],size(Tensor,3)); 

% Use broadcasting to perform elementwise division across all slices 
out = sum(bsxfun(@rdivide,Tensor,reshape(T,1,1,[])),3); 

Опять же, можно заменить последний шаг с еще одной матрицы-умножения для возможного дальнейшего повышения производительности. Таким образом, все матрицы умножения посвящен решение будет -

[m,n,r] = size(Tensor); 
out = reshape(reshape(Tensor,[],size(Tensor,3))*(1./T.'),m,n) 

Продолжительность испытания

Бенчмаркинг код -

% Input arrays 
n = 100; m = 100; 
Tensor=rand(n,n,m); 
Matrix=rand(n,n); 
num_iter = 100; % Number of iterations to be run for 

tic 
disp('------------ Loopy woopy doops : ') 
for iter = 1:num_iter 
    Recursive_Matrix = zeros(n,n); 
    for j=1:n 
     Matrices_Multiplied = Tensor(:,:,j)*Matrix; 
     Recursive_Matrix=Recursive_Matrix+Tensor(:,:,j)/trace(Matrices_Multiplied); 
    end 
end 
toc, clear iter Recursive_Matrix Matrices_Multiplied 

tic 
disp('------------- Bsxfun matrix-mul not so dull : ') 
for iter = 1:num_iter 
    T = reshape(Matrix.',1,[])*reshape(Tensor,[],size(Tensor,3)); 
    out = sum(bsxfun(@rdivide,Tensor,reshape(T,1,1,[])),3); 
end 
toc, clear T out 

tic 
disp('-------------- All matrix-mul having a ball : ') 
for iter = 1:num_iter 
    T = reshape(Matrix.',1,[])*reshape(Tensor,[],size(Tensor,3)); 
    [m,n,r] = size(Tensor); 
    out = reshape(reshape(Tensor,[],size(Tensor,3))*(1./T.'),m,n); 
end 
toc 

тайминги -

------------ Loopy woopy doops : 
Elapsed time is 3.339464 seconds. 
------------- Bsxfun matrix-mul not so dull : 
Elapsed time is 1.354137 seconds. 
-------------- All matrix-mul having a ball : 
Elapsed time is 0.373712 seconds. 
+0

Есть способ векторизовать этот второй цикл для цикла (тот, который имеет «iter» как индекс)? –

+0

@StevenSagona Этот цикл: 'для iter = 1: num_iter' предназначен только для бенчмаркинга, так что мы запускаем код достаточно долго, чтобы измерения времени выполнения были максимально точными. Если вы не знакомы с временными кодами MATLAB, посмотрите здесь, чтобы использовать timeit: http://stackoverflow.com/a/29719681/3293881 и здесь для другого примера о tic-toc с разминкой: http: // stackoverflow. com/a/26137901/3293881 – Divakar

+0

Простите, я должен был пройти через ваш код перед комментированием. Я понимаю все в коде, за исключением этой строки: '(reshape (Tensor, [], size (Tensor, 3)) * (1./T. ')' Я считаю, что это делает что-то отличное от того, что Я запускал этот код, когда n, m были маленькими, и видел, что векторизованный код не дает того же результата, что и исходный. Я думаю, что это умножение матрицы в конце. Я думал, что, возможно, переключение на элементное умножение будет работать, но он возвращает ошибку. –

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