通过本篇文章的学习,你将学习到PyTorch张量模块中第一部分内容,包含以下内容:
torch.tensor()
生成、torch.Tensor()
生成、张量和NumPy数据互相转换、随机数生成张量、其他生成张量的函数等在数学中,一个单独的数可以称为标量,一列或者一行数组可以称为向量,一个二维数组称为矩阵,矩阵中的每一个元素都可以被行和列的索引唯一确定,但如果一个数组的维度超过2,那么我们可以称该数组为张量(Tensor)。
Tips:
- 在PyTorch中,张量属于一种数据结构,它可以是一个标量、一个向量、一个矩阵,甚至是更高维度的数组,因此PyTorch中的张量(Tensor)和Numpy中的数组(ndarray)非常相似,在使用时也会经常将PyTorch中的张量和Numpy中的数组相互转化。
- 在深度网络中,基于PyTorch的相关计算和优化都是在Tensor的基础上完成的。
在torch中CPU和GPU张量分别有8种数据类型,如下表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)。
可以通过torch.set_default_tensor_type()
函数设置默认的数据类型,但是该函数只支持设置浮点型数据类型,下面使用程序演示如何查看和设置张量的数据类型。
# 导入所需要的库
import torch
print(torch.tensor([1.2, 2.2]).dtype)
>>>torch.float32
torch.tensor()
函数生成一个张量,使用.dtype
方法查看张量的数据类型,结果为32位浮点型。
# 将张量的默认数据类型设置为其它类型
# 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.dtype
为float64
。
# 恢复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()
是有区别的,请不要记混淆了。
(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
(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所示:
函数 | 描述 |
---|---|
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.]]
(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.]]
在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])
(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所示。
函数 | 描述 |
---|---|
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的空张量 |
本篇文章主要介绍了PyTorch中张量板块中第一部分的内容,包括张量的概念、张量的数据类型、张量的生成等相关内容,并详细解释了量数据类型的查看、转换、各种生成张量的函数及注意事项,还给出了PyTorch中常用预定义函数等内容。张量板块内容较多,后期会继续介绍张量的操作及计算的相关内容。