Reputation: 11
I have the following einsum expressions:
np.einsum("abc,ab->ac",a,b)
np.einsum("abc,abd->dc", a, b)
That I would need to convert to standard numpy operations. Can anyone help me?
Upvotes: 1
Views: 119
Reputation: 231550
np.einsum("abc,ab->ac",a,b)
treats a
as the batch
dimension, carried through unchanged. b
is the sum-of-products dimension.
(a*b[:,:,None]).sum(axis=1)
should be one equivalent
(a.transpose(0,2,1) @ b[:,:,None])[:,:,0]
should also work - but I'll need to run a test case to be sure.
np.einsum("abc,abd->dc", a, b)
does sum-of-products on 'ab', with 'dc' reversed
(a[:,:,None,:]*b[:,:,:,None]).sum(axis=(0,1))
forms a 'abdc' product, and then sums.
b.reshape(-1,b.shape[-1]).transpose() @ a.reshape(-1,a.shape[-1])
is my guess at the matmul
version. reshape
reduces the 'ab' dimensions to one.
The matmul
equivalents have to have the form
(B,N,M) @ (B,M,O) -> (B,N,O)
with B
as batch, M
as sum-of-products
In [7]: a,b,c,d = 2,3,4,5
In [8]: A = np.arange(a*b*c).reshape(a,b,c); B = np.arange(a*b).reshape(a,b)
In [9]: C = np.einsum('abc,ab->ac',A,B)
In [10]: C.shape
Out[10]: (2, 4)
In [11]: D = (A*B[:,:,None]).sum(axis=1)
In [12]: D.shape
Out[12]: (2, 4)
In [13]: np.allclose(C,D)
Out[13]: True
In [16]: E=(A.transpose(0,2,1) @ B[:,:,None])[:,:,0]
In [17]: E.shape
Out[17]: (2, 4)
In [18]: np.allclose(C,E)
Out[18]: True
and
In [19]: B=np.arange(a*b*d).reshape(a,b,d)
In [20]: C=np.einsum("abc,abd->dc", A,B)
In [21]: C.shape
Out[21]: (5, 4)
In [22]: D=(A[:,:,None,:]*B[:,:,:,None]).sum(axis=(0,1))
In [23]: D.shape
Out[23]: (5, 4)
In [24]: np.allclose(C,D)
Out[24]: True
In [25]: E=B.reshape(-1,B.shape[-1]).transpose() @ A.reshape(-1,A.shape[-1])
In [26]: E.shape
Out[26]: (5, 4)
In [27]: np.allclose(C,E)
Out[27]: True
Upvotes: 2