I want to multiply a 3D tensor with a 2D tensor and get a 2D tensor as result. The way I envision this to be done is rather strange, so I ask for your help.
The 3D tensor, for when we fix the value of the first dimension to some integer within range(3D_tensor.shape[0]), is a 2D matrix. We picture this 2D matrix as:
[[a0, b0, c0], [d0, e0, f0], [g0, h0, p0]]
I want this to be multiplied by the 2D tensor (see above) which can be pictured as:
[[10, 20, 30], [40, 50, 60], [70, 80, 90]]
The multiplication shall not be a matrix-matrix multiplication, but each row from the (left ) 2D matrix to be multiplied, element wise, with the corresponding row from the 2D tensor.
The result shall be a 3 element array: [a0 * 10 + b0 * 20 + c0 * 30, d0 * 40, e0 * 50, f0 * 60, g0 * 70 + h0 * 80 + p0 * 90].
This multiplication procedure repeats for all the other "slices" of the 3D tensor. That is, if the 2D matrix picture above was for 3D_tensor[0, :, :], then we would have [[a1, b1, c1], [d1, e1, f1] ,[g1, h1, p1]] for 3D_tensor[1, :, :], and the result shall be [a1 * 10 + b1 * 20 + c1 * 30, d1 * 40 + e1 * 50 + f1 * 60, g1 * 70 + h1 * 80 + p1 * 90].
These 3-element 1D arrays shall be glued together into a bigger 2D array (the result I want to obtain), where each 3-element 1D array to be one of the 2D array’s rows (so place them horizontally).
That would be, my final result in the pictures above, is a 2D array:
[ [a0 * 10 + b0 * 20 + c0 * 30, d0 * 40, e0 * 50, f0 * 60, g0 * 70 + h0 * 80 + p0 * 90], [a1 * 10 + b1 * 20 + c1 * 30, d1 * 40 + e1 * 50 + f1 * 60, g1 * 70 + h1 * 80 + p1 * 90] ]
Ideally, I want this to be done with the BLAS routines, but using numpy. Is what I want to obtain possible?
I know about np.dot, multiply, @, … , and tried to use them, but I cannot figure how I can do the above, EFFICIENTLY, myself.
Thank you!
>Solution :
Use:
import numpy as np
tensor3d = np.arange(27).reshape((3, 3, 3))
tensor2d = np.array([[10, 20, 30], [40, 50, 60], [70, 80, 90]])
res = (tensor3d * tensor2d).sum(2)
print(res)
Output
[[ 80 620 1700]
[ 620 1970 3860]
[1160 3320 6020]]
The expression:
tensor3d * tensor2d
returns:
[[[ 0 20 60]
[ 120 200 300]
[ 420 560 720]]
[[ 90 200 330]
[ 480 650 840]
[1050 1280 1530]]
[[ 180 380 600]
[ 840 1100 1380]
[1680 2000 2340]]]
basically element-wise multiplication, as requested. Then:
.sum(2)
sums the results across the third axis (2 for 0 based indexing). For example, for the first row of the final result:
80 = 0 + 20 + 60
620 = 120 + 200 + 300
1700 = 420 + 560 + 720