为深度学习创建PyTorch张量 - 最佳选项

为深度学习创建PyTorch张量 - 最佳选项

正如我们所看到的,PyTorch张量是torch.Tensor​ PyTorch类的实例。张量的抽象概念与PyTorch张量之间的区别在于,PyTorch张量为我们提供了一个可以在代码中操作的具体实现。

在上一篇文章中,我们看到了如何使用数据(如Python列表、序列和NumPy ndarrays)在PyTorch中创建张量。给定一个numpy.ndarray​,我们发现有四种方法可以创建一个torch.Tensor​对象。

这里是一个快速回顾:

复制代码
> data = np.array([1,2,3])
> type(data)
numpy.ndarray

> o1 = torch.Tensor(data)
> o2 = torch.tensor(data)
> o3 = torch.as_tensor(data)
> o4 = torch.from_numpy(data)

> print(o1)
tensor([1., 2., 3.])

> print(o2)
tensor([1, 2, 3], dtype=torch.int32)

> print(o3)
tensor([1, 2, 3], dtype=torch.int32)

> print(o4)
tensor([1, 2, 3], dtype=torch.int32)

我们在这篇文章中的任务是探索这些选项之间的区别,并为我们创建张量的需求提出最佳选项。

不同系统上的Numpy dtype​行为

根据你的机器和操作系统,你的dtype​可能与这里和视频中显示的不同。

Numpy根据它是在32位还是64位系统上运行来设置其默认dtype​,并且在Windows系统上的行为也有所不同。

这个链接提供了关于在Windows系统上看到的差异的更多信息。受影响的方法是:tensor​、as_tensor​和from_numpy​。

感谢hivemind的David找出了这一点!

张量创建操作:有什么区别?

让我们开始并找出这些差异都是关于什么的。

大写/小写:torch.Tensor()​与torch.tensor()​

注意第一个选项torch.Tensor()​有一个大写的T​,而第二个选项torch.tensor()​有一个小写的t​。这个区别是怎么回事?

第一个选项带有大写的T​是torch.Tensor​类的构造函数,第二个选项是我们所说的_工厂函数_,它构建torch.Tensor​对象并返回给调用者。

​

​

你可以将torch.tensor()​函数视为一个工厂,它根据一些参数输入构建张量。工厂函数是一种创建对象的软件设计模式。如果你想了解更多,可以查看这里。

好的,这就是大写T​和小写t​之间的区别,但在这两种方式中,哪一种更好?答案是使用任何一个都可以。然而,工厂函数torch.tensor()​有更好的文档和更多的配置选项,所以它目前是胜出的选择。

默认dtype​与推断的dtype​

好吧,在我们从使用列表中删除torch.Tensor()​构造函数之前,让我们回顾一下我们在打印的张量输出中观察到的区别。

区别在于每个张量的dtype​。让我们看看:

复制代码
> print(o1.dtype)
torch.float32

> print(o2.dtype)
torch.int32

> print(o3.dtype)
torch.int32

> print(o4.dtype)
torch.int32

这里的区别在于,torch.Tensor()​构造函数在构建张量时使用默认的dtype​。我们可以使用torch.get_default_dtype()​方法验证默认的dtype​:

复制代码
> torch.get_default_dtype()
torch.float32

通过代码验证,我们可以这样做:

复制代码
> o1.dtype == torch.get_default_dtype()
True

其他调用根据传入的数据选择dtype​。这被称为类型推断。dtype​是根据传入的数据推断的。请注意,也可以通过将dtype​作为参数指定,为这些调用显式设置dtype​:

复制代码
> torch.tensor(data, dtype=torch.float32)
> torch.as_tensor(data, dtype=torch.float32)

使用torch.Tensor()​,我们无法向构造函数传递dtype​。这是torch.Tensor()​构造函数缺乏配置选项的一个例子。这是选择torch.tensor()​工厂函数来创建张量的另一个原因。

让我们看看这些替代创建方法之间的最后一个隐藏区别。

为了性能共享内存:复制与共享

第三个区别隐藏在幕后。为了揭示这个区别,我们需要在用ndarray​创建我们的张量后,改变原始输入数据在numpy.ndarray​中。

让我们这样做,看看我们得到什么:

复制代码
> print('old:', data)
old: [1 2 3]

> data[0] = 0

> print('new:', data)
new: [0 2 3]

> print(o1)
tensor([1., 2., 3.])

> print(o2)
tensor([1, 2, 3], dtype=torch.int32)

> print(o3)
tensor([0, 2, 3], dtype=torch.int32)

