赞
踩
目录
在讲PyTorch这个系列之前,先讲一下pytorch中最常见的tensor张量,包括数据类型,创建类型,类型转换,以及存储方式和数据结构。
(1) 一共包括9种数据类型,3大类
torch.LongTensor常用在深度学习中的标签值 ,比如分类任务中的类别标签0,1,2等torch.FloatTensor常用做深度学习中可学习参数或者输入数据的类型
(2) pytorch中的 type() 和 dtype
tensor.type():返回的是数据所属的Tensor类型,如 torch.LongTensor等
tensor.dtype:返回的是tensor数据自身的类型,如 torch.int8, torch.long等
- x = torch.tensor([1, 2])
- print(x.dtype) # torch.int64
- print(x.type()) # torch.LongTensor
(3) pytorch默认的整数是int64, 默认的浮点数是float32。
- x = torch.tensor([1, 2, 3])
- print(x.dtype) # torch.int64
- y = torch.tensor([1., 2., 3.])
- print(y.dtype) # torch.float32
(3) 使用两种方式创建不同类型的张量
【方式1】直接在后面用dtype定义tensor类型
【方式2】参考上面数据类型表格中的最右侧Tensor type来新建不同类型的张量
- # 方式1:直接在后面用dtype定义tensor类型
- x = torch.tensor([1, 2, 3], dtype=torch.int8)
- print(x.dtype) # torch.int8
-
- # 方式2: 参考上面数据类型表格中的最右侧Tensor type来新建不同类型的张量
- y = torch.CharTensor([1, 2, 3])
- print(y.dtype) # torch.int8
注意:torch.tensor() 和 torch.Tensor()新建张量的区别
torch.Tensor()本质是torch.FloatTensor(),新建的tensor是float类型的
toch.tensor(data, dtype=None, device=None, requires_grad=False) 可以根据dtype定义不同类型
- x = torch.Tensor([1, 2])
- print(x.type()) # torch.FloatTensor
- y = torch.tensor([1, 2], dtype=torch.long)
- print(y.type()) # torch.LongTensor
(4) 使用两种方式进行不同类型的转换
【方式1】使用 float(), short(), int(), long()等函数
【方式2】使用x.type的方式
- # 方式1:使用 float(), short(), int(), long()等函数
- x = torch.tensor([1, 2, 3])
- x = x.short()
- print(x.dtype) # torch.int16
-
- # 方式2: 使用x.type的方式
- y = torch.tensor([1, 2, 3])
- y = y.type(torch.int64)
- print(y.dtype) # torch.int64
(1) Tensor的数据结构如下图所示,主要包含下面两个部分。
(2) 注意:不同的tensor的头信息可能不同,但是却可能共享相同的storage,如下示例
通过reshape或者view的操作,只改变了头部信息,如storage,storage内容和内存地址没有改变
- x = torch.tensor([1, 2, 3, 4, 5, 6])
- y = x.reshape(2, 3)
- print(x.storage(), y.storage()) # 1 2 3 4 5 6 1 2 3 4 5 6
- print(x.storage().data_ptr(), y.storage().data_ptr()) # 2330435641664 2330435641664
- print(x.stride(), y.stride()) # (1,) (3, 1)
所以此时当x改变,y也跟着改变,因为x和y共享相同的storage
- x = torch.tensor([1, 2, 3, 4, 5, 6])
- y = x.reshape(2, 3)
- x[0] = 11
- print(y) # tensor([[11, 2, 3], [4, 5, 6]])
(3) 知识补充: id() 和 data_ptr()的区别和误区
在tensor中,常用x.storage().data_ptr() 来判断两个tensor是否共享storage(),这是torch提供的一个来自于C++底层的方法,该方法可以返回storage()里的首元素的内存地址。如下:
- x = torch.tensor([1, 2, 3, 4, 5, 6])
- y = x.reshape(2, 3)
- print(x.storage().data_ptr(), y.storage().data_ptr()) # 1672574819456 1672574819456
id() 默认不会返回对象的内存地址,而是返回一个唯一的对象标识符,并且在该对象的生命周期内是不变的。虽然,CPython实现以某种方式使用内存地址。但这不应该作为一般情况下的参考。因此用id()来对storage()进行判断时,会出现下面情况 - id不相等
- x = torch.tensor([1, 2, 3, 4, 5, 6])
- y = x.reshape(2, 3)
- print(id(x.storage())) # 2271657541704
- print(id(y.storage())) # 2271657679944
但是受到上面的启发,感觉他们的内存是共享的,那肯定是相等的啊。为什么不相等呢?很简单,是因为x.storage()和y.storage()新建了两个不同的对象,也就是指针,只不过这俩指针指向的是相同的一块内存,但是这俩对象的id是不等的。
那除此之外,有时候他们的id也会相等的时候,如下:
- x = torch.tensor([1, 2, 3, 4, 5, 6])
- y = x.reshape(2, 3)
- print(id(x.storage()), id(y.storage())) # 2137680796872 2137680796872
为什么相等呢?是因为内存的释放速度问题,第一个x新建完释放了内存,然后该内存直接给y.storage()了,所以会相等。
综上:判断两个tensor是否共享storage(),使用storage().data_ptr()才行!不可使用id
注:该博客中部分图文参考链接:【小白学PyTorch】9 tensor数据结构与存储结构 - 知乎,PyTorch 笔记(11)— Tensor内部存储结构(头信息区 Tensor,存储区 Storage)
如看其他Docker内容,可看本博客 Pytorch操作,持续更新中。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。