Точечное произведение на матрицах большей размерности

#python #numpy #matrix

#питон #тупица #матрица

Вопрос:

Когда я хочу взять точечное произведение 2, 2D-матрица numpy работает так, как задумано

 gt;gt;gt; a = np.random.rand(20,10) gt;gt;gt; b = np.random.rand(10,3) gt;gt;gt; dotP = np.dot(a,b) gt;gt;gt; np.shape(dotP) (20, 3)  

В моем случае я хочу выполнить аналогичную операцию, но с массивами более высоких измерений. В приведенном ниже примере первые 2 измерения a (20 и 10) эквивалентны размерам матрицы в предыдущем примере. И здесь представлены последние 3 измерения (6,5,4). Аналогично в b матрице 10 и 3 взяты из предыдущего примера и введены (6,5,4). Когда я использую операцию с точкой в приведенном ниже примере, я получаю следующий результат.

 gt;gt;gt; a = np.random.rand(20,10,6,5,4) gt;gt;gt; b = np.random.rand(10,6,5,4,3) gt;gt;gt; dotP = np.dot(a,b) gt;gt;gt; np.shape(dotP) (20, 10, 6, 5, 10, 6, 5, 3)  

Чего я хочу добиться, так это операции умножения, подобной следующей:

 gt;gt;gt; dotP = np.dot(a,b) gt;gt;gt; np.shape(dotP) (20, 3, 6, 5, 4)  

Возможное решение-сделать трансляцию в цикле for, но я не уверен, что это лучший способ сделать это:

 dotP = [] for x in range(np.shape(b)[-1]):  dotP.append(np.sum(a * b[:, :, :, :, x], axis=1).reshape((20,1,6,5,4))) dotP = tuple(dotP) dotP = np.hstack(dotP)  

Комментарии:

1. проверять np.matmul . Внимательно прочитайте документы.

Ответ №1:

Основное правило для A.dot(B) состоит в том, что последняя из A пар со 2-й по последнюю из B .

 gt;gt;gt; a = np.random.rand(20,10,6,5,4) gt;gt;gt; b = np.random.rand(10,6,5,4,3) gt;gt;gt; dotP = np.dot(a,b) gt;gt;gt; np.shape(dotP) (20, 10, 6, 5, 10, 6, 5, 3)  

Здесь сумма продуктов находится на общем 4 , с неким внешним продуктом в других измерениях. (20,10,6,5) и(10,6,4,3)

Но вы хотели получить сумму продуктов 10 , которая находится в неправильном месте.

matmul обрабатывает «пакеты», но с тем же «последним из/со 2-го по последнее правило». Тогда это должно сработать с

 (6,5,4,20,10) and (6,5,4,10,3) producing a (6,5,4,20,3)  

где (6,5,4) — общие размеры пакета.

 In [43]: gt;gt;gt; a = np.random.rand(6,5,4,20,10)  ...: gt;gt;gt; b = np.random.rand(6,5,4,10,3)  ...: gt;gt;gt; dotP = np.dot(a,b)  ...: gt;gt;gt; np.shape(dotP) Out[43]: (6, 5, 4, 20, 6, 5, 4, 3)  In [44]:   ...: gt;gt;gt; dotP = np.matmul(a,b)  ...: gt;gt;gt; np.shape(dotP) Out[44]: (6, 5, 4, 20, 3)  

У нас больше контроля над размерами с einsum :

 In [46]: gt;gt;gt; a = np.random.rand(20,10,6,5,4)  ...: gt;gt;gt; b = np.random.rand(10,6,5,4,3)  ...: gt;gt;gt; dotP = np.einsum('ijklm,jklmo-gt;ioklm',a,b)  ...: gt;gt;gt; np.shape(dotP) Out[46]: (20, 3, 6, 5, 4)