> print(o4)
tensor([0, 2, 3], dtype=torch.int32)

注意,最初我们有data[0]=1​,还要注意我们只改变了原始numpy.ndarray​中的数据。注意我们没有明确地对我们的张量(o1​,o2​,o3​,o4​)进行任何更改。

然而,在设置data[0]=0​之后,我们可以看到我们的一些张量发生了变化。前两个o1​和o2​仍然在索引0​处有原始值1​,而后两个o3​和o4​在索引0​处有新值0​。

这是因为torch.Tensor()​和torch.tensor()​在输入数据时_复制_它们,而torch.as_tensor()​和torch.from_numpy()​在内存中与原始输入对象_共享_它们的输入数据。

共享数据 复制数据
torch.as_tensor() torch.tensor()
torch.from_numpy() torch.Tensor()

这种共享只是意味着内存中的实际数据存在于一个地方。因此,对底层数据发生的任何更改都将反映在两个对象中,即torch.Tensor​和numpy.ndarray​。

共享数据比复制数据更有效,使用的内存更少,因为数据不会写入内存中的两个位置。

如果我们有一个torch.Tensor​,我们想将其转换为numpy.ndarray​,我们可以这样做:

复制代码
> print(o3.numpy())
[0 2 3]

> print(o4.numpy())
[0 2 3]

这给出了:

复制代码
> print(type(o3.numpy()))
<class 'numpy.ndarray'>

> print(type(o4.numpy()))
<class 'numpy.ndarray'>

这确立了torch.as_tensor()​和torch.from_numpy()​都与它们的输入数据共享内存。然而,我们应该使用哪一个,它们之间有什么区别?

​torch.from_numpy()​函数只接受numpy.ndarray​,而torch.as_tensor()​函数接受各种数组式对象,包括其他PyTorch张量。因此,torch.as_tensor()​是在内存共享游戏中的胜出选择。

那为什么要这么多种函数呢?

在PyTorch中创建张量的最佳选项

鉴于所有这些细节,这两个是最佳选项:

  • torch.tensor()
  • torch.as_tensor()

​torch.tensor()​调用是主要的选择,而torch.as_tensor()​应该在调整我们的代码以提高性能时使用。

​

​

关于内存共享(在可能的地方工作)的一些注意事项:

  1. 由于numpy.ndarray对象分配在CPU上,当使用GPU时,as_tensor()函数必须将数据从CPU复制到GPU。
  2. as_tensor()的内存共享不适用于内置的Python数据结构,如列表。
  3. as_tensor()调用需要开发人员了解共享功能。这是必要的,这样我们就不会在不知不觉中对底层数据进行了不想要的更改,而没有意识到更改会影响到多个对象。
  4. 如果numpy.ndarray对象和张量对象之间有很多来回操作,as_tensor()的性能提升将更大。然而,如果只是一个单一的加载操作,从性能角度来看不应该有太大影响。
总结

此时,我们应该对PyTorch的tensor​创建选项有了更好的理解。我们学习了工厂函数,并且看到了内存_共享与复制_如何影响性能和程序行为。下次见!

相关推荐
for_ever_love__5 小时前
PyTorch 张量与 autograd——自动求导怎么工作
pytorch·python·深度学习·自动求导
Είναι η κοπέλα1 天前
显存计算与模型选择:你的显卡能跑多大的模型
人工智能·pytorch·python·开源·conda
海天一色y2 天前
模型部署的「通用语」:ONNX 转换
pytorch·onnx
Thomas.Sir2 天前
第26课:工业零部件外观缺陷检测系统:从学术Demo到产线工程的重构实战
pytorch·ai
Zguigo3 天前
【CUDA6】CUDA Stream 是什么,为什么 CUDA 是异步执行,如何正确测量 GPU 时间以及多个任务如何重叠执行
人工智能·pytorch·深度学习
论文复现现场3 天前
RTX 3090 24GB 适合科研吗?单卡论文复现、PyTorch 显存检查与 OOM 排错
人工智能·pytorch·python·深度学习·cuda·rtx3090
论文复现现场4 天前
AutoDL、算家云与公有云 GPU 怎么选?环境复现、计费与断点恢复对比
pytorch·深度学习·云计算·gpu
盘古开天16664 天前
PPO算法代码实战(三):PyTorch从零实现PPO求解CartPole
人工智能·pytorch·算法
Είναι η κοπέλα4 天前
PyTorch 安装与验证
人工智能·pytorch·python
盼小辉丶5 天前
PyTorch强化学习实战(27)——进化策略在强化学习中的应用
人工智能·pytorch·深度学习·强化学习