#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)