当前位置:   article > 正文

Pytorch基础 - 0. Tensor数据类型与存储结构

Pytorch基础 - 0. Tensor数据类型与存储结构

目录

1. Tensor数据类型

2. Tensor存储结构


在讲PyTorch这个系列之前,先讲一下pytorch中最常见的tensor张量,包括数据类型,创建类型,类型转换,以及存储方式和数据结构。

1. 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等

  1. x = torch.tensor([1, 2])
  2. print(x.dtype) # torch.int64
  3. print(x.type()) # torch.LongTensor

(3) pytorch默认的整数是int64, 默认的浮点数是float32。

  1. x = torch.tensor([1, 2, 3])
  2. print(x.dtype) # torch.int64
  3. y = torch.tensor([1., 2., 3.])
  4. print(y.dtype) # torch.float32

(3) 使用两种方式创建不同类型的张量

【方式1】直接在后面用dtype定义tensor类型

【方式2】参考上面数据类型表格中的最右侧Tensor type来新建不同类型的张量

  1. # 方式1:直接在后面用dtype定义tensor类型
  2. x = torch.tensor([1, 2, 3], dtype=torch.int8)
  3. print(x.dtype) # torch.int8
  4. # 方式2: 参考上面数据类型表格中的最右侧Tensor type来新建不同类型的张量
  5. y = torch.CharTensor([1, 2, 3])
  6. 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定义不同类型

  1. x = torch.Tensor([1, 2])
  2. print(x.type()) # torch.FloatTensor
  3. y = torch.tensor([1, 2], dtype=torch.long)
  4. print(y.type()) # torch.LongTensor

(4) 使用两种方式进行不同类型的转换

【方式1】使用 float(), short(), int(), long()等函数

【方式2】使用x.type的方式

  1. # 方式1:使用 float(), short(), int(), long()等函数
  2. x = torch.tensor([1, 2, 3])
  3. x = x.short()
  4. print(x.dtype) # torch.int16
  5. # 方式2: 使用x.type的方式
  6. y = torch.tensor([1, 2, 3])
  7. y = y.type(torch.int64)
  8. print(y.dtype) # torch.int64

2. Tensor存储结构

(1) Tensor的数据结构如下图所示,主要包含下面两个部分。

  • 头信息区 Tensor:保存张量的形状size,步长stride,数据类型int, char等信息
  • 存储区 Storage:保存真正的数据,Storage是在data之上的接口
  • 头信息区的占用内存较小,Storage为主要的占用内存

 (2) 注意:不同的tensor的头信息可能不同,但是却可能共享相同的storage,如下示例

通过reshape或者view的操作,只改变了头部信息,如storage,storage内容和内存地址没有改变

  1. x = torch.tensor([1, 2, 3, 4, 5, 6])
  2. y = x.reshape(2, 3)
  3. print(x.storage(), y.storage()) # 1 2 3 4 5 6 1 2 3 4 5 6
  4. print(x.storage().data_ptr(), y.storage().data_ptr()) # 2330435641664 2330435641664
  5. print(x.stride(), y.stride()) # (1,) (3, 1)

所以此时当x改变,y也跟着改变,因为x和y共享相同的storage

  1. x = torch.tensor([1, 2, 3, 4, 5, 6])
  2. y = x.reshape(2, 3)
  3. x[0] = 11
  4. print(y) # tensor([[11, 2, 3], [4, 5, 6]])

(3) 知识补充: id() 和 data_ptr()的区别和误区

在tensor中,常用x.storage().data_ptr() 来判断两个tensor是否共享storage(),这是torch提供的一个来自于C++底层的方法,该方法可以返回storage()里的首元素的内存地址。如下:

  1. x = torch.tensor([1, 2, 3, 4, 5, 6])
  2. y = x.reshape(2, 3)
  3. print(x.storage().data_ptr(), y.storage().data_ptr()) # 1672574819456 1672574819456

id() 默认不会返回对象的内存地址,而是返回一个唯一的对象标识符,并且在该对象的生命周期内是不变的。虽然,CPython实现以某种方式使用内存地址。但这不应该作为一般情况下的参考。因此用id()来对storage()进行判断时,会出现下面情况 - id不相等

  1. x = torch.tensor([1, 2, 3, 4, 5, 6])
  2. y = x.reshape(2, 3)
  3. print(id(x.storage())) # 2271657541704
  4. print(id(y.storage())) # 2271657679944

但是受到上面的启发,感觉他们的内存是共享的,那肯定是相等的啊。为什么不相等呢?很简单,是因为x.storage()和y.storage()新建了两个不同的对象,也就是指针,只不过这俩指针指向的是相同的一块内存,但是这俩对象的id是不等的。

那除此之外,有时候他们的id也会相等的时候,如下:

  1. x = torch.tensor([1, 2, 3, 4, 5, 6])
  2. y = x.reshape(2, 3)
  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操作,持续更新中。 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/272495
推荐阅读
相关标签
  

闽ICP备14008679号