我如何汇总2D张量,而其中一些必须平均并且其中一些保留?

发布于 2025-02-10 15:16:50 字数 699 浏览 2 评论 0原文

我想汇总2D张量。规则是,如果变量“ IDX”中的数字相同,则为相应的张量。以下是问题。

idx = torch.tensor([[0, 1, 2], [1, 2, 3], [3, 4, 5]])
x = torch.tensor([[10, 10, 10], [11, 11, 11], [12, 12, 12],
                  [13, 13, 13], [14, 14, 14], [15, 15, 15],
                  [16, 16, 16], [17, 17, 17], [18, 18, 18]])

例如,由于重复索引(1,2),因此将汇总相应的张量

[[11, 11, 11], [12, 12, 12]] and [[13, 13, 13], [14, 14, 14]]

我们会得到张量

[[12, 12, 12], [13, 13, 13]]

,因此,如果没有重复的数字, ,请保持张量。因此,对于这个问题,所需的答案是

torch.tensor([[10, 10, 10], [12, 12, 12], [13, 13, 13], [15.5, 15.5, 15.5], [17, 17, 17], [18, 18, 18]])

我该怎么做?预先感谢您的帮助。

I want to aggregate a 2D tensor. The rule is, if the number in the the variable "idx" is the same, average the corresponding tensor. Below is the problem.

idx = torch.tensor([[0, 1, 2], [1, 2, 3], [3, 4, 5]])
x = torch.tensor([[10, 10, 10], [11, 11, 11], [12, 12, 12],
                  [13, 13, 13], [14, 14, 14], [15, 15, 15],
                  [16, 16, 16], [17, 17, 17], [18, 18, 18]])

For example, since index (1, 2) is repeated, the corresponding tensors

[[11, 11, 11], [12, 12, 12]] and [[13, 13, 13], [14, 14, 14]]

will be aggregated and thus we get the tensor

[[12, 12, 12], [13, 13, 13]]

if there is no repeated number, keep the tensor. So for this problem the desired answer is

torch.tensor([[10, 10, 10], [12, 12, 12], [13, 13, 13], [15.5, 15.5, 15.5], [17, 17, 17], [18, 18, 18]])

How do I do this? Thank you in advance for helping.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

红焚 2025-02-17 15:16:50

看起来您可以使用散点功能。

2D中的最小设置

让我们探索您的问题的简化版本,从而没有三胞胎,而是有单个值。在这种情况下,我们将拥有:

>>> x = torch.tensor([[10, 11, 12],
                      [13, 14, 15],
                      [16, 17, 18]])

>>> idx = torch.tensor([[0, 1, 2],
                        [1, 2, 3],
                        [3, 4, 5]])

我们应该查看中间结果,而不是所需的结果本身。最终,我们知道结果将沿其一个维度之一求和或平均。我们可以首先定义其形状,它的行应该与xidx以及与IDX中的唯一索引一样多。在此特定示例中,我们正在寻找的中间结果将具有(3,6)的形状。由于#[| 0,5 |] = 6

tensor([[10, 11, 12,  0,  0,  0],
        [ 0, 13, 14, 15,  0,  0],
        [ 0,  0,  0, 16, 17, 18]])

我们可以看到,一旦沿着第一个维度减少,我们就会得到:

tensor([10., 12., 13., 15.5, 17., 18.])

这是1D中此最小示例的所需结果。

要进行这样的操作,我们可以从 TORCH.TENSOR.SCATTER 。当应用于二维张量并设置dim = 1时,调用此行:

out.scatter_(dim=1, index=idx, src=x) 

将对out>:

out[i][idx[i][j]] = x[i][j]

如果我们尝试使用输入张量,我们会得到:

>>> o = torch.zeros(len(idx), idx.max()+1, dtype=int)
>>> o.scatter_(1, idx, x)
tensor([[10, 11, 12,  0,  0,  0],
        [ 0, 13, 14, 15,  0,  0],
        [ 0,  0,  0, 16, 17, 18]])

然后,我们只需要使用 /code>

>>> o.sum(dim=0) / o.count_nonzero(dim=0)
tensor([10.0000, 12.0000, 13.0000, 15.5000, 17.0000, 18.0000])

原始问题

,但是,在您的原始用例中,每个元素有三个值:

>>> x = torch.tensor([[10, 10, 10], [11, 11, 11], [12, 12, 12],
                      [13, 13, 13], [14, 14, 14], [15, 15, 15],
                      [16, 16, 16], [17, 17, 17], [18, 18, 18]])

>>> idx = torch.tensor([[0, 1, 2], 
                        [1, 2, 3], 
                        [3, 4, 5]])

