Как работает numpy точек для 3-D матрицы - PullRequest
1 голос
/ 06 мая 2020

как работает numpy .dot для 3-D массивов.

У меня есть:

  • A с формой [15, 30, 500]
  • B с формой [15]

После:

C = np.dot(a.T, B)

Я получаю C с формой [500, 30], но не могу понять как (я хочу перенести код на другой язык без numpy).

Спасибо.

1 Ответ

1 голос
/ 06 мая 2020

Поскольку это похоже на код, написанный другими, и вы хотите понять, что делает этот случай (в частности, не в целом), для целей переноса я воспользуюсь простой демонстрацией:

In [46]: A = np.arange(24).reshape(2,3,4); B = np.array([10,20])                                       
In [47]: A                                                                                             
Out[47]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])
In [48]: A.T                                                                                           
Out[48]: 
array([[[ 0, 12],
        [ 4, 16],
        [ 8, 20]],

       [[ 1, 13],
        [ 5, 17],
        [ 9, 21]],

       [[ 2, 14],
        [ 6, 18],
        [10, 22]],

       [[ 3, 15],
        [ 7, 19],
        [11, 23]]])

dot:

In [50]: C = np.dot(A.T, B)                                                                            
In [51]: C                                                                                             
Out[51]: 
array([[240, 360, 480],
       [270, 390, 510],
       [300, 420, 540],
       [330, 450, 570]])

то же самое, но с использованием широковещательной рассылки, поэлементного умножения и суммы:

In [52]: (A.T * B[None,None,:]).sum(axis=2)                                                            
Out[52]: 
array([[240, 360, 480],
       [270, 390, 510],
       [300, 420, 540],
       [330, 450, 570]])

Или с обозначением индексации einsum :

In [53]: np.einsum('ijk,i->kj',A,B)                                                                    
Out[53]: 
array([[240, 360, 480],
       [270, 390, 510],
       [300, 420, 540],
       [330, 450, 570]])

Промежуточный шаг в поэлементном умножении:

In [54]: (A.T * B[None,None,:])                                                                        
Out[54]: 
array([[[  0, 240],
        [ 40, 320],
        [ 80, 400]],

       [[ 10, 260],
        [ 50, 340],
        [ 90, 420]],

       [[ 20, 280],
        [ 60, 360],
        [100, 440]],

       [[ 30, 300],
        [ 70, 380],
        [110, 460]]])

Итак, это скалярное произведение (скалярное произведение) каждой строки A.T (последнее измерение) с B. Итак, есть одно значение для первых двух измерений (здесь (4,3)).

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