张量(Tensor)对象是我们在实际使用PyTorch的过程中操作的基本数据类型。PyTorch中定义了适用深度学习的基本数据结构——张量,以及张量的各类计算。其实也相当于NumPy中定义的Array和对应的科学计算方法。张量的概念并非PyTorch独有,基本上通用的深度学习框架都拥有张量这一类数据结构,但不同的深度学习框架中张量的定义和使用方法都略有差别。而张量作为数组的衍生概念,其本身的定义和使用方法和Numpy中的Array非常类似,甚至我们可以直接使用Numpy中的Array来进行操作复现一些简单的神经网络算法场景,但写一些更复杂的神经网络则会非常复杂,并且Array数据结构本身也不支持GPU运行。
导入PyTorch包:
import torch
查看版本号:
torch.__version__
张量的最基本的创建方法和Numpy中创建Array的格式一致,都是创建函数(序列)的格式:张量创建函数:torch.tensor()
#通过列表创建函数
t = torch.tensor([1,2])
# 创建的张量t为 tensor([1,2])
#通过元组创建张量
torch.tensor((1, 2))
#通过数组创建张量
import numpy as np
a = np.array((1,2))
t1 = torch.tensor(a)
#创建的张量t为 tensor([1,2],dtype=torch.int32)
#张量和数组类似,都拥有dtype方法,可返回张量类型
注意:整数型的数组默认创建int32(整型)类型,而张量默认创建int64(长整型)类型。
注意:创建浮点型数组时,Array默认创建的是float64(双精度浮点型),张量默认是float32(单精度浮点型)。
除了数值型张量,常用的常量类型还有布尔型张量。
我们还可以通过dtype参数,在创建张量过程中设置输出结果。
零维张量可视为拥有张量属性的单独一个数。张量可以存在GPU上,但Python原生的数值型对象不行,零维张量可以存在GPU上。从学术名称来说,Python中单独一个数是scalars(标量),而零维的张量则是tensor。
一般来说,三维及三维以上的张量,我们就将其称为高维张量。N维张量的创建方法,我们可以先创建M个N-1维的数组,然后将其拼成一个N维的张量。
和NumPy中array相同,当张量各元素属于不同类型时,系统会自动进行隐式转化。
我们还可以使用.float()、.int()等方法对张量类型进行转化。
张量常用的一些函数/方法如下:
t = torch.tensor([1,2])
1)使用ndim属性查看张量的维度
t.ndim
# 1
2)使用shape属性查看形状
t.shape
# torch.Size([2])
3)和size函数相同
t.size()
#torch.Size([2])
注:和NumPy不同,PyTorch中size方法返回结果和shape属性返回结果一致。
4)使用len函数返回张量拥有的(N-1)维元素的个数
len(t)
# 3
5)使用numel函数返回张量中元素的总数
t.numel()
# 2
注:一维张量的len和numel返回结果相同,但更高维度的张量则不然。
如:t1= torch.tensor([[1,2],[3,4]])
# tensor([[1,2],
[3,4]])
len(t1)
# 2
t1.numel()
# 4
张量作为数字的结构化集合,其结构也是可以根据实际需求灵活调整的。
6)flatten函数可以将任意维度张量转化为一维张量
t1.flatten()
# tensor([1,2,3,4]) 按行排列,拉平。
注:如果将零维张量使用flatten,则会将其转化为一维张量。
t0 = torch.tensor(1)
# tensor(1)
t0.flatten()
# tensor([1])
t0.flatten().ndim
# 1
7)可以用reshape方法任意变形
注意:reshape过程中维度的变化,reshape转化后的维度由该方法输入的参数“个数”决定。
在很多数值科学计算的过程中,都会创建一些特殊取值的张量,用于模拟特殊取值的矩阵,如全0矩阵、对角矩阵等。
1)全0张量
torch.zeros([2,3])
# tensor([[0.,0.,0.],
[0.,0.,0.]])
注:由于zeros就已经确定了张量元素取值,因此该函数传入的参数实际上是决定了张量的形状。
2)单位矩阵
3)对角矩阵
略有特殊的是,在PyTorch中,需要利用一维张量去创建对角矩阵,不能使用list直接创建对角矩阵。
t = torch.tensor([1,2])
torch.diag(t)
# tensor([[1,0],
[0,2]])
4) rand:服从0-1均匀分布的张量
5) randn:服从标准正态分布的张量
6)normal:服从指定正态分布的张量
7) randint:整数随机采样结果
8)arange/linspace:生成数列
9)empty:生成未初始化的指定形状矩阵
10)full:根据指定形状,填充指定数值
11)我们还能根据指定对象的形状进行数值填充,只需要在上述函数后面加上_like即可。
t1 = torch.tensor([1,2])
t2 = torch.tensor([[1,2],[3,4]])
torch.full_like(t1,2)
# 根据t1形状,填充数值2
#tensor([2,2])
torch.randint_like(t2,1,10)
# tensor([[4,8],
[5,8]])
torch.zeros_like(t1)
# tensor([0,0])
注:__like类型转化需要注意转化前后数据类型一致的问题,类型不一致将会报错。
张量、数组和列表是较为相似的三种类型对象,在实际操作过程中,经常会涉及三种对象的相互转化。在此前张量的创建过程中,我们看到torch.tensor函数可以直接将数组或者列表转化为张量,而我们也可以将张量转化为数组或者列表。前面介绍了0维张量的概念,此处也将进一步给出零维张量和数值对象的转化方法。
1).numpy方法:张量转化为数组
t1 = torch.tensor([1,2,3,4,5,6,7,8,9,10])
# tensor([1,2,3,4,5,6,7,8,9,10])
t1.numpy()
# array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], dtype=int64)
2) .tolist方法:张量转化为列表
t1.tolist()
# [1,2,3,4,5,6,7,8,9,10]
3) .list函数:张量转化为列表
注:此时转化的列表是由一个个零维张量构成的列表,而非张量的数值组成的列表。
很多时候,我们需要将最终计算的结果张量转化为单独的数值进行输出,此时需要使用.tem方法来执行。
Python 中其他对象类型一样,等号赋值操作实际上是浅拷贝,需要进行深拷贝,则需要使用clone方法。
此处,t1和t11二者指向相同的对象,而要使得t11不随t1对象改变而改变,则需要对t11进行深拷贝,从而使得t11单独拥有一份对象。