PyTorch内存模型:“ torch.from_numpy()”和“ torch.Tensor()”
deep-learning
numpy
python
pytorch
6
0

我试图深入了解PyTorch Tensor内存模型的工作方式。

# input numpy array
In [91]: arr = np.arange(10, dtype=float32).reshape(5, 2)

# input tensors in two different ways
In [92]: t1, t2 = torch.Tensor(arr), torch.from_numpy(arr)

# their types
In [93]: type(arr), type(t1), type(t2)
Out[93]: (numpy.ndarray, torch.FloatTensor, torch.FloatTensor)

# ndarray 
In [94]: arr
Out[94]: 
array([[ 0.,  1.],
       [ 2.,  3.],
       [ 4.,  5.],
       [ 6.,  7.],
       [ 8.,  9.]], dtype=float32)

我知道PyTorch张量共享 NumPy ndarrays 的内存缓冲区 。因此,改变一个将反映在另一个中。因此,这里我在Tensor t2切片和更新一些值

In [98]: t2[:, 1] = 23.0

正如预期的那样,由于它们共享相同的内存缓冲区,因此在t2arr对其进行了更新。

In [99]: t2
Out[99]: 

  0  23
  2  23
  4  23
  6  23
  8  23
[torch.FloatTensor of size 5x2]


In [101]: arr
Out[101]: 
array([[  0.,  23.],
       [  2.,  23.],
       [  4.,  23.],
       [  6.,  23.],
       [  8.,  23.]], dtype=float32)

但是, t1也被更新 。请记住, t1是使用torch.Tensor()构造的,而t2是使用torch.from_numpy()构造的

In [100]: t1
Out[100]: 

  0  23
  2  23
  4  23
  6  23
  8  23
[torch.FloatTensor of size 5x2]

因此,无论我们使用torch.from_numpy()还是torch.Tensor()从ndarray构造张量, 所有这些张量和ndarray共享相同的内存缓冲区。

基于这种理解,我的问题是,为什么仅当torch.Tensor()可以完成这项工作时,为什么存在专用函数torch.from_numpy()

我查看了PyTorch文档,但未提及任何内容?有什么想法/建议吗?

参考资料:
Stack Overflow
收藏
评论
共 3 个回答
高赞 时间 活跃

from_numpy()自动继承输入数组dtype 。在另一方面, torch.Tensor是一个别名torch.FloatTensor

因此,如果将int64数组传递给torch.Tensor ,则输出张量为浮点张量,它们将不会共享存储。 torch.from_numpy为您提供了torch.LongTensor预期的效果。

a = np.arange(10)
ft = torch.Tensor(a)  # same as torch.FloatTensor
it = torch.from_numpy(a)

a.dtype  # == dtype('int64')
ft.dtype  # == torch.float32
it.dtype  # == torch.int64
收藏
评论

这来自_torch_docs.py ;也有对“ 为什么 ”一个可能的讨论在这里

def from_numpy(ndarray): # real signature unknown; restored from __doc__
    """
    from_numpy(ndarray) -> Tensor

    Creates a :class:`Tensor` from a :class:`numpy.ndarray`.

    The returned tensor and `ndarray` share the same memory. 
    Modifications to the tensor will be reflected in the `ndarray` 
    and vice versa. The returned tensor is not resizable.

    Example::

        >>> a = numpy.array([1, 2, 3])
        >>> t = torch.from_numpy(a)
        >>> t
        torch.LongTensor([1, 2, 3])
        >>> t[0] = -1
        >>> a
        array([-1,  2,  3])
    """
    pass

来自numpy文档:

不同的ndarrays可以共享相同的数据,因此在一个ndarray中所做的更改可能在另一个中可见。也就是说,一个ndarray可以是另一个ndarray的“视图”,并且它所引用的数据由“基本” ndarray

Pytorch docs

如果给定numpy.ndarraytorch.Tensortorch.Storage ,则返回共享相同数据的新张量。如果给出了Python序列,则从序列的副本中创建一个新的张量。

收藏
评论

在Pytorch中构建张量的推荐方法是使用以下两个工厂函数: torch.tensortorch.as_tensor

torch.tensor 始终复制数据。例如, torch.tensor(x)等效于x.clone().detach()

torch.as_tensor 始终尝试避免复制数据。如果原始数据是一个numpy数组,则as_tensor避免复制数据的情况之一。

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号