【问题标题】:How can I slice a PyTorch tensor with another tensor?如何用另一个张量切片 PyTorch 张量?
【发布时间】:2020-08-01 01:21:12
【问题描述】:

我有:

inp =  torch.randn(4, 1040, 161)

我还有另一个名为 indices 的张量,其值:

tensor([[124, 583, 158, 529],
        [172, 631, 206, 577]], device='cuda:0')

我想要相当于:

inp0 = inp[:,124:172,:]
inp1 = inp[:,583:631,:]
inp2 = inp[:,158:206,:]
inp3 = inp[:,529:577,:]

除了全部加在一起,.size 为[4, 48, 161]。我怎样才能做到这一点?

目前,我的解决方案是 for 循环:

            left_indices = torch.empty(inp.size(0), self.side_length, inp.size(2))
            for batch_index in range(len(inp)):
                print(left_indices_start[batch_index].item())
                left_indices[batch_index] = inp[batch_index, left_indices_start[batch_index].item():left_indices_end[batch_index].item()]

【问题讨论】:

  • @Shanoon 你是想把所有的inp_is 都堆起来还是分开?
  • 我想把它们叠起来
  • 我的回答将它们全部叠加起来。最终形状为(4, 192, 161)

标签: python numpy pytorch tensor


【解决方案1】:

给你(编辑:在执行以下操作之前,您可能需要使用tensor=tensor.cpu() 将张量复制到 cpu):

index = tensor([[124, 583, 158, 529],
    [172, 631, 206, 577]], device='cuda:0')
#create a concatenated list of ranges of indices you desire to slice
indexer = np.r_[tuple([np.s_[i:j] for (i,j) in zip(index[0,:],index[1,:])])]
#slice using numpy indexing
sliced_inp = inp[:, indexer, :]

这是它的工作原理:

np.s_[i:j] 创建一个从 start=i 到 end=j 的索引切片对象(只是一个范围)。

np.r_[i:j, k:m] 在切片(i,j)(k,m) 中创建一个列表所有索引(您可以将更多切片传递给np.r_ 以一次将它们连接在一起。这是仅连接两个切片的示例。)

因此,indexer 通过连接切片列表(每个切片是一个索引范围)来创建所有索引列表。

更新:如果您需要删除间隔重叠和排序间隔:

indexer = np.unique(indexer)

如果您想删除区间重叠但不排序并保持原始顺序(以及第一次出现的重叠)

uni = np.unique(indexer, return_index=True)[1]
indexer = [indexer[index] for index in sorted(uni)]

【讨论】:

  • 你能解释一下r_s_是做什么的吗?
  • @Shamoon 我稍后会添加更多解释。
  • @Shamoon 我刚刚检查过,您不需要转换为 numpy。这些操作也适用于张量。我刚刚编辑了张量的答案。如果它适合您,请接受关闭它。谢谢。
  • 我收到TypeError: can't convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.
  • @Shamoon 我没有CUDA,所以我使用了cpu。我猜你可以使用index=index.cpu()inp=inp.cpu()indexinp 复制到cpu。我不确定如何在 GPU 上进行 numpy 操作。
【解决方案2】:
inp =  torch.randn(4, 1040, 161)   
indices = torch.tensor([[124, 583, 158, 529],
            [172, 631, 206, 577]])
k = zip(indices[0], indices[1])
for i,j in k:
    print(inp[:,i:j,:])

您可以像这样实现它... zip 函数有助于将您的索引张量转换为您可以通过 for 循环直接使用的元组列表

希望对你有所帮助....

【讨论】:

  • 我能以某种方式避免循环吗?
  • 您希望只避免 for 循环...如果使用 while 循环可以为您解决问题吗?
  • @Shamoon 我以为您想将它们全部堆叠在一起。如果您想循环并且不关心快速堆叠它们,则不需要压缩,只需循环索引即可。比如:for i in range(indices.shape[1]): print(inp[:,indices[0,i]:indices[1,i],:])
猜你喜欢
  • 2019-12-12
  • 1970-01-01
  • 2017-12-01
  • 1970-01-01
  • 2019-04-25
  • 2020-10-17
  • 1970-01-01
  • 2021-06-18
  • 2018-11-22
相关资源
最近更新 更多