【问题标题】:Creating one hot vector from indices given as a tensor从给定为张量的索引创建一个热向量
【发布时间】:2017-11-11 16:57:25
【问题描述】:

我有一个大小为 4 x 6 的张量,其中 4 是批量大小,6 是序列长度。序列向量的每个元素都是某个索引(0 到 n)。我想创建一个4 x 6 x n 张量,其中第 3 维的向量将是索引的一个热编码,这意味着我想将 1 放入指定的索引中,其余的值将为零。

例如,我有以下张量:

[[5, 3, 2, 11, 15, 15],
[1, 4, 6, 7, 3, 3],
[2, 4, 7, 8, 9, 10],
[11, 12, 15, 2, 5, 7]]

在这里,所有值都在 (0 到 n) 之间,其中 n = 15。所以,我想将张量转换为 4 X 6 X 16 张量,其中第三维将代表一个热编码向量。

如何使用 PyTorch 功能做到这一点?现在,我正在使用循环执行此操作,但我想避免循环!

【问题讨论】:

    标签: pytorch


    【解决方案1】:

    我找到的最简单的方法。其中 x 是数字列表,class_count 是您拥有的课程数量。

    def one_hot(x, class_count):
        return torch.eye(class_count)[x,:]
    

    像这样使用它:

    x = [0,2,5,4]
    class_count = 8
    one_hot(x,class_count)
    tensor([[1., 0., 0., 0., 0., 0., 0., 0.],
            [0., 0., 1., 0., 0., 0., 0., 0.],
            [0., 0., 0., 0., 0., 1., 0., 0.],
            [0., 0., 0., 0., 1., 0., 0., 0.]])
    
    
    

    【讨论】:

      【解决方案2】:

      新答案 从 PyTorch 1.1 开始,one_hot 中有一个 torch.nn.functional 函数。给定任何索引张量 indices 和最大索引 n,您可以按如下方式创建 one_hot 版本:

      n = 5
      indices = torch.randint(0,n, size=(4,7))
      one_hot = torch.nn.functional.one_hot(indices, n) # size=(4,7,n)
      

      很老的答案

      目前,根据我的经验,在 PyTorch 中切片和索引可能有点痛苦。我假设您不想将张量转换为 numpy 数组。目前我能想到的最优雅的方法是使用稀疏张量,然后转换为密集张量。这将按如下方式工作:

      from torch.sparse import FloatTensor as STensor
      
      batch_size = 4
      seq_length = 6
      feat_dim = 16
      
      batch_idx = torch.LongTensor([i for i in range(batch_size) for s in range(seq_length)])
      seq_idx = torch.LongTensor(list(range(seq_length))*batch_size)
      feat_idx = torch.LongTensor([[5, 3, 2, 11, 15, 15], [1, 4, 6, 7, 3, 3],                            
                                   [2, 4, 7, 8, 9, 10], [11, 12, 15, 2, 5, 7]]).view(24,)
      
      my_stack = torch.stack([batch_idx, seq_idx, feat_idx]) # indices must be nDim * nEntries
      my_final_array = STensor(my_stack, torch.ones(batch_size * seq_length), 
                               torch.Size([batch_size, seq_length, feat_dim])).to_dense()    
      
      print(my_final_array)
      

      注意:PyTorch 目前正在进行一些工作,这将在接下来的两三周内添加 numpy 风格的广播和其他功能以及其他功能。所以有可能,在不久的将来会有更好的解决方案。

      希望这对您有所帮助。

      【讨论】:

        【解决方案3】:

        这可以在PyTorch 中使用任何Tensor 对象的就地scatter_ 方法来完成。

        labels = torch.LongTensor([[[2,1,0]], [[0,1,0]]]).permute(0,2,1) # Let this be your current batch
        batch_size, k, _ = labels.size()
        labels_one_hot = torch.FloatTensor(batch_size, k, num_classes).zero_()
        labels_one_hot.scatter_(2, labels, 1)
        

        对于num_classes=3(索引应该不同于[0,3)),这会给你

        (0 ,.,.) = 
          0  0  1
          0  1  0
          1  0  0
        (1 ,.,.) = 
          1  0  0
          0  1  0
          1  0  0
        [torch.FloatTensor of size 2x3x3]
        

        注意labels 应该是torch.LongTensor

        PyTorch 文档参考:torch.Tensor.scatter_

        【讨论】:

        • labels 而不是 X?
        • @ramin 它应该是标签而不是 X。我提交了一个编辑。这也是一种更快的方法。
        猜你喜欢
        • 2019-10-24
        • 2017-10-12
        • 1970-01-01
        • 1970-01-01
        • 2021-04-04
        • 1970-01-01
        • 2023-03-10
        • 1970-01-01
        • 2020-07-15
        相关资源
        最近更新 更多