Python тензорная матрица умножается - PullRequest
0 голосов
/ 23 февраля 2020

У меня есть тензор

A = 
[[[a,b],
  [c,d]],
 [[e,f],
  [g,h]]]

и матрица

B = 
[[1,2],
 [3,4]]

Мне нужно получить

C = 
[[a*1+e*2,b*1+f*2],
 [c*3+g*4,d*3+h*4]]

Как мне это сделать, используя numpy в матричной форме? Я изучил np.tensordot(), но, похоже, в этом случае это не помогает.

Ответы [ 2 ]

2 голосов
/ 23 февраля 2020

Проблема ОП может быть переформулирована в стандартном формате с использованием тензорной записи и так называемого Соглашения Эйнштейна о суммировании

A kij B ik ⇒ C ij

Numpy имеет удобную функцию полезности для выполнения тех тензорных операций, которые можно описать с помощью соглашения о суммировании Эйнштейна, что неудивительно numpy.einsum, что позволяет напрямую отображать тензорную запись в оптимизированные циклы C -уровня с помощью строки инструкций , которая точно отражает тензорную запись 'kij, ik -> ij'

import numpy as np
a = np.arange(8).reshape(2,2,2)+1
b = np.arange(4).reshape(2,2)+1
c = np.einsum('kij, ik -> ij', a, b)
print(c)
# [[11 14]
#  [37 44]]

Достоинства numpy.einsum

  1. Исходный код документирует детали выполненной операции.
  2. np.einsum обычно быстро

    In [12]: import numpy as np 
        ...:  
        ...: i, j, k = 100, 320, 140 # just three largish numbers
        ...: a = np.random.random((k,i,j)) 
        ...: b = np.random.random((i,k))                                                      
    
    In [13]: %timeit np.einsum('kij,ik->ij', a, b)                                            
    7.47 ms ± 82.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    
    In [14]: %timeit (a * b[None,:,:].T).sum(axis = 0)                                        
    49.3 ms ± 6.77 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
1 голос
/ 23 февраля 2020

Вы можете попробовать это:

>>> import numpy as np
>>> a = np.arange(1,9).reshape(2,2,2)
>>> a
array([[[1, 2],
        [3, 4]],

       [[5, 6],
        [7, 8]]])
>>> b = np.arange(1,5).reshape(2,2)
>>> b
array([[1, 2],
       [3, 4]])
>>> (a * b[None,:,:].T).sum(axis = 0)
array([[11, 14],
       [37, 44]])

Промежуточные шаги выглядят так:

>>> b[None,:,:]
array([[[1, 2],
        [3, 4]]])
>>> b[None,:,:].T
array([[[1],
        [3]],

       [[2],
        [4]]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...