3

I want to compute N group of the dot product, for each group suppose it was a (4,3) matrix, called x_i. So I vectorize these N matrices into a (N,4,3) matrix, such as:

 [[[1,2,3],
   [4,5,6],
   [7,8,9],
   [0,1,2]],
     ...
   [7,2,2],
   [4,2,4],
   [7,1,9],
   [3,1,2]]].  #  #N matrices

If I compute each dot product of x_i and x_i.T individually:

np.dot(x_i, x_i.T)

It will get a (4,4) matrix.

But how to compute these after vectorization?

The final result should be (N,4,4).

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
Yan-Jen Huang
  • 305
  • 1
  • 2
  • 8

4 Answers4

3
In [31]: x = np.arange(5*12).reshape(5,4,3)
In [32]: x@x.transpose(0,2,1)
Out[32]: 
array([[[    5,    14,    23,    32],
        [   14,    50,    86,   122],
        [   23,    86,   149,   212],
        [   32,   122,   212,   302]],

       [[  509,   626,   743,   860],
        [  626,   770,   914,  1058],
        [  743,   914,  1085,  1256],
        [  860,  1058,  1256,  1454]],

       [[ 1877,  2102,  2327,  2552],
        [ 2102,  2354,  2606,  2858],
        [ 2327,  2606,  2885,  3164],
        [ 2552,  2858,  3164,  3470]],

       [[ 4109,  4442,  4775,  5108],
        [ 4442,  4802,  5162,  5522],
        [ 4775,  5162,  5549,  5936],
        [ 5108,  5522,  5936,  6350]],

       [[ 7205,  7646,  8087,  8528],
        [ 7646,  8114,  8582,  9050],
        [ 8087,  8582,  9077,  9572],
        [ 8528,  9050,  9572, 10094]]])
In [33]: _.shape
Out[33]: (5, 4, 4)

checking

In [34]: x[0,...].dot(x[0,...].T)
Out[34]: 
array([[  5,  14,  23,  32],
       [ 14,  50,  86, 122],
       [ 23,  86, 149, 212],
       [ 32, 122, 212, 302]])

@ or matmul does a dot product on the last 2 dimensions, while treating the first, as you do, as the 'i' dimension.

x.tanspose(0,2,1) switches the last 2 dimensions, leaving the first unchanged. For a 2d array x.transpose() is x.transpose(1,0). It is what you expressed as x_i.T.

As with dot, the key for a@b, is that the last dimension of a works with the 2nd to the last dimension of b.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
3

np.matmul will do the trick:

N=2; m=4; n=3
x = np.ones((N,m,n))
np.matmul(x,x.transpose(0,2,1))

array([[[3., 3., 3., 3.],
    [3., 3., 3., 3.],
    [3., 3., 3., 3.],
    [3., 3., 3., 3.]],

   [[3., 3., 3., 3.],
    [3., 3., 3., 3.],
    [3., 3., 3., 3.],
    [3., 3., 3., 3.]]])

Shape checking:

np.matmul(x,x.reshape((N,n,m))).shape

(2, 4, 4)

P.S., as hpaulj mentioned in the comment this solution is basically equivalent to his!

Peybae
  • 1,093
  • 14
  • 25
  • 1
    `matmul` can be expressed as the `@` operator. `reshape` is the not the same as transpose. Your code works because your `x` is all ones. – hpaulj Aug 21 '18 at 19:38
  • Thanks you!! This is what I am looking for! I got the same result using this method to vectorize as using a loop. But now, I am wonder when to use np.matmul or np.dot. – Yan-Jen Huang Aug 22 '18 at 02:09
  • 1
    @Yan-JenHuang this answer can probably help you to understand the differences between dot and matmul: https://stackoverflow.com/questions/34142485/difference-between-numpy-dot-and-python-3-5-matrix-multiplication – Peybae Aug 22 '18 at 16:27
1

seems that np.einsum could do this

x = np.arange(5*12).reshape(5,4,3)
np.einsum("nik, njk->nij", x, x)
Sacry
  • 535
  • 4
  • 9
-1

you can generate a 3D list. I would have make it like:

N=[]
for n in range (len(N)):
    N.append(n,np.dot(x_i, x_i.T))
Roya
  • 1
  • 1
  • 2
    You shouldn't name variables as `list` since that's a builtin and it's not vectorized because you're using a `for` loop. – roganjosh Aug 21 '18 at 17:28
  • I understand your point about names, but why you say it is nor vectorizable? – Roya Dec 12 '18 at 19:35