0
\$\begingroup\$

Here's the problem.

Return a copy of x, where the minimum value along each row has been set to 0.

For example, if x is:

x = torch.tensor([[
        [10, 20, 30],
        [ 2,  5,  1]
      ]])

Then y = zero_row_min(x) should be:

torch.tensor([
    [0, 20, 30],
    [2,  5,  0]
  ])

Your implementation should use reduction and indexing operations; you should not use any explicit loops. The input tensor should not be modified.

Inputs:

  • x: Tensor of shape (M, N)

Returns:

  • y: Tensor of shape (M, N) that is a copy of x, except the minimum value along each row is replaced with 0.

It has been hinted at that clone and argmin should be used.

I'm having trouble understanding how to do this without a loop and my current code below (although it gets the problem right) is crude. I'm looking for a better way to solve this problem.

  x0 = torch.tensor([[10, 20, 30], [2, 5, 1]])
  x1 = torch.tensor([[2, 5, 10, -1], [1, 3, 2, 4], [5, 6, 2, 10]])

  func(x0)
  func(x1)
  
  def func(x):

    y = None

    # g = x.argmin(dim=1)

    g = x.min(dim=1)[1]

    if x.shape[0] == 2:
      x[0,:][g[0]] = 0
      x[1,:][g[1]] = 0
    elif x.shape[0] == 3:
      x[0,:][g[0]] = 0
      x[1,:][g[1]] = 0
      x[2,:][g[2]] = 0

    y = x
  
    return y
\$\endgroup\$
4
  • \$\begingroup\$ The idea should be copy_of_array[argmin_indices] = 0. \$\endgroup\$
    – Andrew
    Sep 1 at 16:21
  • \$\begingroup\$ Can you provide expected shape for each of your variables? e.g. (1000, 2, 12) or whatever. \$\endgroup\$
    – Reinderien
    Sep 1 at 17:33
  • 1
    \$\begingroup\$ @Reinderien Sure, x0 = torch.tensor([[10, 20, 30], [2, 5, 1]]) and x1 = torch.tensor([[2, 5, 10, -1], [1, 3, 2, 4], [5, 6, 2, 10]]). I've added them to the original post for clarification as well. \$\endgroup\$
    – Ryan
    Sep 1 at 17:44
  • \$\begingroup\$ @Andrew I believe that's similar to the way I went about solving it. It works, but I have to manually iterate over each row to mutate the min() value. \$\endgroup\$
    – Ryan
    Sep 1 at 17:55
0
\$\begingroup\$

Not much of a code review, but this should work:

def zero_min(x):
    y = x.clone()
    y[torch.arange(x.shape[0]), torch.argmin(x, dim=1)] = 0
    return y

In each row, if the minimum is not unique, then only the occurrence with the smallest index will be zeroed out.

To zero out all the occurrences, you could do something like the following:

def zero_em_all_min(x):
    y = x.clone()
    y[x == x.min(dim=1, keepdims=True).values] = 0
    return y
\$\endgroup\$
2
  • \$\begingroup\$ Thanks, didn't think to use torch.arange to iterate through the rows. I'll ask on regular SE in the future. \$\endgroup\$
    – Ryan
    Sep 1 at 18:24
  • \$\begingroup\$ @Ryan I'm happy it could be answered, but perhaps that is indeed the better platform for a similar question! \$\endgroup\$
    – Andrew
    Sep 1 at 18:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.