2.1 PyTorch中张量的数据类型及生成全面详解

PyTorch中的张量

  • 目标
  • 1. 什么是张量
  • 2. 张量的数据类型
    • 2.1 张量的数据类型
    • 2.2 张量的数据类型查看及转换
      • 2.2.1 查看张量的数据类型
      • 2.2.2 重新设置张量的默认数据类型及其转换
      • 2.2.3 获取张量的默认数据类型
  • 3. 张量的生成
    • 3.1 torch.tensor()函数生成张量
    • 3.2 torch.Tensor()函数生成张量
    • 3.3 张量和NumPy数据互相转换
    • 3.4 随机数生成张量
    • 3.5 其他生成张量的函数
  • 4. 小结
  • 参考资料

目标

通过本篇文章的学习,你将学习到PyTorch张量模块中第一部分内容,包含以下内容:

  • 张量的数据类型——查看张量的数据类型、重新设置张量的默认数据类型及其转换、获取张量的默认数据类型
  • 张量的生成——torch.tensor()生成、torch.Tensor()生成、张量和NumPy数据互相转换、随机数生成张量、其他生成张量的函数等

1. 什么是张量

在数学中,一个单独的数可以称为标量,一列或者一行数组可以称为向量,一个二维数组称为矩阵,矩阵中的每一个元素都可以被行和列的索引唯一确定,但如果一个数组的维度超过2,那么我们可以称该数组为张量(Tensor)

Tips:

  • 在PyTorch中,张量属于一种数据结构,它可以是一个标量、一个向量、一个矩阵,甚至是更高维度的数组,因此PyTorch中的张量(Tensor)和Numpy中的数组(ndarray)非常相似,在使用时也会经常将PyTorch中的张量和Numpy中的数组相互转化。
  • 在深度网络中,基于PyTorch的相关计算和优化都是在Tensor的基础上完成的。

2. 张量的数据类型

2.1 张量的数据类型

在torch中CPU和GPU张量分别有8种数据类型,如下表1所示。

表1 张量的数据类型
Data type dtype CPU Tensor GPU Tensor
32-bit floating point torch.float32 or torch.float torch.FloatTensor torch.cuda.FloatTensor
64-bit floating point torch.float64 or torch.double torch.DoubleTensor torch.cuda.DoubleTensor
16-bit floating point torch.float16 or torch.half torch.HalfTensor torch.cuda.HalfTensor
8-bit integer (unsigned) torch.uint8 torch.ByteTensor torch.cuda.ByteTensor
8-bit integer (signed) torch.int8 torch.CharTensor torch.cuda.CharTensor
16-bit integer (signed) torch.int16 or torch.short torch.ShortTensor torch.cuda.ShortTensor
32-bit integer (signed) torch.int32 or torch.int torch.IntTensor torch.cuda.IntTensor
64-bit integer (signed) torch.int64 or torch.long torch.LongTensor torch.cuda.LongTensor

注意: 在torch中默认的数据类型是32位浮点型(torch.FloatTensor)。

2.2 张量的数据类型查看及转换

可以通过torch.set_default_tensor_type()函数设置默认的数据类型,但是该函数只支持设置浮点型数据类型,下面使用程序演示如何查看和设置张量的数据类型。

2.2.1 查看张量的数据类型

# 导入所需要的库
import torch

print(torch.tensor([1.2, 2.2]).dtype)

>>>torch.float32

torch.tensor()函数生成一个张量,使用.dtype方法查看张量的数据类型,结果为32位浮点型。

2.2.2 重新设置张量的默认数据类型及其转换

# 将张量的默认数据类型设置为其它类型
# torch.set_default_tensor_type()函数只支持设置浮点型数据类型
torch.set_default_tensor_type(torch.DoubleTensor)
print(torch.tensor([1.2, 2.2]).dtype)

>>>torch.float64
# 将张量的默认数据类型转化为其他数据类型
a = torch.tensor([1.2, 2.2])
print("a.dtype:", a.dtype)
print("a.long()方法:", a.long().dtype)
print("a.int()方法:", a.int().dtype)
print("a.float()方法:", a.float().dtype)

