Let’s start!

data=np.array([1.,2.,3.,4.])
t1=torch.Tensor(data)
t2=torch.tensor(data)
t3=torch.as_tensor(data)
t4=torch.from_numpy(data)
print(t1)
print(t2)
print(t3)
print(t4)
结果:
tensor([1., 2., 3., 4.])
tensor([1., 2., 3., 4.], dtype=torch.float64)
tensor([1., 2., 3., 4.], dtype=torch.float64)
tensor([1., 2., 3., 4.], dtype=torch.float64)

**

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

**

torch.Tensor() Vs torch.tensor()

带有大写 T 的第一个选项是 torch.Tensor 类的构造函数,而第二个选项是我们所说的工厂函数,用于构造torch.Tensor 对象并将其返回给调用者。你可以把torch.tensor()函数看作是一个工厂,它在给定一些参数输入后构建张量。工厂函数是一种创建对象的软件设计模式。好的。这就是大写的T和小写的t之间的区别,但是这两者之间哪种方式更好?答案是,使用任何一种都是可以的。然而,工厂函数torch.tensor()有更好的文档和更多的配置选项,所以它目前获得了胜利。

2 默认dtype与推断dtype

好吧,在我们把torch.Tensor()构造函数从我们的列表中剔除之前,让我们来看看我们在打印的张量输出中观察到的差异。

差异在于每个张量的dtype。让我们看一下。

print(t1.dtype)
torch.float32

print(t2.dtype)
torch.float64

print(t3.dtype)
torch.float64

print(t4.dtype)
torch.float64

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

torch.get_default_dtype()
结果:
torch.float32
为了用代码验证,我们可以这样做。

t1.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()工厂函数来创建我们的张量的原因之一。

3 为了性能而共享内存,复制与共享

data[0]=100
print(t1)
print(t2)
print(t3)
print(t4)
结果:
tensor([1., 2., 3., 4.])
tensor([1., 2., 3., 4.], dtype=torch.float64)
tensor([100.,   2.,   3.,   4.], dtype=torch.float64)
tensor([100.,   2.,   3.,   4.], dtype=torch.float64)

出现这种现象的原因是torch.Tensor()和torch.tensor()复制它们的输入数据,然而torch.as_tensor()和torch.from_numpy()在内存中与原始输入对象共享其输入数据。也就是原数据改变时,由于共享数据,这两个函数的输入数据也随之改变。

共享数据比复制数据更节省内存,因为数据没有写到内存中的两个位置,而是只有一个位置。

如果我们有一个torch.Tensor,同时,我们想把它转化为一个numpy.ndarray,或者把一个numpy.ndarray转化为一个torch.Tensor,我们可以这样做:

type(t3)
结果:
torch.Tensor

t4=t3.numpy()
type(t4)
numpy.ndarray

t5=torch.tensor(t4)
type(t5)
torch.Tensor

torch.as_tensor() 和torch.from_numpy() 都可以和它们的输入共享内存,那么我们应该用哪一个?

torch.from_numpy()函数只接受numpy.ndarrays,而torch.as_tensor()函数接受各种类似数组的对象,包括其他PyTorch的张量。由于这个原因,torch.as_tensor()是内存共享游戏中的获胜选择。

4 在pytorch中创建tensor的最好选择

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()的性能改善会更大。然而,如果只有一次加载操作,从性能角度看应该不会有太大影响。

我的公众号:Math and Code

欢迎关注!

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