Pytorch: How to vectorize torch.unique() for multiple dimensions

Viewed 70

I have a 4D tensor (M), and I need to find the unique vectors within the 3rd dimension without using for loops. However:

value ,inverse, counts = M.unique(dim=2, return_inverse=True, return_counts=True )

returns a 2D counts output tensor which is not what I'm expecting.

Take the following [2,2,7,3] shape tensor M

M = torch.Tensor([[[[2.4,5.5,1], [3.44,5.43,1], [2.4,5.5,1], [3.44,8.43,1], [3.44,5.43,9], [3.44,5.43,1], [3.44,5.43,1]],
                [[2.4,5.5,1], [3.44,5.43,1], [2.4,5.5,1], [3.44,8.43,1], [3.44,5.43,9], [3.44,5.43,1], [3.44,5.43,1]]],
                [[[2.4,5.5,1], [3.44,5.43,1], [2.4,5.5,1], [3.44,8.43,1], [3.44,5.43,9], [3.44,5.43,1], [3.44,5.43,1]],
                [[2.4,5.5,1], [10.44,5.43,1], [9,5.5,1], [9.44,5.49,1], [3.44,5.43,9], [3.44,5.43,2], [9,5.43,1]]]])

when I run:

value ,inverse, counts = M.unique(dim=2, return_inverse=True, return_counts=True )

I get:

value tensor([[[[ 2.4000,  5.5000,  1.0000],
    [ 2.4000,  5.5000,  1.0000],
    [ 3.4400,  5.4300,  1.0000],
    [ 3.4400,  5.4300,  1.0000],
    [ 3.4400,  5.4300,  1.0000],
    [ 3.4400,  5.4300,  9.0000],
    [ 3.4400,  8.4300,  1.0000]],

   [[ 2.4000,  5.5000,  1.0000],
    [ 2.4000,  5.5000,  1.0000],
    [ 3.4400,  5.4300,  1.0000],
    [ 3.4400,  5.4300,  1.0000],
    [ 3.4400, 88.4300,  1.0000],
    [ 3.4400,  5.4300,  9.0000],
    [ 3.4400,  8.4300,  1.0000]]],


  [[[ 2.4000,  5.5000,  1.0000],
    [ 2.4000,  5.5000,  1.0000],
    [ 3.4400,  5.4300,  1.0000],
    [ 3.4400,  5.4300,  1.0000],
    [ 3.4400,  5.4300,  1.0000],
    [ 3.4400,  5.4300,  9.0000],
    [ 3.4400,  8.4300,  1.0000]],

   [[ 2.4000,  5.5000,  1.0000],
    [ 9.0000,  5.5000,  1.0000],
    [ 3.4400,  5.4300,  2.0000],
    [ 9.0000,  5.4300,  1.0000],
    [10.4400,  5.4300,  1.0000],
    [ 3.4400,  5.4300,  9.0000],
    [ 9.4400,  5.4900,  1.0000]]]])

Instead of:

value tensor([[[[ 2.4000,  5.5000,  1.0000],
    [ 3.4400,  5.4300,  1.0000],
    [ 3.4400,  5.4300,  9.0000],
    [ 3.4400,  8.4300,  1.0000]],

   [[ 2.4000,  5.5000,  1.0000],
    [ 3.4400,  5.4300,  1.0000],
    [ 3.4400, 88.4300,  1.0000],
    [ 3.4400,  5.4300,  9.0000],
    [ 3.4400,  8.4300,  1.0000]]],


  [[[ 2.4000,  5.5000,  1.0000],  
    [ 3.4400,  5.4300,  1.0000],
    [ 3.4400,  5.4300,  9.0000],
    [ 3.4400,  8.4300,  1.0000]],

   [[ 2.4000,  5.5000,  1.0000],
    [ 9.0000,  5.5000,  1.0000],
    [ 3.4400,  5.4300,  2.0000],
    [ 9.0000,  5.4300,  1.0000],
    [10.4400,  5.4300,  1.0000],
    [ 3.4400,  5.4300,  9.0000],
    [ 9.4400,  5.4900,  1.0000]]]])

And I get counts of:

counts tensor([1, 1, 1, 1, 1, 1, 1])

opposed to:

counts [[2,3,1,1],[2,2,1,1,1],[2,3,1,1],[1,1,1,1,1,1,1]]

I understand that this is not possible as the 3rd dimension elements are not consistent in length, but surely the unique function could just pad the output with a vector of zeros?

Is there a way to do what I'd like to do with or without the unique function that returns something like:

value tensor([[[[ 2.4000,  5.5000,  1.0000], 
      [ 3.4400,  5.4300,  1.0000], 
      [ 3.4400,  5.4300,  9.0000],
      [ 3.4400,  8.4300,  1.0000]],
      [ 0,  0,  0],
      [ 0,  0,  0],
      [ 0,  0,  0],

     [[ 2.4000,  5.5000,  1.0000], 
      [ 3.4400,  5.4300,  1.0000], 
      [ 3.4400, 88.4300,  1.0000],
      [ 3.4400,  5.4300,  9.0000],
      [ 3.4400,  8.4300,  1.0000],
      [ 0,  0,  0],
      [ 0,  0,  0]]],


    [[[ 2.4000,  5.5000,  1.0000], 
      [ 3.4400,  5.4300,  1.0000], 
      [ 3.4400,  5.4300,  9.0000],
      [ 3.4400,  8.4300,  1.0000],
      [ 0,  0,  0],
      [ 0,  0,  0],
      [ 0,  0,  0]],

     [[ 2.4000,  5.5000,  1.0000],
      [ 9.0000,  5.5000,  1.0000],
      [ 3.4400,  5.4300,  2.0000],
      [ 9.0000,  5.4300,  1.0000],
      [10.4400,  5.4300,  1.0000],
      [ 3.4400,  5.4300,  9.0000],
      [ 9.4400,  5.4900,  1.0000]]]])

And:

counts torch([[2,3,1,1,0,0,0],[2,2,1,1,1,0,0],[2,3,1,1,0,0,0],[1,1,1,1,1,1,1]])
0 Answers
Related