умножение «поперек» в двух массивах numpy

#python #arrays #numpy

Вопрос:

Учитывая два массивных массива формы (25, 2) , и (2,) их можно легко умножить на:

 import numpy as np

a = np.random.rand(2, 25)
b = np.random.rand(2)

(a.T * b).T  # ok, shape (2, 25)
 

У меня аналогичная ситуация , когда b есть форма (2, 4) , и я хотел бы получить те же результаты, что и выше, для всех «4» b . Следующие работы,

 a = np.random.rand(25, 2)
b = np.random.rand(2, 4)

c = np.moveaxis([a * bb for bb in b.T], -1, 0)  # shape (2, 4, 25)
 

но у меня есть предчувствие, что это возможно и без moveaxis этого .

Есть какие-нибудь идеи?

Ответ №1:

 In [185]: a = np.random.rand(2, 25)
     ...: b = np.random.rand(2)
 

Умножение возможно с помощью broadcasting :

 In [186]: a.shape
Out[186]: (2, 25)
In [187]: a.T.shape
Out[187]: (25, 2)
In [189]: (a.T*b).shape
Out[189]: (25, 2)
 

(25,2) * (2,) => (25,2) * (1,2) => (25,2). Транспонирование-это a moveaxis , изменение результата на (2,25)

В вашем втором случае.

 In [191]: c = np.moveaxis([a * bb for bb in b.T], -1, 0)
In [192]: c.shape
Out[192]: (2, 4, 25)
In [193]: np.array([a * bb for bb in b.T]).shape
Out[193]: (4, 25, 2)
 

b.T есть (4,2), так bb же как и (2,); с (25,2) a , производит (25,2), как указано выше. добавьте в (4,) итерацию.

(25,1,2) * (1,4,2) => (25,4,2), который может быть перенесен в (2,4,25)

 In [195]: (a[:,None]*b.T).shape
Out[195]: (25, 4, 2)
In [196]: np.allclose((a[:,None]*b.T).T,c)
Out[196]: True
 

(2,4,1) * (2,1,25) => (2,4,25)

 In [197]: (b[:,:,None] * a.T[:,None]).shape
Out[197]: (2, 4, 25)
In [198]: np.allclose((b[:,:,None] * a.T[:,None]),c)
Out[198]: True
 

Ответ №2:

Альтернатива с numpy.einsum :

 np.einsum('ij,jk->jki', a, b)
 

Результаты проверки совпадают:

 (np.einsum('ij,jk->jki', a, b) == c).all()
True