网站色彩,装修设计公司logo,通信工程师,长春网站制作费用为深度学习创建PyTorch张量 - 最佳选项
正如我们所看到的#xff0c;PyTorch张量是torch.Tensor PyTorch类的实例。张量的抽象概念与PyTorch张量之间的区别在于#xff0c;PyTorch张量为我们提供了一个可以在代码中操作的具体实现。
在上一篇文章中#xff0c;我们看到了…为深度学习创建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], dtypetorch.int32) print(o3)
tensor([1, 2, 3], dtypetorch.int32) print(o4)
tensor([1, 2, 3], dtypetorch.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, dtypetorch.float32)torch.as_tensor(data, dtypetorch.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], dtypetorch.int32) print(o3)
tensor([0, 2, 3], dtypetorch.int32) print(o4)
tensor([0, 2, 3], dtypetorch.int32)
注意最初我们有data[0]1还要注意我们只改变了原始numpy.ndarray中的数据。注意我们没有明确地对我们的张量o1o2o3o4进行任何更改。
然而在设置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()应该在调整我们的代码以提高性能时使用。
关于内存共享在可能的地方工作的一些注意事项
由于numpy.ndarray对象分配在CPU上当使用GPU时as_tensor()函数必须将数据从CPU复制到GPU。as_tensor()的内存共享不适用于内置的Python数据结构如列表。as_tensor()调用需要开发人员了解共享功能。这是必要的这样我们就不会在不知不觉中对底层数据进行了不想要的更改而没有意识到更改会影响到多个对象。如果numpy.ndarray对象和张量对象之间有很多来回操作as_tensor()的性能提升将更大。然而如果只是一个单一的加载操作从性能角度来看不应该有太大影响。
总结
此时我们应该对PyTorch的tensor创建选项有了更好的理解。我们学习了工厂函数并且看到了内存_共享与复制_如何影响性能和程序行为。下次见