>>>a.dtype: torch.float64
>>>a.long(): torch.int64
>>>a.int(): torch.int32
>>>a.float(): torch.float32

Tips: 由于已经重新设置过张量的默认数据类型为64-bit floating point,所以生成张量a的数据类型a.dtypefloat64

2.2.3 获取张量的默认数据类型

# 恢复torch默认的数据类型
torch.set_default_tensor_type(torch.FloatTensor)
print(torch.tensor([1.2, 2.2]).dtype)

>>>torch.float32

# 使用torch.get_default_dtype()获取默认的数据类型
print(torch.get_default_dtype())

>>>torch.float32

从张量的.dtype方法输出结果为torch.float32可知,已经将默认的数据类型恢复为32位浮点型。

Tips:torch.set_default_tensor_type()torch.get_default_dtype()是有区别的,请不要记混淆了。

3. 张量的生成

3.1 torch.tensor()函数生成张量

(1)Python列表或序列可以通过torch.tensor()函数构造张量

A = torch.tensor([[1.0, 1.0], [2.0, 2.0]])
print(A)

>>>tensor([[1., 1.],
        [2., 2.]])

(2)查看张量的维度.shape、大小.size()和元素数量.numel()

# 获取张量的维度
print("A的维度为:", A.shape)
# 获取张量的形状大小
print("A的形状大小为:", A.size())
# 计算张量中包含元素的数量
print("A的元素数量为:", A.numel())

>>>A的维度为: torch.Size([2, 2])
>>>A的形状大小为: torch.Size([2, 2])
>>>A的元素数量为: 4

(3)参数dtype指定张量的数据类型,参数requires_grad指定张量是否需要计算梯度

在PyTorch中,只有计算了梯度的张量,才能在深度网络优化时根据梯度大小进行更新,下面生成一个需要计算梯度的张量B:

B = torch.tensor((1, 2, 3), dtype=torch.float32, requires_grad=True)
print(B)

>>>tensor([1., 2., 3.], requires_grad=True)

参数dtype=torch.float32指定张量B中的元素为32位浮点型,参数requires_grad=True表明张量可以计算每个元素的梯度。

为更好的理解PyTorch中梯度的计算,下面针对张量B计算sum ( B 2 B^2 B2)在每个元素上梯度的大小为示例:

# 因为张量B是可以计算梯度的,故可以计算sum(B**2)的梯度
Y  = B.pow(2).sum()
print(Y)
Y.backward()
print(B.grad)

>>>tensor(14., grad_fn=<SumBackward0>)
>>>tensor([2., 4., 6.])

从输出结果可以看出每个元素位置上的梯度为2 x B

注意: 只有浮点型数据才能计算梯度,其他类型的数据是不能计算张量的梯度,如下面的程序就会报错:

# 注意只有浮点型张量允许计算梯度
B = torch.tensor((1, 2, 3), dtype=torch.int32, requires_grad=True)
print(B)

>>>Traceback (most recent call last):
  File "D:/深度学习/Tensor of PyTorch.py", line 44, in <module>
    B = torch.tensor((1, 2, 3), dtype=torch.int32, requires_grad=True)
RuntimeError: Only Tensors of floating point dtype can require gradients

3.2 torch.Tensor()函数生成张量

(1)torch.Tensor()torch.tensor()相比,有如下区别:

  • torch.Tensor()可以根据指定的形状生成张量。如,根据Python列表生成张量C。
# 根据已有的数据创建张量
C = torch.Tensor([1, 2, 3, 4])
print(C)

>>>tensor([1., 2., 3., 4.])
  • 可以根据形状参数生成特定尺寸的张量
# 创建具有特定大小的张量
D = torch.Tensor(2, 3)
print(D)

>>>tensor([[0.0000e+00, 0.0000e+00, 1.4013e-45],
        [0.0000e+00, 1.4013e-45, 0.0000e+00]])

(2)使用torch.**_like()系列函数生成与指定张量维度相同、性质相似的张量。

如使用torch.ones_like()函数生成与D维度相同的全1张量:

# 创建一个与D相同大小类型的全1张量
print(torch.ones_like(D))

>>>tensor([[1., 1., 1.],
        [1., 1., 1.]])

使用torch.zeros_like()函数生成与D维度相同的全0张量:

