文章目录
一.张量的定义
在 PyTorch 中,张量可以是一个标量、一个向量、一个矩阵及更高维的数组,可以用阶来表示张量的维数。
- 标量:0 阶的数值,一个单独的数,如 135。
- 向量:1 阶的数值,一列或一行数组,如 [1, 3, 5]。
- 矩阵:2 阶的数值,二维数组 ,如 [[1, 2, 3], [4, 5, 6]]。
- 张量:超过 2 阶的数值,高维数组,如 [[[xxx]]]。
在 PyTorch0.4 版本之前,Tensor 不能计算梯度,所以在需要深度学习网络中,需要计算梯度的 Tensor 都需要使用 Variable(Tensor)进行封装,然后构建计算图。在 0.4 之后,合并了 Tensor 类和 Variable类,可以直接计算 Tensor 的梯度,因此 Variable() 逐渐消失。
二.张量的生成
PyTorch 生成张量有多种方式,有一半主要使用以下 5 种。
1.torch.tensor()函数
tensor(data [,dtype [,device [,requires_grad]]])
- data:数值或布尔类型的 Python 列表或元组。
- dtype:数据类型,默认为 torch.int64 或 torch.float32。
- device:tensor 被分配的设备,默认为 cpu。
- requires_grad:是否需要计算每个元素梯度,默认为 False,注意 data 或 dtype 必须是浮点数才可以修改为 True。
(1).创建
# 一般张量
A = torch.tensor([[1,2,],[3,4]])
# 可求梯度的张量
B = torch.tensor([[1,2,],[3,4]],dtype=torch.float32,requires_grad=True)
'''
tensor([[1, 2],
[3, 4]])
tensor([[1., 2.],
[3., 4.]], requires_grad=True)
'''
(2).属性
A = torch.tensor([[1,2,],[3,4]])
A.data # 张量的数据
A.dtype # 张量的 dtype
A.device # 张量的所在设备
A.requires_grad # 张量是否可以求导
A.shape # 张量的维度:torch.size([2,2])
A.size() # 张量的形状:torch.size([2,2])
A.numel() # 张量的元素数量:4
A.item() # 张量的 python 数值,注意必须是 0 维张量,即标量才行
(3).张量求梯度
x = torch.tensor([[1.0,2],[3,4]],requires_grad=True)
y = torch.tensor([[2.3,4],[30,14]],requires_grad=True)
z = torch.sum(x**2+2*y**2+1)
# 固定 torch.sum 形式,因为 z.backward()求导时z必须时一个浮点类型标量,sum()的作用就是标量化
# 逐元素求导
# 如果写成 torch.max 或 median,每个元素位置的数将会是所有元素对应的 max、median 值或 0.0
print(x.requires_grad) # x是否可以求导
print(y.requires_grad)
print(z.requires_grad)
z.backward() # z对包含的张量求导(本例为x和y)
print(x.grad) # z对x求导后的结果
print(y.grad) # z对y求导后的结果
'''
tensor([[2., 4.],
[6., 8.]])
tensor([[ 9.2000, 16.0000],
[120.0000, 56.0000]])
'''
2.torch.Tensor()类
(1).普通创建
A = torch.Tensor([[1,2,],[3,4]]) # 根据已有的数据创建张量,dtype 为 torch.float32
A = torch.Tensor(2,3) # 创建特定形状的张量,数值是随机的
B = torch.ones_like(A) # 创建与 A 维度相同、性质相似的全 1 张量
B = torch.zeros_like(A) # 创建与 A 维度相同、性质相似的全 0 张量
B = torch.rand_like(A) # 创建与指定张量A维度、性质相似的随机张量
(2).随机生成张量
torch.manual_seed(123) # 随机数的种子,保证生成的随机数是可重复出现的
A = torch.arange(n) # 0到n-1的一维序列
A = torch.arange(2,n) # 2到n-1的一维序列
A = torch.arange(start,end,step) # 一维序列
A = torch.randperm(n) # 0到n-1的一维整数序列,元素位置随机打乱
A = torch.linspace(start,end,num) # 生成固定等间隔的num个数,包含start和end
A = torch.logspace(start,end,num) # 生成以对数为间隔的num个数,包含start和end
A = torch.normal(mean=num,std=num) # mean和std都可以多个,对应每个随机数分布的均值和标准差的二维数据
A = torch.eye(3,4) # 生成3行4列的单位矩阵(注意只能生成二维的单位矩阵)
# 以下为多维数据,括号里几个参数就是几维数据
A = torch.rand(3,4) # 生成3行4列的均匀分布,区间[0,1)
A = torch.ones(3,4) # 生成3行4列的全1
A = torch.zeros(3,4) # 生成3行4列的全0
A = torch.empty(3,4) # 生成3行4列的全无穷小矩阵
A = torch.full((3,4),fill_value=num) # 生成3行4列的全num矩阵
三.张量的数据类型
数据类型 | dtype | CPU tensor | GPU tensor |
---|---|---|---|
16位浮点型 | torch.float16 torch.half | torch.HalfTensor | torch.cuda.HalfTensor |
32位浮点型(默认) | torch.float32 torch.float | torch.FloatTensor | torch.cuda.FloatTensor |
64位浮点型 | torch.float64 torch.double | torch.DoubleTensor | torch.cuda.DoubleTensor |
8位无符号整型 | torch.uint8 | torch.ByteTensor | torch.cuda.ByteTensor |
8位有符号整型 | torch.int8 | torch.CharTensor | torch.cuda.CharTensor |
16位有符号整型 | torch.int16 torch.short | torch.ShortTensor | torch.cuda.ShortTensor |
32位有符号整型 | torch.int32 torch.int | torch.IntTensor | torch.cuda.IntTensor |
64位有符号整型(默认) | torch.int64 torch.long | torch.LongTensor | torch.cuda.LongTensor |
1.获取张量的默认数据类型
torch.get_default_dtype()
2.修改张量的默认数据类型
torch.set_default_tensor_type(torch.half)
3.张量数据类型转换
A = torch.tensor([[1,2,],[3,4]])
B = A.to(torch.float32) # 括号中必须是dtype格式
C = A.type(torch.DoubleTensor) # 括号中必须是CPU tensor格式或GPU tensor格式
4.torch和numpy转换
(1).numpy 转 torch
np_a = np.ones((2,3))
torch_a = torch.as_tensor(np_a)
torch_a = torch.from_numpy(np_a)
(2).torch 转 numpy
np_a = torch_a.numpy()
四.张量的操作
1.改变形状
A = torch.arange(n).reshape(m,n)
B = torch.reshape(input=A,shape=(m,n))
A.resize_(m,n)
A.resize_as_(B)
A = A.view(A.shape[0],-1) # 通常用在卷积层与全连接层中间
A = A.view(A.size(0),-1)
2.改变维度
# 维度提升
A = torch.arange(12).reshape(2,6)
B = torch.unsqueeze(A,dim=0) # 在0维前面插入一个维度
B = A.unsqueeze(dim=0)
B.shape #[1,2,6]
# 维度减小
C = torch.squeeze(B) # 移除所有维度为1的维度
C = torch.squeeze(B,dim=0) # 移除指定维度为1的维度
C = B.squeeze()
C = B.squeeze(dim=0)
# 维度提升并改变内容(广播机制)
A = torch.arange(l)
B = A.expand(m, n, k)
C = A.expand_as(B)
# 注意 expand 的参数
# 当 A 标量时,expand 中的 m,n,k 可以是任意非负整数
# 当 A 一维数组时,expand 中的 m,n 可以是任意非负整数,k必须和 A 的长度相等,或者直接写成-1
# 当 A 多维数组时,expand 中的 后几个数值形状必须和 A 的 shape 相同
2.获取元素
# 切片方式
A[:,:,:]
# 索引设置
torch.where(condition,x,y) # 满足条件时返回x对应索引的位置值,否则返回y对应的位置的值(并不是返回x或y)
torch.tril(A,diagonal=0) # 返回张量的下三角部分的内容,上三角用0填充,diagonal为对角线的偏移位置,正数向上偏移,负数向下
torch.triu(A,diagonal=0) # 返回张量的上三角部分的内容,下三角用0填充
torch.diag(A,diagonal=0) # 返回对角线的元素
torch.diag(torch.tensor([1,2,3])) # 提供对角线的元素生成矩阵
3.拼接和拆分
#使用cat拼接
A = torch.tensor([[0,1,2],[3,4,5]])
B = torch.tensor([[0,2,4],[6,8,10]])
torch.cat((A,B),dim=0) # 在0维拼接
torch.cat((A,B),dim=1) # 在1维拼接
# 使用stack方式会多出来一个维度,所以可以dim=2
torch.stack((A,B),dim=0)
torch.stack((A,B),dim=1)
torch.stack((A,B),dim=2)
#使用chunk分割,沿着dim维度切分,不能被整数切割时,最后一个块最小,但不能为0
B1,B2 = torch.chunk(A,2,dim=0)
B1,B2 = torch.chunk(A,2,dim=1)
B1,B2,B3 = torch.chunk(A,3,dim=0)
B1,B2,B3 = torch.chunk(A,3,dim=1)
#使用split分割,沿着dim维度切分,[指定每个块的大小]
B1,B2 = torch.chunk(A,[1,2],dim=0)
B1,B2 = torch.chunk(A,[1,2],dim=1)
B1,B2,B3 = torch.chunk(A,[1,2,3],dim=0)
B1,B2,B3 = torch.chunk(A,[1,2,3],dim=1)
五.张量的计算
1.比较大小
torch.allclose(A,B,rtol=1e-5,atol=1e-8,equal_nan=False)
# 比较两个元素是否接近;公式:|A-B|≤atol+rtolx|B|;
# equal_nan=False时两个NaN不接近,为True时两个NaN接近
torch.eq(A,B) # 逐元素比较是否相等(返回一堆bool)
torch.equal(A,B) # 比较两个张量的形状和元素是否都相同
torch.ge(A,B) # 逐元素比较 ≥
torch.gt(A,B) # 逐元素比较 >
torch.le(A,B) # 逐元素比较 ≤
torch.lt(A,B) # 逐元素比较 <
torch.ne(A,B) # 逐元素比较 !=
torch.isnan(A) # 逐元素判断是否为缺失值
2.基本运算
(1) 逐元素运算
A*B
A/B
A+B
A-B
A//B
A**2
A.pow(2)
torch.pow(A,2)
torch.exp(A) # A各元素的e次方
torch.log(A)
torch.sqrt(A)
torch.rsqrt(A) # 平方根倒数
torch.clamp_max(A,4) # A中超过4的值变为4
torch.clamp_min(A,4) # A中小于4的值变为4
torch.clamp(A,2.5,4) # A中小于2.5的值变为2.5,大于4的值变为4
(2) 矩阵之间的运算
torch.t(A) # A的转置
A.matmul(B) # 矩阵相乘
torch.matmul(A,B) # 矩阵相乘
torch.inverse(A) # 求A的逆矩阵
3.统计相关的计算
torch.max(tensor=,dim=) A.max(dim=) # A中dim维度的最大值
torch.max(A) # A中的最大值
torch.min(A) # A中的最小值
torch.argmax(A) # A中的最大值的位置
torch.argmin(A) # A中的最小值的位置
torch.sort(A,descending=Fasle,dim=-1)# 对一维张量排序或高维指定维度进行排序,默认升序
torch.topk(A,K,dim) # 获取张量中前K个最大的数及其位置
torch.kthvalue(A,K,dim) # 获取张量中第K个最小的数及其位置
torch.mean(A,dim) # 张量指定维度的均值 (不加dim时是所有元素的)
torch.sum(A,dim) # 张量指定维度的求和 (不加dim时是所有元素的)
torch.cumsum(A,dim) # 张量指定维度的计算累加和
torch.median(A,dim) # 张量指定维度的计算中位数(不加dim时是所有元素的)
torch.cumprod(A,dim) # 张量指定维度的计算累乘积
torch.std(A,dim) # 张量指定维度的标准差 (不加dim时是所有元素的)