Reputation: 17631
This is an easy question, but I'm getting confused by the size involved.
Using NumPy, I have a 3-dimensional array, shape = (10, 100, 100).
(The way I think of it is as an np.ndarray of 10 "matrices", each shaped 100 by 100, i.e.
arr1 = [M1 M2 M3....M10]
where M1.shape = (100,100), M2.shape = (100,100),...
I also have a second array of data called "arrB", which is arrB.shaped (100,)
. My goal is to do matrix multiplication with these numpy arrays, i.e. (arrB.T)*arr1*(arrB)
, resulting in a single integer. Using numpy arrays, this operation should be completed with np.dot()
op1 = np.dot(arr1, arrB)
op2 = np.dot((arrB.T), op1)
or
endproduct = np.dot((arrB.T), np.dot(arr1, arrB) )
However, this does not work. I get an error:
ValueError: shapes (100,) and (10,100) not aligned: 100 (dim 0) != 10 (dim 0)
If I do the operation on one "matrix" M# at a time, I can perform this operation, i.e.
element1 = arr1[0]
end = np.dot((arrB.T), np.dot(element1, arrB) )
Without splicing my original array, doing the operations, and appending again, how can I perform these operations on my original array arr1
to result in
result = [(arrB.T)*arr1[0]*(arrB) (arrB.T)*arr1[1]*(arrB) (arrB.T)*arr1[2]*(arrB) ...
....(arrB.T)*arr1[9]*(arrB) ]
Upvotes: 0
Views: 1726
Reputation: 231375
With arrB
, shape (100,), .T
does nothing. It needs to be (1,100)
if you want .T
to turn it into a (100,1)
array.
In any case, to do the double dot with a (100,100) element you don't need .T
. Try:
np.dot(arrB, np.dot(element1, arrB) )
With only 10 'elements', the list comprehension or iterative method isn't bad:
out = np.empty((10,))
for i in range(10):
out[i] = np.dot(arrB, np.dot(arrA[i], arrB))
or using a comprehension:
np.array([np.dot(arrB,np.dot(elmt,arrB)) for elmt in arrA] )
np.einsum
is another option:
np.einsum('i,kij,j->k',arrB, arrA, arrB)
np.tensordot
is also designed to work with 3d arrays. It reshapes and transposes its inputs, so they become 2d arrays that np.dot
can use.
np.dot(np.tensordot(arrA,arrB,[(2,),(0,)]),arrB) # needs more testing
You'll have to do some timings with realistic arrays to determine which is most efficient (and readable) for you.
Upvotes: 5
Reputation: 90889
You can use list comprehension for this as -
arr3 = np.array([np.dot(arr2.T , np.dot(arr1[i] , arr2)) for i in range(arr1.shape[0])])
Upvotes: 0