# 创建一个与D相同大小类型的全0张量
print(torch.zeros_like(D))

>>>tensor([[0., 0., 0.],
        [0., 0., 0.]])

使用torch.rand_like()函数生成与D维度相同的随机张量:

# 创建一个与D相同大小类型的随机张量
print(torch.rand_like(D))

>>>tensor([[0.4231, 0.9051, 0.2136],
        [0.8762, 0.3098, 0.9619]])

(3)对一个创建好的张量D,可以使用D.new_**()系列函数创建出新的张量。

如使用D.new_tentor()将列表转化为张量:

# 创建一个类型相似但尺寸不同的张量
E = [[1, 2], [3, 4]]
E = D.new_tensor(E)
print('D.dtype:', D.dtype)
print('E.dtype:', E.dtype)

>>>D.dtype: torch.float32
>>>E.dtype: torch.float32

Tips: D.new_tensor(E)是将列表E转化为32位浮点型的张量

还可以使用其他函数得到新的张量,如下表2所示:

表2 D.new_**()系列函数
函数 描述
D.new_full((3,3),fill_value=1) 3 x 3使用1填充的张量
D.new_zeros((3,3)) 3 x 3的全0张量
D.new_ones((3,3)) 3 x 3的全1张量
D.new_empty((3,3)) 3 x 3的空张量
# 3 x 3使用fill_value填充的张量
print(D.new_full((3, 3), fill_value=1))
# 3 x 3的全1张量
print(D.new_ones((3, 3)))
# 3 x 3的全0张量
print(D.new_zeros((3, 3)))
# 3 x 3的空张量
print(D.new_empty((3, 3)))

>>>tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])
>>>tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])
>>>tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
>>>tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]]

3.3 张量和NumPy数据互相转换

(1)将Numpy数组转化为PyTorch张量,可以使用torch.as_tensor()函数和torch.from_numpy()函数。

# 利用Numpy数组生成张量
import numpy as np
F = np.ones((3, 3))
# 使用torch.as_tensor()函数
Ftensor = torch.as_tensor(F)
print(Ftensor)
Ftensor = torch.from_numpy(F)
print(Ftensor)

>>>tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
>>>tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)

注意: 从上面程序片段中可以看到,Numpy数组转化为PyTorch张量的输出中得到的张量类型是64位浮点型数组,这是因为使用Numpy生成的数组默认就是64位浮点型数组。

(2)将PyTorch张量转化为Numpy数组,可以使用torch.numpy()函数转化为Numpy数组。

# 使用torch.numpy()将张量转化为Numpy数组
print(Ftensor.numpy())

>>>[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]

3.4 随机数生成张量

在PyTorch中可以通过相关随机数生成张量,并且可以指定生成随机数的分布函数等。

(1)使用torch.normal()函数生成服从正态分布的张量

# 通过指定均值和标准差生成随机数
# 指定生成随机数的种子
torch.manual_seed(123)
# 生成服从正态分布(0, 1)分布的随机函数
A = torch.normal(mean=0.0, std=torch.tensor(1.0))
print(A)

>>>tensor(-0.1115)

注意: 在生成随机数之前,可以使用torch.manual_seed()函数,指定生成随机数的种子,用于保证生成的随机数是可以重复出现的。

如果mean参数和std参数都只有一个元素,则只会生成一个随机数;如果mean参数和std参数有多个值,则只会生成多个随机数。

指定一个均值和多个标准差生成随机数,例如:

# 通过指定一个均值和多个标准差生成随机数
# 指定生成随机数的种子
torch.manual_seed(123)
# 均值为0,标准差分别为1、2、3、4
A = torch.normal(mean=0.0, std=torch.arange(1, 5.0))
print(A)

>>>tensor([-0.1115,  0.2407, -1.1089, -0.9617])

分别指定每个随机数服从的均值,例如:

# 分别指定每个随机数服从的均值
# 指定生成随机数的种子
torch.manual_seed(123)
# 均值分别为1、2、3、4,标准差分别为1、2、3、4
A = torch.normal(mean=torch.arange(1, 5.0), std=torch.arange(1, 5.0))
print(A)

