【问题标题】:Stacking copies of an array/ a torch tensor efficiently?有效地堆叠阵列/火炬张量的副本?
【发布时间】:2017-06-16 15:39:56
【问题描述】:

我是 Python/Pytorch 用户。首先,在 numpy 中,假设我有一个大小为 LxL 的数组 M,我想要以下 数组:A=(M,...,M) 的大小,比如 NxLxL,有没有比这样做更优雅/内存效率更高的方法:

A=np.array([M]*N) ?

与火炬张量相同的问题! 原因,现在,如果 M 是变量(torch.tensor),我必须这样做:

A=torch.autograd.Variable(torch.tensor(np.array([M]*N))) 

太丑了!

【问题讨论】:

  • numpytilerepeat。使用它们可能需要M[None,...]
  • 你可以只广播它。 (我不确定 PyTorch 是否有广播;最近是 implemented,但我不确定它是否可用。)
  • 还有expand,有点像手动广播。

标签: arrays numpy pytorch tensor


【解决方案1】:

请注意,您需要决定是要为扩展数组分配新内存,还是只需要原始数组的现有内存的新视图。

在 PyTorch 中,这种区别产生了 expand()repeat() 两种方法。前者仅在现有张量上创建一个新视图,其中通过将步幅设置为 0 将大小为 1 的维度扩展到更大的大小。大小为 1 的任何维度都可以扩展到任意值而无需分配新内存。相反,后者复制原始数据并分配新内存。

在 PyTorch 中,您可以使用 expand()repeat() 来满足您的目的:

import torch

L = 10
N = 20
A = torch.randn(L,L)
A.expand(N, L, L) # specifies new size
A.repeat(N,1,1) # specifies number of copies

在 Numpy 中,有多种方法可以更优雅、更高效地实现上述操作。对于您的特定目的,我会推荐np.tile() 而不是np.repeat(),因为np.repeat() 旨在对数组的特定元素进行操作,而np.tile() 旨在对整个数组进行操作。因此,

import numpy as np

L = 10
N = 20
A = np.random.rand(L,L)
np.tile(A,(N, 1, 1))

【讨论】:

  • np.tile 使用np.repeat,每个维度使用一次。它不使用repeat's 应用不同数量的每个元素的能力,但除此之外它只是repeat 的扩展。它的代码是可读的python。
【解决方案2】:

如果你不介意创造新的记忆:

  • 在 numpy 中,您可以使用np.repeat()np.tile()。考虑到效率,您应该选择为您的目的组织内存的一个,而不是事后重新安排:
    • np.repeat([1, 2], 2) == [1, 1, 2, 2]
    • np.tile([1, 2], 2) == [1, 2, 1, 2]
  • 在pytorch中,你可以使用tensor.repeat()注意:这匹配np.tile,而不是np.repeat

如果你不想创建新内存:

  • 在numpy中,你可以使用np.broadcast_to()。这会创建内存的只读视图。
  • 在pytorch中,你可以使用tensor.expand()。这会创建一个可编辑的内存视图,因此像 += 这样的操作会产生奇怪的效果。

【讨论】:

  • np.tile 不同于 np.repeat
  • @NicolasGervais 非常好。它们有何不同?我想更新答案。
  • 如果你平铺abc,它会给出abcabcabc,如果你重复它会给出aaabbbccc
【解决方案3】:

numpy repeat 中更快:

np.repeat(M[None,...], N,0)

我扩展M 的维度,然后沿着新维度重复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-20
    • 1970-01-01
    • 2017-02-23
    • 1970-01-01
    • 2020-11-24
    • 2015-07-29
    • 2015-09-16
    相关资源
    最近更新 更多