因此,我们首先必须在xidx上进行以下操作:

  1. reshape x与Shape 的3D张量

     >>> X_ = X.View(*IDX.Shape,X.Size(-1))
    张量([[[[10,10,10],
             [11,11,11],
             [12,12,12]],
    
            [[13,13,13],
             [14、14、14],
             [15,15,15]],
    
            [[16,16,16],
             [17、17、17],
             [18,18,18]]])
     


  2. 重塑>使其具有与x _的形状相同的形状:

     >>> idx_ = idx.unsqueeze(-1).expand_as(x_)
    张量([[[[0,0,0],
             [1,1,1],
             [2,2,2]],
    
            [[1,1,1],
             [2,2,2],
             [3,3,3]],
    
            [[3,3,3],
             [4,4,4],
             [5,5,5]]]))
     

然后,我们只需要使用torch.scatter.scatter.scatter应用相同的方法,但是 (dim = 1,index = idx_,src = x _)

out[i][idx[i][j][k]][k] = x[i][j][k]

out.scatter_

>>> o = torch.zeros(len(idx), idx.max()+1, idx.size(-1), dtype=int)
>>> o.scatter_(1, idx_, x_)
tensor([[[10, 10, 10],
         [11, 11, 11],
         [12, 12, 12],
         [ 0,  0,  0],
         [ 0,  0,  0],
         [ 0,  0,  0]],

        [[ 0,  0,  0],
         [13, 13, 13],
         [14, 14, 14],
         [15, 15, 15],
         [ 0,  0,  0],
         [ 0,  0,  0]],

        [[ 0,  0,  0],
         [ 0,  0,  0],
         [ 0,  0,  0],
         [16, 16, 16],
         [17, 17, 17],
         [18, 18, 18]]])

在3D中, ie dim = 1,与以前相同:

>>> o.sum(dim=0) / o.count_nonzero(dim=0)
tensor([[10.0000, 10.0000, 10.0000],
        [12.0000, 12.0000, 12.0000],
        [13.0000, 13.0000, 13.0000],
        [15.5000, 15.5000, 15.5000],
        [17.0000, 17.0000, 17.0000],
        [18.0000, 18.0000, 18.0000]])

It looks like you could use a scatter function.

Minimal setup in 2D

Let us explore a reduced version of your problem whereby instead of having triplets, we have single values. In that scenario, we would have:

>>> x = torch.tensor([[10, 11, 12],
                      [13, 14, 15],
                      [16, 17, 18]])

>>> idx = torch.tensor([[0, 1, 2],
                        [1, 2, 3],
                        [3, 4, 5]])

We should look at an intermediate result rather than the desired result itself. Ultimately, we know that the result will be summed or averaged along one of its dimensions. We can first define its shape, it should have as many rows as x and idx and as many columns as there are unique indices in idx. In this particular example, the intermediate result we're looking for will have a shape of (3, 6). Since #[|0,5|]=6:

tensor([[10, 11, 12,  0,  0,  0],
        [ 0, 13, 14, 15,  0,  0],
        [ 0,  0,  0, 16, 17, 18]])

We can see that once reduced along the first dimension, we get:

tensor([10., 12., 13., 15.5, 17., 18.])

Which is the desired result for this minimal example in 1D.

To do such operation we can benefit from torch.Tensor.scatter. When applied on two-dimensional tensors, and setting dim=1, calling this line:

out.scatter_(dim=1, index=idx, src=x) 

will have the following effect on out:

out[i][idx[i][j]] = x[i][j]

If we try on our input tensors, we get:

>>> o = torch.zeros(len(idx), idx.max()+1, dtype=int)
>>> o.scatter_(1, idx, x)
tensor([[10, 11, 12,  0,  0,  0],
        [ 0, 13, 14, 15,  0,  0],
        [ 0,  0,  0, 16, 17, 18]])

Then we only have to average over nonzero values using torch.sum and torch.count_nonzero:

>>> o.sum(dim=0) / o.count_nonzero(dim=0)
tensor([10.0000, 12.0000, 13.0000, 15.5000, 17.0000, 18.0000])

Original problem

However, in your original use case, you have three values per element:

>>> x = torch.tensor([[10, 10, 10], [11, 11, 11], [12, 12, 12],
                      [13, 13, 13], [14, 14, 14], [15, 15, 15],
                      [16, 16, 16], [17, 17, 17], [18, 18, 18]])

>>> idx = torch.tensor([[0, 1, 2], 
                        [1, 2, 3], 
                        [3, 4, 5]])

Therefore, we first have to do the following on x and idx:

  1. reshape x to a 3D tensor with shape (*idx.shape, x.size(-1)):

    >>> x_ = x.view(*idx.shape, x.size(-1))
    tensor([[[10, 10, 10],
             [11, 11, 11],
             [12, 12, 12]],
    
            [[13, 13, 13],
             [14, 14, 14],
             [15, 15, 15]],
    
            [[16, 16, 16],
             [17, 17, 17],
             [18, 18, 18]]])
    
  2. Unsqueeze and expand idx such that it has the same shape as x_:

    >>> idx_ = idx.unsqueeze(-1).expand_as(x_)
    tensor([[[0, 0, 0],
             [1, 1, 1],
             [2, 2, 2]],
    
            [[1, 1, 1],
             [2, 2, 2],
             [3, 3, 3]],
    
            [[3, 3, 3],
             [4, 4, 4],
             [5, 5, 5]]])
    

Then we simply have to apply the same approach with torch.scatter, but in 3D, i.e. out.scatter_(dim=1, index=idx_, src=x_) which will result in:

out[i][idx[i][j][k]][k] = x[i][j][k]

For our inputs:

>>> o = torch.zeros(len(idx), idx.max()+1, idx.size(-1), dtype=int)
>>> o.scatter_(1, idx_, x_)
tensor([[[10, 10, 10],
         [11, 11, 11],
         [12, 12, 12],
         [ 0,  0,  0],
         [ 0,  0,  0],
         [ 0,  0,  0]],

        [[ 0,  0,  0],
         [13, 13, 13],
         [14, 14, 14],
         [15, 15, 15],
         [ 0,  0,  0],
         [ 0,  0,  0]],

        [[ 0,  0,  0],
         [ 0,  0,  0],
         [ 0,  0,  0],
         [16, 16, 16],
         [17, 17, 17],
         [18, 18, 18]]])

To finish it off, reduce on dim=1, same way as before:

>>> o.sum(dim=0) / o.count_nonzero(dim=0)
tensor([[10.0000, 10.0000, 10.0000],
        [12.0000, 12.0000, 12.0000],
        [13.0000, 13.0000, 13.0000],
        [15.5000, 15.5000, 15.5000],
        [17.0000, 17.0000, 17.0000],
        [18.0000, 18.0000, 18.0000]])
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文