>>>tensor([0.8885, 2.2407, 1.8911, 3.0383])

(2)使用torch.rand()函数在区间[0, 1]上生成服从均匀分布的张量

# 在区间[0,1]上生成服从均匀分布的张量
torch.manual_seed(123)
# 均值为0,标准差为1的3x4张量
B = torch.rand(3, 4)
print(B)

>>>tensor([[0.2961, 0.5166, 0.2517, 0.6886],
        [0.0740, 0.8665, 0.1366, 0.1025],
        [0.1841, 0.7264, 0.3153, 0.6871]])

(3)使用torch.rand_like()函数生成与其维度相同的随机变量

# 生成和其他张量尺寸相同的随机张量
torch.manual_seed(123)
C = torch.ones(2, 3)
D = torch.rand_like(C)
print(D)

>>>tensor([[0.2961, 0.5166, 0.2517],
        [0.6886, 0.0740, 0.8665]])

(4)在生成随机数前,如果没有指定生成随机数的种子,则使用torch.randn()torch.rand_like()函数都可以生成服从标准正态分布的随机数张量,例如:

# 生成服从标准正态分布的随机数张量
print(torch.randn(3, 3))
print(torch.rand_like(C))

>>>tensor([[ 0.9447,  0.6217, -1.3501],
        [-0.1881, -2.3891, -0.4759],
        [ 1.7603,  0.6547,  0.5490]])
>>>tensor([[0.2775, 0.8573, 0.8993],
        [0.0390, 0.9268, 0.7388]])

(5)使用torch.randperm(n)函数,可将0~n(包含0不包含 n n n)之间的整数进行随机排序后输出,如将0~9这10个数字重新排序后输出:

# 将0~10(不包含10)之间的整数随机排序
torch.manual_seed(123)
print(torch.randperm(10))

>>>tensor([2, 0, 8, 1, 3, 7, 4, 9, 5, 6])

3.5 其他生成张量的函数

(1)在PyTorch中包含np.arrange()用法类似的函数torch.arrange(),常用来生成张量。

# 使用torch.arrange()生成张量
print(torch.arange(start=0, end=10, step=2))

>>>tensor([0, 2, 4, 6, 8])

(2)使用torch.linspace()函数在范围内生成固定数量的等间隔张量。

# 在范围内生成固定数量的等间隔张量
print(torch.linspace(start=1, end=10, steps=6))

>>>tensor([ 1.0000,  2.8000,  4.6000,  6.4000,  8.2000, 10.0000])

(3)使用torch.logspace()函数可生成以对数为间隔的张量

# 生成以对数为间隔的张量
print(torch.logspace(start=0.1, end=1.0, steps=6))

>>>tensor([ 1.2589,  1.9055,  2.8840,  4.3652,  6.6069, 10.0000])

输出结果与10**(torch.linspace(start=0.1, end=1.0, steps=6))等价

print(10**(torch.linspace(start=0.1, end=1.0, steps=6)))

>>>tensor([ 1.2589,  1.9055,  2.8840,  4.3652,  6.6069, 10.0000])

PyTorch中还包含很多预定义的函数,用于生成特定的张量。常用函数如下表3所示。

表3 生成张量系列函数
函数 描述
torch.zeros(3, 3) 3 x 3全0的张量
torch.ones((3, 3)) 3 x 3的全1张量
torch.eye(3) 3 x 3的单位张量
torch.full((3, 3), fill_value=1) 3 x 3使用1填充的张量
torch.empty(3, 3) 3 x 3的空张量

4. 小结

本篇文章主要介绍了PyTorch中张量板块中第一部分的内容,包括张量的概念、张量的数据类型、张量的生成等相关内容,并详细解释了量数据类型的查看、转换、各种生成张量的函数及注意事项,还给出了PyTorch中常用预定义函数等内容。张量板块内容较多,后期会继续介绍张量的操作及计算的相关内容。

参考资料

  1. 《PyTorch 深度学习入门与实战(案例视频精讲)》,孙玉林,余本国著. 北京:中国水利水电出版社,2020.7
如果文章对你有帮助,欢迎点赞与关注, 谢谢!

在这里插入图片描述

你可能感兴趣的:(深度学习,pytorch,python,张量)