torch.tensor和torch.Tensor之间有什么区别?

61
torch.tensortorch.Tensor之间有什么区别?为什么提供这两个非常相似且容易混淆的替代方式的原因是什么?
5个回答

56
在PyTorch中,torch.Tensor是主要的张量类。因此,所有张量都只是torch.Tensor的实例。torch.Tensor()将返回一个没有data的空张量。相比之下,torch.tensor是一个返回张量的函数。在文档中说:
torch.tensor(data, dtype=None, device=None, requires_grad=False) → Tensor

使用data构造一个张量。

tensor_without_data = torch.Tensor()

但是另一方面:

tensor_without_data = torch.tensor()

将导致错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-ebc3ceaa76d2> in <module>()
----> 1 torch.tensor()

TypeError: tensor() missing 1 required positional arguments: "data"
但一般情况下,选择 `torch.tensor` 而非 `torch.Tensor` 没有理由。此外,`torch.Tensor` 缺少文档字符串。

创建一个没有 data 的张量的行为,类似于使用 torch.Tensor() 可以通过以下方式实现:

torch.tensor(())

输出:

tensor([])

13
除了上面的答案,我注意到:
  • torch.Tensor() 创建一个使用 torch.get_default_dtype() 定义的默认数据类型的tensor。
  • torch.tensor() 将从数据推断出数据类型。
例如:
>>> torch.Tensor([1, 2, 3]).dtype
torch.float32

>>> torch.tensor([1, 2, 3]).dtype
torch.int64

9
根据pytorch discussion上的讨论,torch.Tensor构造函数被重载为与torch.tensortorch.empty执行相同的操作。认为这种重载会使代码混乱,因此将torch.Tensor分成了torch.tensortorch.empty
因此,是的,在某种程度上,当您传入数据时,torch.tensor的工作方式类似于torch.Tensor。不,两者都不应比另一个更有效。只是torch.emptytorch.tensor具有比torch.Tensor构造函数更好的API。

5

2
torch.Tensor”是创建参数时(例如在nn.Linearnn._ConvNd中)常用的方法。
为什么呢?因为它非常快,甚至比torch.empty()更快。
import torch
torch.set_default_dtype(torch.float32) # default

%timeit torch.empty(1000,1000)
%timeit torch.Tensor(1000,1000)
%timeit torch.ones(1000,1000)
%timeit torch.tensor([[1]*1000]*1000)

输出:
68.4 µs ± 789 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
67.9 µs ± 349 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
1.26 ms ± 8.61 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
36.1 ms ± 610 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

`torch.Tensor()`和`torch.empty()`非常相似,它们都返回一个填充有未初始化数据的张量。
虽然在技术上是可能的,但为什么我们不在`__init__`中初始化参数呢?
下面是在实践中使用`torch.Tensor`在`nn.Linear`内创建`weight`参数的示例:
self.weight = nn.Parameter(torch.Tensor(out_features, in_features))

我们的设计不会初始化它。还有另一个 `reset_parameters()` 方法,因为在训练过程中可能需要再次“重置”参数,所以我们在 `__init__()` 方法的末尾调用 `reset_paremeters()`。
也许在未来,`torch.empty()` 将取代 `torch.Tensor()`,因为它们的效果相同。
此外,`reset_parameters()` 还有一个很好的选项,您可以创建自己的版本并在需要时更改原始初始化过程。

1
这些性能比较似乎存在一些缺陷。前两项测量值之间的差距不足一个标准差,而最后一个测量存在缺陷,因为它还测量了 [[1]*1000]*1000 的调用,这很可能是缓慢且占据运行时间的主导因素。 - Turakar
@Turakar 不,它不会主导运行时。 py -m timeit "a = [[1]*1000]*1000" 50000 次循环,5 次中的最佳结果:每次循环 5.11 微秒并且将其作为设置的一部分, py -m timeit -s "import torch; a = [[1]*1000]*1000" "torch.tensor(a)" 10 次循环,5 次中的最佳结果:每次循环 31.7 毫秒 - pu239
有趣,看来我错了。 - Turakar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接