分享

张量及张量的数据类型

 人老颠东 2023-05-01 发布于安徽

什么是张量

标量(scalar):一个标量就是一个单独的数。访问标量不需要索引,所以标量是 0D(Dimensionality 维度) 的。

向量( vector):一个向量是一列数。我们习惯用列向量。访问向量中的标量需要 1 个索引,所以向量是 1D 数组。

矩阵( matrix):矩阵是一个 2D 数组,因为访问其中的标量要 2 个索引。

张量( tensor):超过 2 个维度的数组,所以也称张量为多维数组(multidimensional array)。

图片

PyTorch 中的张量和 NumPy 多维数组很相似,但是比 NumPy 多维数组强大多了:

    • 张量可以移到 GPU 中加速计算。

    • 张量支持在多个设备上进行分布式计算。

    • 张量自动跟踪计算图,方便自动求导。

其实标量可以看成 0D 张量,向量就是 1D 张量,矩阵就是 2D 张量。

PyTorch 中的张量

In [1]: import torch # 导入 PyTorch 包的标准方式
In [5]: s = torch.tensor(2.) # 将标量转成张量
In [6]: s, s.shape # 属性返回张量的形状Out[6]: (tensor(2.), torch.Size([]))
In [7]: v = torch.tensor([1., 2.]) # 将普通Python列表转成张量
In [8]: v, v.shapeOut[8]: (tensor([1., 2.]), torch.Size([2]))
In [9]: m = torch.tensor([[1., 2., 3.], [4., 5., 6.]])
In [10]: m, m.shapeOut[10]:(tensor([[1., 2., 3.], [4., 5., 6.]]), torch.Size([2, 3]))

关于张量的形状,比如 2D 张量的形状是torch.Size([2, 3]),表示有 2 个坐标轴,第一个坐标轴上有 2 个索引,第二个坐标轴上有 3 个索引。

PyTorch 中张量的数据类型

  • torch.float32torch.float:32 位浮点型。

  • torch.float64torch.double:64 位双精度浮点型。

  • torch.float16torch.half:16 位单精度浮点型。

  • torch.int8:8 位有符号整型。

  • torch.uint8:8 位无符号整型。

  • torch.int16torch.short:16 位有符号短整型。

  • torch.int32torch.int:32 位有符号整型。

  • torch.int64torch.long:64 位有符号整型。

  • torch.bool:布尔型。

In [11]: x = torch.ones(2, 3)
In [12]: xOut[12]:tensor([[1., 1., 1.], [1., 1., 1.]])
In [13]: x.dtypeOut[13]: torch.float32

通过 .dtype 属性可以看到x的数据类型是32位浮点型。

PyTorch 默认数据类型是 32 位浮点型。使用 64 位浮点型的话对精度的提升有限,反而增加了计算时间和运行内存。标准 CPU 对 16 位浮点型的支持不太友好,但是现代 GPU 广泛使用 16 位浮点型。如果需要,可以切换到 16 位浮点型以减少神经网络模型的占用空间,这对准确性的影响很小。

如果你用整数构建张量的话,那默认将是 64 位整型:

In [13]: x = torch.tensor([2, 2])
In [14]: xOut[14]: tensor([2, 2])
In [15]: x.dtypeOut[15]: torch.int64

也可以在创建张量时显示指定数据类型:

In [16]: double_points = torch.ones(10, 2, dtype=torch.double)
In [17]: double_points.dtypeOut[17]: torch.float64
In [18]: short_points = torch.tensor([[1, 2], [3, 4]], dtype=torch.short)
In [19]: short_points.dtypeOut[19]: torch.int16

torch.ones 生成内容全为 1 的张量。

强制转换数据类型

In [21]: x = torch.zeros(10, 2)
In [22]: x.dtypeOut[22]: torch.float32
In [23]: y = x.double() # 转成64位浮点型
In [24]: x.dtype, y.dtypeOut[24]: (torch.float32, torch.float64)

torch.zeros() 生成内容全为 0 的张量。

y = x.double() 将x的类型转成了64位浮点型,这个强制转换其实是复制了一份x:

In [32]: x[0]Out[32]: tensor([0., 0.])
In [33]: y[0]Out[33]: tensor([0., 0.], dtype=torch.float64)
In [34]: y[0, 0] = 1
In [35]: x[0]Out[35]: tensor([0., 0.])
In [36]: y[0]Out[36]: tensor([1., 0.], dtype=torch.float64)

也可以使用to方法强制转换类型:

In [37]: x = torch.ones(10, 2)
In [38]: x.dtypeOut[38]: torch.float32
In [39]: y = x.to(dtype=torch.double)
In [40]: y.dtypeOut[40]: torch.float64
In [41]: x[0]Out[41]: tensor([1., 1.])
In [42]: y[0]Out[42]: tensor([1., 1.], dtype=torch.float64)
In [43]: y[0, 0] = 0
In [44]: x[0]Out[44]: tensor([1., 1.])

y = x.to(dtype=torch.double) 与 y = x.to(torch.double) 效果是一样的。

上面 2 种数据类型转换方式都是重新复制了一份张量,比较占用内存。

如果多种不同数据类型的张量混合运算,最终结果张量的数据类型将是范围更大的数据类型:

In [45]: points_64 = torch.rand(5, dtype=torch.double)
In [46]: points_short = points_64.to(torch.short)
In [47]: points_64 * points_shortOut[47]: tensor([0., 0., 0., 0., 0.], dtype=torch.float64)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多