Search code examples
python-3.xnumpyarray-broadcastingnumpy-einsum

how do I interpret np.einsum("ijij->ij"


I am trying to make sense of np.einsum, and there does not appear to be examples related to my specific context. There are many good examples in the numpy docs, a guide here, here, and a stackoverflow answer here.

However

There is no example similar to my problem which is np.einsum("ijij->ij", padded_matrix)

where when I output padded_matrix I get

     >> padded_matrix  

>> [[[[[1.         0.         0.         0.33333333 0.         0.33333333]]

   [[0.         1.         0.         0.         0.         0.        ]]

   [[0.         0.         1.         0.         0.         0.        ]]

   [[0.33333333 0.         0.         1.         0.         0.33333333]]

   [[0.         0.         0.         0.         1.         0.        ]]

   [[0.33333333 0.         0.         0.33333333 0.         1.        ]]]]]

padded_matrix is length of 1, and is <class 'numpy.ndarray'>. Unfortunately copying the output for padded matrix does not work. In the actual program, padded_matrix is a call to a function too complicated to include here, hence, why I have copied its output.

The result is [[1. 1. 1. 1. 1. 1.]] but I cannot figure out how the elements were multiplied and then which axis was summed.

Given that I have not provided a working MWE, if anyone can just tell me what "ijij->ij" should do in the context of the given padded_matrix as a <class 'numpy.ndarray'>, I would be grateful.

My best guess is

np.einsum("ii->i,A") views the diagonal of Matrix A, so does this mean that in this usage, i is effectively replaced by ij due to all the padding, so that np.einsum("ijij->ij",padded_matrix) is a view of the diaganol?


Solution

  • There's no multiplication since there's only one argument:

    In [25]: arr = np.arange(36).reshape(1,6,1,6)                                            
    In [26]: arr                                                                             
    Out[26]: 
    array([[[[ 0,  1,  2,  3,  4,  5]],
    
            [[ 6,  7,  8,  9, 10, 11]],
    
            [[12, 13, 14, 15, 16, 17]],
    
            [[18, 19, 20, 21, 22, 23]],
    
            [[24, 25, 26, 27, 28, 29]],
    
            [[30, 31, 32, 33, 34, 35]]]])
    In [27]: np.einsum('ijij->ij', arr)                                                      
    Out[27]: array([[ 0,  7, 14, 21, 28, 35]])
    

    This einsum is effectively a diagonal.

    In [29]: np.einsum('ii->i', arr.squeeze())                                               
    Out[29]: array([ 0,  7, 14, 21, 28, 35])
    In [30]: np.diagonal(arr.squeeze())                                                      
    Out[30]: array([ 0,  7, 14, 21, 28, 35])