Search code examples
pythonnumpyvectorizationlinear-algebra

"Vectorized" Matrix-Vector multiplication in numpy


I have an $I$-indexed array $V = (V_i)_{i \in I}$ of (column) vectors $V_i$, which I want to multiply pointwise (along $i \in I$) by a matrix $M$. So I'm looking for a "vectorized" operation, wherein the individual operation is a multiplication of a matrix with a vector; that is

$W = (M V_i)_{i \in I}$

Is there a numpy way to do this?

numpy.dot unfortunately assumes that $V$ is a matrix, instead of an $I$-indexed family of vectors, which obviously fails.


So basically I want to "vectorize" the operation

W = [np.dot(M, V[i]) for i in range(N)]

Considering the 2D array V as a list (first index) of column vectors (second index).

If

shape(M) == (2, 2)
shape(V) == (N, 2)

Then

shape(W) == (N, 2)

Solution

  • EDIT:

    Based on your iterative example, it seems it can be done with a dot product with some transposes to match the shapes. This is the same as (M@V.T).T which is the transpose of M @ V.T.

    # Step by step
        ((2,2) @ (5,2).T).T
    ->  ((2,2) @ (2,5)).T
    ->  (2,5).T
    ->  (5,2)
    

    Code to prove this is as follows. Your iterative output results in a matrix W which is exactly equal to the solutions matrix.

    M = np.random.random((2,2))
    V = np.random.random((5,2))
    
    # YOUR ITERATIVE SOLUTION (STACKED AS MATRIX)
    W = np.stack([np.dot(M, V[i]) for i in range(5)])
    print(W)
    
    #array([[0.71663319, 0.84053871],
    #       [0.28626354, 0.36282745],
    #       [0.26865497, 0.55552295],
    #       [0.40165606, 0.10177711],
    #       [0.33950909, 0.54215385]])
    
    
    # PROPOSED DOT PRODUCt
    solution = (M@V.T).T           #<---------------
    print(solution)
    
    #array([[0.71663319, 0.84053871],
    #       [0.28626354, 0.36282745],
    #       [0.26865497, 0.55552295],
    #       [0.40165606, 0.10177711],
    #      [0.33950909, 0.54215385]])
    
    np.allclose(W, solution) #compare the 2 matrices
    
    True
    

    IIUC, your ar elooking for a pointwise multiplication of a matrix M and vector V (with broadcasting).

    The matrix here is (3,3), while V is an array with 4 column vectors, each of which you want to independently multiply with the matrix while obeying broadcasting rules.

    # Broadcasting Rules
    
     M ->     3, 3
     V ->  4, 1, 3   #V.T[:,None,:] 
    ----------------
     R ->  4, 3, 3
    ----------------
    

    Code for this -

    M = np.array([[1,1,1],
                  [0,0,0],
                  [1,1,1]])    #3,3 matrix M
    
    V = np.array([[1,2,3,4],
                  [1,2,3,4],   #4,3 indexed vector
                  [1,2,3,4]])  #store 4 column vectors
                               
    
    
    R = M * V.T[:,None,:]          #<--------------
    R
    
    array([[[1, 1, 1],
            [0, 0, 0],
            [1, 1, 1]],
    
           [[2, 2, 2],
            [0, 0, 0],
            [2, 2, 2]],
    
           [[3, 3, 3],
            [0, 0, 0],
            [3, 3, 3]],
    
           [[4, 4, 4],
            [0, 0, 0],
            [4, 4, 4]]])
    

    Post this if you have any aggregation, you can reduce the matrix with the required operations.

    Example, Matrix M * Column vector [1,1,1] results in -

    array([[[1, 1, 1],
            [0, 0, 0],
            [1, 1, 1]],
    

    while, Matrix M * Column vector [4,4,4] results in -

    array([[[4, 4, 4],
            [0, 0, 0],
            [4, 4, 4]],