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

打印 上一主题 下一主题

主题 810|帖子 810|积分 2430

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

正如我们所看到的,PyTorch张量是torch.Tensor​ PyTorch类的实例。张量的抽象概念与PyTorch张量之间的区别在于,PyTorch张量为我们提供了一个可以在代码中操纵的详细实现。
在上一篇文章中,我们看到了如何利用数据(如Python列表、序列和NumPy ndarrays)在PyTorch中创建张量。给定一个numpy.ndarray​,我们发现有四种方法可以创建一个torch.Tensor​对象。
这里是一个快速回顾:
  1. > data = np.array([1,2,3])
  2. > type(data)
  3. numpy.ndarray
  4. > o1 = torch.Tensor(data)
  5. > o2 = torch.tensor(data)
  6. > o3 = torch.as_tensor(data)
  7. > o4 = torch.from_numpy(data)
复制代码
  1. > print(o1)
  2. tensor([1., 2., 3.])
复制代码
  1. > print(o2)
  2. tensor([1, 2, 3], dtype=torch.int32)
复制代码
  1. > print(o3)
  2. tensor([1, 2, 3], dtype=torch.int32)
复制代码
  1. > print(o4)
  2. 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​。让我们看看:
  1. > print(o1.dtype)
  2. torch.float32
  3. > print(o2.dtype)
  4. torch.int32
  5. > print(o3.dtype)
  6. torch.int32
  7. > print(o4.dtype)
  8. torch.int32
复制代码
这里的区别在于,torch.Tensor()​构造函数在构建张量时利用默认的dtype​。我们可以利用torch.get_default_dtype()​方法验证默认的dtype​:
  1. > torch.get_default_dtype()
  2. torch.float32
复制代码
通过代码验证,我们可以如许做:
  1. > o1.dtype == torch.get_default_dtype()
  2. True
复制代码
其他调用根据传入的数据选择dtype​。这被称为类型推断。dtype​是根据传入的数据推断的。请留意,也可以通过将dtype​作为参数指定,为这些调用显式设置dtype​:
  1. > torch.tensor(data, dtype=torch.float32)
  2. > torch.as_tensor(data, dtype=torch.float32)
复制代码
利用torch.Tensor()​,我们无法向构造函数传递dtype​。这是torch.Tensor()​构造函数缺乏设置选项的一个例子。这是选择torch.tensor()​工厂函数来创建张量的另一个缘故原由。
让我们看看这些更换创建方法之间的末了一个隐藏区别。
为了性能共享内存:复制与共享

第三个区别隐藏在幕后。为了揭示这个区别,我们需要在用ndarray​创建我们的张量后,改变原始输入数据在numpy.ndarray​中。
让我们如许做,看看我们得到什么:
  1. > print('old:', data)old: [1 2 3]> data[0] = 0> print('new:', data)new: [0 2 3]> print(o1)
  2. tensor([1., 2., 3.])
  3. > print(o2)
  4. tensor([1, 2, 3], dtype=torch.int32)
  5. > 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​,我们可以如许做:
  1. > print(o3.numpy())
  2. [0 2 3]
  3. > print(o4.numpy())
  4. [0 2 3]
复制代码
这给出了:
  1. > print(type(o3.numpy()))
  2. <class 'numpy.ndarray'>
  3. > print(type(o4.numpy()))
  4. <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​创建选项有了更好的理解。我们学习了工厂函数,并且看到了内存_共享与复制_如何影响性能和程序行为。下次见!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

光之使者

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表