More views: concatenation, index lists, repeats of whole matrices, columns or rows

Issue #44 resolved
Marcin Junczys-Dowmunt created an issue

Hi again, Another few things that would be immensely useful:

  1. A view that allows to subselect rows/columns based on a vector of indeces, possible with repetitions, permutations.
  2. A view that allows for the concatenation of two or more matrices along specified dimensions.
  3. Somewhat similar to the two above: A view that allows for the repetition of a whole matrix along a specified axis n times.
  4. A view that allow for the repetition of all rows/columns n-times (the repeated rows would appear after one another).

I guess 2-4 could actually be implemented based on 1. alone.

Sorry, for spamming your issues lists.

Comments (11)

  1. Klaus Iglberger

    Hi Marcin!

    Thanks for all the good ideas. They will keep us busy for a while ;-)

    Best regards,

    Klaus!

  2. Marcin Junczys-Dowmunt reporter

    Oooh, one more!

    A reshaping view, like numpy's reshape operation.

    Where in your code would I look for inspirations if I wanted to take a jab at some of those ideas myself? I will be happy to contribute back if something comes out of it.

  3. Evan Berkowitz

    It seems that you can already reshape dense matrices, using CustomMatrix.

    Here's an example that a colleague and I came up with today:

            blaze::DynamicVector<double> v{1,2,3,-1,-2,-3};
            blaze::DynamicVector<double> u{0,0,0,0,0,0};
            blaze::DynamicMatrix<double> space_matrix{{1,3},{4,7}};
            blaze::CustomMatrix<double,blaze::unaligned,blaze::unpadded,blaze::rowMajor> vit(&v[0], 2, 3);
            blaze::CustomMatrix<double,blaze::unaligned,blaze::unpadded,blaze::rowMajor> ujs(&u[0], 2, 3);
            ujs = space_matrix * vit;
    
            std::cout << ujs << '\n';
            std::cout << u << std::endl;
    

    which correctly spits out

    (           -2           -4           -6 )
    (           -3           -6           -9 )
    
    (          -2 )
    (          -4 )
    (          -6 )
    (          -3 )
    (          -6 )
    (          -9 )
    

    I don't know if similar tricks will work on sparse types.

  4. Klaus Iglberger

    Hi Evan!

    Thanks a lot for sharing this solution. It's great to see that the available features already provide such flexibility. Unfortunately this trick does not work on sparse matrices, as CustomMatrix only works on arrays and always represents a dense matrix. However, in just a few weeks we will release row and column selection views, which will enable (almost) all of the features requested above. If you are interested, check out issue #48, which we are currently working on. It is already possible to select specific elements from a dense or sparse vector, the selection of rows and columns from dense and sparse matrices will be available soon.

    Thanks again,

    Best regards,

    Klaus!

  5. Evan Berkowitz

    Hi Klaus,

    My comment was only responding to @emjotde's request for numpy-like reshape, which lets you take a matrix (or vector) and reinterpret it as any matrix (or vector) with the same number of elements (but with a different shape). eg. a 6-element vector can be seen as a 2*3 matrix (as in my example above).

    Honestly, I couldn't believe it when the code above worked---it seems kind of magical. I hope this surprise functionality is protected by some unit tests :D

  6. Klaus Iglberger

    Summary

    With the introduction of element selections, row selections, and column selections (see issue #48) it is now possible to ...

    • ... subselect vector elements based on a vector of indices, including repetitions and permutations;
    • ... subselect rows/columns based on a vector of indices, including repetitions and permutations.

    The features have been implemented, tested, optimized, and documented as required. They are immediately available via cloning the Blaze repository and will be officially released in Blaze 3.3.

    Examples

    Repeating a Matrix Row-Wise

    blaze::DynamicMatrix<int> A
       { { 1, 0, 2, 0 }
       , { 0, 3, 0, 4 }
       , { 5, 0, 6, 0 } };
    
    DynamicMatrix<int> B;
    
    B = rows<0,1,2,0,1,2>( A );
    
        ( 1, 0, 2, 0 )
        ( 0, 3, 0, 4 )
    B = ( 5, 0, 6, 0 )
        ( 1, 0, 2, 0 )
        ( 0, 3, 0, 4 )
        ( 5, 0, 6, 0 )
    

    Repeating a Matrix Column-Wise

    blaze::DynamicMatrix<int> A
       { { 1, 0, 2, 0 }
       , { 0, 3, 0, 4 }
       , { 5, 0, 6, 0 } };
    
    DynamicMatrix<int> B;
    
    B = columns<0,1,2,3,0,1,2,3>( A );
    
        ( 1, 0, 2, 0, 1, 0, 2, 0 )
    B = ( 0, 3, 0, 4, 0, 3, 0, 4 )
        ( 5, 0, 6, 0, 5, 0, 6, 0 )
    

    Repeating Each Row of a Matrix

    blaze::DynamicMatrix<int> A
       { { 1, 0, 2, 0 }
       , { 0, 3, 0, 4 }
       , { 5, 0, 6, 0 } };
    
    DynamicMatrix<int> B;
    
    B = rows<0,0,1,1,2,2>( A );
    
        ( 1, 0, 2, 0 )
        ( 1, 0, 2, 0 )
    B = ( 0, 3, 0, 4 )
        ( 0, 3, 0, 4 )
        ( 5, 0, 6, 0 )
        ( 5, 0, 6, 0 )
    

    Reversing the Columns of a Matrix

    blaze::DynamicMatrix<int> A
       { { 1, 0, 2, 0 }
       , { 0, 3, 0, 4 }
       , { 5, 0, 6, 0 } };
    
    DynamicMatrix<int> B;
    
    B = columns<3,2,1,0>( A );
    
        ( 0, 2, 0, 1 )
    B = ( 4, 0, 3, 0 )
        ( 0, 6, 0, 5 )
    
  7. Ecolss Logan

    Hi @Klaus Iglberger , sorry about bringing this thread up again.

    I’m having the same issue, I wonder what is the latest solution of reshape on DynamicMatrix now?

    For example, I want to flatten a (10,5) matrix into a (1, 50) matrix before feeding it to an NN layer. So a typical reshape would be helpful here.

  8. Klaus Iglberger

    Hi @Ecolss Logan !

    Blaze doesn’t provide a reshape() operation for two reasons:

    1. Blaze uses padding to speed up performance. Therefore you cannot expect that a 10x5 matrix consists of exactly 50 contiguous elements. Since padding can make a big difference in terms of performance (e.g. factor 4-5 for the matrix/matrix multiplication of 3x3 matrices), we deem the performance win more important than the reshape() operation.
    2. It is semantically not clear whether the flattening should result in a matrix or a vector. You would expect a 1x50 matrix, but other users expect a vector with 50 elements. We cannot express this runtime decision with types, since Blaze distinguishes between vectors and matrices. We would need a generalized tensor implementation for that (see issue #53).

    The best approach to approximate this operation is explicitly deactivate padding (see Padding) and to build on CustomVector and CustomMatrix:

    using namespace blaze;
    
    StaticMatrix<int,10,5,rowMajor,unaligned,unpadded> A{};
    // ... Initialization of A
    CustomVector<int,unaligned,unpadded,columnVector> b( A.data(), 50 );
    

    I hope this helps,

    Best regards,

    Klaus!

  9. Log in to comment