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)
**
**
torch.Tensor() Vs torch.tensor()
带有大写 T 的第一个选项是 torch.Tensor 类的构造函数,而第二个选项是我们所说的工厂函数,用于构造torch.Tensor 对象并将其返回给调用者。你可以把torch.tensor()函数看作是一个工厂,它在给定一些参数输入后构建张量。工厂函数是一种创建对象的软件设计模式。好的。这就是大写的T和小写的t之间的区别,但是这两者之间哪种方式更好?答案是,使用任何一种都是可以的。然而,工厂函数torch.tensor()有更好的文档和更多的配置选项,所以它目前获得了胜利。
好吧,在我们把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()工厂函数来创建我们的张量的原因之一。
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()是内存共享游戏中的获胜选择。
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
欢迎关注!