首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么本例中的这个tensor.unfold方法要添加一个维度?

为什么本例中的这个tensor.unfold方法要添加一个维度?
EN

Stack Overflow用户
提问于 2020-06-11 22:40:33
回答 1查看 896关注 0票数 0

我正在熟悉来自https://pytorch.org/docs/stable/tensors.html#torch.Tensor.unfold的method展开方法。

我看了他们的例子

代码语言:javascript
复制
>>> x = torch.arange(1., 8)
>>> x
tensor([ 1.,  2.,  3.,  4.,  5.,  6.,  7.])
>>> x.unfold(0, 2, 1)
tensor([[ 1.,  2.],
        [ 2.,  3.],
        [ 3.,  4.],
        [ 4.,  5.],
        [ 5.,  6.],
        [ 6.,  7.]])

我在上面了解到,当我们在维数0中展开时,我们一次取2大小的块,步幅为1,因此,结果是排列不同的块,即[1., 2.][2., 3.]等等。因为我们在最后有6块,这些块将被放在一起,最后的形状是(6,2)

但是,我还有另一个示例,如下所示。

代码语言:javascript
复制
In [115]: s = torch.arange(20).view(1,10,2)

In [116]: s
Out[116]:
tensor([[[ 0,  1],
         [ 2,  3],
         [ 4,  5],
         [ 6,  7],
         [ 8,  9],
         [10, 11],
         [12, 13],
         [14, 15],
         [16, 17],
         [18, 19]]])

In [117]: s.unfold(0,1,1)
Out[117]:
tensor([[[[ 0],
          [ 1]],

         [[ 2],
          [ 3]],

         [[ 4],
          [ 5]],

         [[ 6],
          [ 7]],

         [[ 8],
          [ 9]],

         [[10],
          [11]],

         [[12],
          [13]],

         [[14],
          [15]],

         [[16],
          [17]],

         [[18],
          [19]]]])

In [119]: s.unfold(0,1,1).shape
Out[119]: torch.Size([1, 10, 2, 1])

所以你看,我原来的张量是形状的(1,10,2),我要求用参数s.unfold(0, 1, 1)展开运算。

根据上一个例子中的原始理解,我假设这意味着在维度0中,我们一次取1块,步幅为1。因此,当我们进入维度0时,我们看到只有一个块大小的(10,2)。因此,输出应该只接受这个块,可能它应该添加一个维度来包装这个块,并给我一个大小为(1, 10, 2)的输出。

但是,它给了我一个大小为(1, 10, 2, 1)的输出。为什么它在最后有一个额外的维度?有人能直截了当地解释一下吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-12 03:16:16

这些文件指出:

在返回的张量中附加了尺寸为size的附加维数。

其中size是您指定的块的大小(第二个参数)。根据定义,它总是添加一个额外的维度,这使得无论您选择什么大小,它都是一致的。仅仅因为一个维度的大小为1,并不意味着它应该被自动省略。

关于这背后的直觉,让我们考虑一下,与其返回一个张量,在最后一个维度中表示块,我们创建了一个所有块的列表。为了简单起见,我们将它限制在第一个维度上,步骤为1。

代码语言:javascript
复制
import torch
from typing import List


def list_chunks(tensor: torch.Tensor, size: int) -> List[torch.Tensor]:
    chunks = []
    for i in range(tensor.size(0) - size + 1):
        chunks.append(tensor[i : i + size])
    return chunks


x = torch.arange(1.0, 8)
s = torch.arange(20).view(1, 10, 2)

# As expected, a list with 6 elements, as there are 6 chunks.
list_chunks(x, 2)
# => [tensor([1., 2.]),
#     tensor([2., 3.]),
#     tensor([3., 4.]),
#     tensor([4., 5.]),
#     tensor([5., 6.]),
#     tensor([6., 7.])]

# The list has only a single element, as there is only a single chunk.
# But it's still a list.
list_chunks(s, 1)
# => [tensor([[[ 0,  1],
#              [ 2,  3],
#              [ 4,  5],
#              [ 6,  7],
#              [ 8,  9],
#              [10, 11],
#              [12, 13],
#              [14, 15],
#              [16, 17],
#              [18, 19]]])]

我特意添加了类型注释,以便更清楚地了解我们对函数的期望。如果只有一个块,它将是一个包含一个元素的列表,因为它总是一个块列表。

您期待的是一种不同的行为,即当存在单个块时,您需要的是单个块,而不是列表。这将对实现进行如下更改。

代码语言:javascript
复制
from typing import List, Union


def list_chunks(tensor: torch.Tensor, size: int) -> Union[List[torch.Tensor], torch.Tensor]:
    chunks = []
    for i in range(tensor.size(0) - size + 1):
        chunks.append(tensor[i : i + size])
    # If it's a single chunk, return just the chunk itself
    if len(chunks) == 1:
        return chunks[0]
    else:
        return chunks

有了这个改变,任何使用这个函数的人现在都需要考虑两种情况。如果您不区分列表和单个块(张量),您将得到意想不到的结果,例如,在块上循环将循环在张量的第一个维度上。

编程上直观的方法是总是返回块列表,torch.unfold也会这样做,但是它不是块列表,而是一个张量,其中最后一个维度可以被看作是块的列表。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62334729

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档