2016-03-17 2 views
1

Я пытаюсь выполнить умножение матрицы с фронтальными срезами трехмерного тензора, показанного ниже. Если X.shape == (N, N) и Y.shape == (N, N, Y), то полученный тензор должен иметь форму (N, N, Y).Тенденционный тензор: Tensordot над лобными срезами тензора

Что такое правильный np.tensordot синтаксис для этого?

Я пытаюсь ограничить себя np.tensordot, а не np.einsum, потому что я хочу позже перевести это решение на Theano. К сожалению, у Theano еще нет np.einsum.

enter image description here

График адаптированного this paper о тензорном умножении. Не-tensordot ответ эквивалентно следующему

tensor = np.random.rand(3, 3, 2) 
X = np.random.rand(3, 3) 

output = np.zeros((3, 3, 2)) 
output[:, :, 0] = X.dot(tensor[:, :, 0]) 
output[:, :, 1] = X.dot(tensor[:, :, 1]) 

ответ

1

Восстановление вдоль axis=1 для X и axis=0 для tensor, таким образом, np.tensordot на основе решение было бы -

np.tensordot(X,tensor, axes=([1],[0])) 

Пояснение:

Возьмем ваше итерационное решение для объяснения и в нем первая итерация:

output[:, :, 0] = X.dot(tensor[:, :, 0]) 

В скалярном произведении, первый вход X, форма которого (N x N), а второй вход tensor[:, :, 0], который является первым срезом вдоль последней оси и его форма (N x N). Этот точечный продукт вызывает уменьшение вдоль второй оси X, то есть axis=1 и вдоль первой оси, то есть axis=0 от tensor[:, :, 0], что также является первой осью всей матрицы tensor. Теперь это продолжается во всех итерациях. Поэтому даже в большой картине нам нужно сделать то же самое: уменьшить/потерять axis=1 в X и axis=0 в тензоре, как и мы!


Интеграция @ ответ hlin117 в

np.tensordot(X,tensor, axes=([1],[0])) 

Хронометраж:

>>> N = 200 
>>> tensor = np.random.rand(N, N, 30) 
>>> X = np.random.rand(N, N) 
>>> 
>>> %timeit np.tensordot(X, tensor, axes=([1], [0])) 
100 loops, best of 3: 14.7 ms per loop 
>>> %timeit np.tensordot(X, tensor, axes=1) 
100 loops, best of 3: 15.2 ms per loop 
+0

Это дает мне тот же ответ, что и выше. Спасибо! – hlin117

+0

Последний вопрос, @ Дивакар. Теперь я хочу выполнить вышеуказанное, используя боковые срезы, используя тензор '(n, m, m). ('output [0,:,:] = X.dot (Tensor [0,:,:])' и т. д. Я пробовал 'np.tensor (X, Tensor, axes = ([1], [1 ]) ', но это не дает мне желаемых результатов.Каким должен быть параметр 'axes' в этом случае? – hlin117

+1

@ hlin117 Из-за того, как вы сохраняете вывод, вам необходимо затем транспонировать: 'np.tensordot (X, тензор, оси = ([1], [1])). Транспонировать (1,0,2)' , – Divakar

1

кажется выше, эквивалентно следующему:

np.tensordot(X, tensor, axes=1) 

axes=1, потому что (если axes аргумент является скаляром) N должна быть последней осью первого аргумента, а N должна быть первой осью второго аргумента.

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