У меня нет доступа к matlab, поэтому я пробую кое-что с октавой .Как бы вы эффективно реализовали тензорное произведение, описанное в следующей формуле?
Мой подход для тензоров произвольного порядка a
и b
следующий
% Tensor product
function out = tp(a,b)
if isvector(a)
da = prod(size(a));
else
da = size(a);
endif
if isvector(b)
db = prod(size(b));
else
db = size(b);
endif
out = reshape(a(:)*(b(:)'),[da,db]);
endfunction
if
операторы существуют только для того, чтобы уловить случай, когда a
или b
являются векторами.Я не знаю, является ли это эффективным подходом, так как я обычно не программирую, и я новичок в октаве.Каков будет ваш подход?
Я буду использовать норму Фробениуса, см. Рисунок ниже, чтобы увидеть, есть ли разница с явным вычислением.
Ниже приведены некоторые явные вычисления для проверки реализации.Это прекрасно работает, но я хотел спросить, есть ли лучший способ сделать это для тензоров произвольного порядка.Спасибо!
% Frobenius norm
function out = nf(a)
out = sqrt(a(:)'*a(:));
endfunction
% Tests for (m,n)
% (1,1)
disp("(1,1)")
a = rand(4,1);
b = rand(7,1);
c1 = tp(a,b);
c2 = zeros(4,7);
for i1=1:4 for i2=1:7
c2(i1,i2) = a(i1)*b(i2);
endfor endfor
size(c1)
size(c2)
nf(c1-c2)
%(1,2)
disp("(1,2)")
a = rand(4,1);
b = rand(7,3);
c1 = tp(a,b);
c2 = zeros(4,7,3);
for i1=1:4 for i2=1:7 for i3=1:3
c2(i1,i2,i3) = a(i1)*b(i2,i3);
endfor endfor endfor
size(c1)
size(c2)
nf(c1-c2)
%(2,1)
disp("(2,1)")
a = rand(4,2);
b = rand(1,3);
c1 = tp(a,b);
c2 = zeros(4,2,3);
for i1=1:4 for i2=1:2 for i3=1:3
c2(i1,i2,i3) = a(i1,i2)*b(i3);
endfor endfor endfor
size(c1)
size(c2)
nf(c1-c2)
%(3,2)
disp("(3,2)")
a = rand(4,2,5);
b = rand(7,3);
c1 = tp(a,b);
c2 = zeros(4,2,5,7,3);
for i1=1:4 for i2=1:2 for i3=1:5 for i4=1:7 for i5=1:3
c2(i1,i2,i3,i4,i5) = a(i1,i2,i3)*b(i4,i5);
endfor endfor endfor endfor endfor
size(c1)
size(c2)
nf(c1-c2)
РЕДАКТИРОВАТЬ
Я взглянул на пакет tenorlab, см. Ответ Метахоминида ниже, и это фантастика.Просто для любопытства я хотел проверить производительность по времени между моей реализацией, реализацией Андраса Дика (см. Его ответ ниже) и пакетом tennslab.
% See Andras Deak answer
function c=tensorprod(a, b)
b_inj = reshape(b, [ones(1,ndims(a)), size(b)]);
c = a.*b_inj;
end
% Tests
a = rand(10,11,12);
b = rand(9,8,7);
tic; c1=outprod(a,b); t1=toc % tensorlab, see Metahominid's answer
tic; c2=tp(a,b); t2=toc % my approach
tic; c3=tensorprod(a,b); t3=toc % Andras Deak's approach
disp("Check size")
size(c1)
size(c2)
size(c3)
disp("Check Frobenius norm")
frob(c1) % from tensorlab
nf(c2)
disp("Check equality of elements")
nf(c1-c2)
nf(c1-c3)
disp("Compare time performance relative to tp(a,b)")
t1/t2
t3/t2
Соотношение времени вычислений t1 реализации тензорного потока outprod (соответствующего моему tp) и t2 для tp для рассматриваемых измерений около 2-4 (по крайней мере, на моем компьютере).Это, безусловно, так, поскольку в моей реализации я не проверяю наличие ошибок на входе и не отлавливаю неопределенные случаи.Почти то же самое наблюдается для t3 / t2, сравнивая подход Андраса Дика к моему.Пожалуйста, не поймите меня неправильно, я не пытаюсь похвастаться, но хочу дать несколько заключительных замечаний для людей, которые могут быть заинтересованы в этом.Вывод: если вам нужно что-то для небольших тензоров на ходу, моя простая реализация может быть полезна для вас, если вам нужно больше вещей, вам определенно стоит взглянуть на тензорный меч (см. Ответ Метахоминида ниже).Спасибо за ответы и отзывы!