Hello Stack Overflow,
I am able to get desired results through a loop but wondering how I can apply a dot product per row of a 2D array. I'm trying to take each row from A and apply a series of dot products with B. It's a bit wonky right now with my intermediate results but I do get my desired results. Looking to vectorize and eliminate the loop.
A = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
B = np.array([[9,-1,8],[-12,20,-5],[6,1,4]])
int_result = np.ones((len(A),3))
for r in np.arange(0,len(A)):
int_result[r] = A[r].T.dot(B).dot(A[r])
print(int_result)
desired_result = int_result[:,0]
print(desired_result)
Intermediate Results
[[ 117. 117. 117.]
[ 744. 744. 744.]
[1911. 1911. 1911.]
[3618. 3618. 3618.]]
Desired Results
[ 117. 744. 1911. 3618.]
CodePudding user response:
This is 2 np.matmul
multiplications, using the first dimension of A
as the batch
dimension:
In [55]: A = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
...: B = np.array([[9,-1,8],[-12,20,-5],[6,1,4]])
In [56]: A
Out[56]:
array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]])
In [57]: B
Out[57]:
array([[ 9, -1, 8],
[-12, 20, -5],
[ 6, 1, 4]])
In [58]: A.shape
Out[58]: (4, 3)
In [59]: B.shape
Out[59]: (3, 3)
Adding dimensions to A
to make it (4,1,3) and (4,3,1), we can do:
In [60]: (A[:,None,:]@B@A[:,:,None]).shape
Out[60]: (4, 1, 1)
and removing the size 1 dimensions:
In [61]: (A[:,None,:]@B@A[:,:,None]).squeeze()
Out[61]: array([ 117, 744, 1911, 3618])
The einsum
equivalent is equally good:
In [62]: np.einsum('ij,kj,ik->i',A,B,A)
Out[62]: array([ 117, 744, 1911, 3618])
In your loop:
In [65]: r=3; A[r]@B@A[r] # A[r] is 1d, so T isn't needed
Out[65]: 3618