Почему tenordot / reshape не согласны с кроной?

1

Если я определяю массив X с формой (2, 2):

X = np.array([[1, 2], [3, 4]])

и возьмите кронекер-продукт, затем измените результат, используя

np.kron(X, X).reshape((2, 2, 2, 2))

Я получаю результирующую матрицу:

array([[[[ 1,  2],
         [ 2,  4]],

        [[ 3,  4],
         [ 6,  8]]],


       [[[ 3,  6],
         [ 4,  8]],

        [[ 9, 12],
         [12, 16]]]])

Однако, когда я использую np.tensordot(X, X, axes=0) выводится следующая матрица

array([[[[ 1,  2],
         [ 3,  4]],

        [[ 2,  4],
         [ 6,  8]]],


       [[[ 3,  6],
         [ 9, 12]],

        [[ 4,  8],
         [12, 16]]]])

который отличается от первого выхода. Почему это так? Я нашел это при поиске ответов, однако я не понимаю, почему это решение работает или как обобщать на более высокие размеры.

Теги:
numpy
tensor
matrix

1 ответ

1

Мой первый вопрос: почему вы ожидаете, что они будут такими же?

Пусть делают kron без перестройки:

In [403]: X = np.array([[1, 2],
     ...:               [3, 4]])
     ...:               
In [404]: np.kron(X,X)
Out[404]: 
array([[ 1,  2,  2,  4],
       [ 3,  4,  6,  8],
       [ 3,  6,  4,  8],
       [ 9, 12, 12, 16]])

Легко визуализировать действие.

[X*1, X*2
 X*3, X*4]

tensordot обычно считается обобщением np.dot, способным обрабатывать более сложные ситуации, чем общий матричный продукт (т.е. сумма произведений на одной или нескольких осях). Но здесь нет суммирования.

In [405]: np.tensordot(X,X, axes=0)
Out[405]: 
array([[[[ 1,  2],
         [ 3,  4]],

        [[ 2,  4],
         [ 6,  8]]],


       [[[ 3,  6],
         [ 9, 12]],

        [[ 4,  8],
         [12, 16]]]])

Когда axes представляют собой целое число, а не кортеж, действие немного сложно понять. Документы говорят:

''axes = 0'' : tensor product :math:'a\otimes b'

Я просто попытался объяснить, что происходит, когда axes являются скалярными (это не тривиально). Как работает функция numpy.tensordot поэтапно?

Указание axes=0 эквивалентно предоставлению этого кортежа:

np.tensordot(X,X, axes=([],[]))

В любом случае на выходе видно, что этот тензордот производит одинаковые числа, но макет отличается от kron.

Я могу воспроизвести kron схему с помощью

In [424]: np.tensordot(X,X,axes=0).transpose(0,2,1,3).reshape(4,4)
Out[424]: 
array([[ 1,  2,  2,  4],
       [ 3,  4,  6,  8],
       [ 3,  6,  4,  8],
       [ 9, 12, 12, 16]])

То есть я обмениваю средние 2 оси.

И, упуская форму, я получаю то же самое (2,2,2,2), которое вы получаете от kron:

np.tensordot(X,X,axes=0).transpose(0,2,1,3)

Мне нравится np.einsum:

np.einsum('ij,kl->ijkl',X,X)    # = tensordot(X,X,0)
np.einsum('ij,kl->ikjl',X,X)    # = kron(X,X).reshape(2,2,2,2)

Или, используя трансляцию, 2 продукта:

X[:,:,None,None]*X[None,None,:,:]   # tensordot 0
X[:,None,:,None]*X[None,:,None,:]   # kron

Ещё вопросы

Сообщество Overcoder
Наверх
Меню