一. 张量的基础概念
在学深度学习里,Tensor实际上就是一个多维数组(multidimensional
array) ,是一种最基础的数据结构。
二. 张量常用操作
访问某一个元素(最后一个跳跃访问,每三行访问一个元素,每两列访问一个元素)
image-20241109210857386
构造一个张量:
1 2 import torch a = torch.ones(3 )
使用ndim查看张量的维度:
1 2 t1 = torch.tensor([1 ,2 ]) t1.ndim
输出:1
使用shape查看形状
1 2 t1 = torch.tensor([1 ,2 ]) t1.shape
由两个形状相同的二维数组创建一个三维的张量
1 2 3 a1 = np.array([[1 ,2 ,2 ],[3 ,4 ,4 ]]) a2 = np.array([[5 ,6 ,6 ],[7 ,8 ,8 ]]) t3 = torch.tensor([a1,a2])
输出:结果是一个三位向量
tensor([[[1, 2, 2], [3, 4, 4]], [[5, 6, 6], [7, 8, 8]]],
dtype=torch.int32)
flatten拉平,将任意维度张量转化为一维张量
1 2 t2 = torch.tensor([[1 , 2 ],[3 , 4 ]]) t2.flatten()
输出:
tensor([1, 2, 3, 4])
reshape方法,任意变形
1 2 t1 = torch.tensor([1 ,2 ]) t1.reshape(2 ,1 )
输出:
tensor([[1],[2]])
torch.Size([2, 1])
特殊张量创建:全零张量 .zeros()、全1张量 .ones()、单位矩阵
.eyes()、对角矩阵 .diag(一维张量)
1 2 3 torch.eye(5 ) t1 = torch.tensor([1 , 2 ]) torch.diag(t1)
输出:
tensor([[1., 0., 0., 0., 0.], [0., 1., 0., 0., 0.], [0., 0., 1., 0.,
0.], [0., 0., 0., 1., 0.], [0., 0., 0., 0., 1.]])
tensor([[1, 0],
[0, 2]])
服从0-1均匀分布的张量rand
输出:
tensor([[-0.8110, -1.1295, -0.2913], [-1.1786, -0.8882, 0.2433]])
arange/linspace:生成数列
1 2 3 torch.arange(5 ) torch.arange(1 ,5 ,0.5 ) torch.linspace(1 ,5 ,3 )
empty,初始化指定形状矩阵
输出:
tensor([[2, 2, 2, 2], [2, 2, 2, 2]])
创建指定形状的数组
1 2 torch.full_like(t1,2 ) torch.randint_like(t2,1 ,10 )
张量与其它相关类型(数组、列表)之间转化方法
1 2 3 t1 = torch.tensor([1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ]) t1.numpy() t1.tolist()
输出:
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], dtype=int64)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
切片,一小点需要注意
分块
1 tc = torch.chunk(t2,4 ,dim=0 )
输出: (tensor([[0, 1, 2]]), tensor([[3, 4, 5]]), tensor([[6, 7,
8]]), tensor([[ 9, 10, 11]]))
拆分:split函数
1 2 t2 = torch.arange(12 ).reshape(4 ,3 ) torch.split(t2,2 ,0 )
输出:
(tensor([[0, 1, 2], [3, 4, 5]]), tensor([[ 6, 7, 8], [ 9, 10,
11]]))
torch.split(t2,[1,3],0)
[1,3]表示“第一块长度为1,第二块长度为3
torch.cat
的用法:多个张量合并在一起,默认按行(dim=0)【记住二维张量dim=0表示行】进行拼接,维度不匹配会报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 z = torch.arange(12 , dtype=torch.float32).reshape(3 ,4 ) k = torch.tensor([[2 ,3 ,4 ,1 ],[4 ,5 ,6 ,1 ],[7 ,8 ,9 ,1 ]]) h = torch.cat((z,k), dim=0 ), torch.cat((z,k), dim=1 )print (h) 输出: (tensor([[ 0. , 1. , 2. , 3. ], [ 4. , 5. , 6. , 7. ], [ 8. , 9. , 10. , 11. ], [ 2. , 3. , 4. , 1. ], [ 4. , 5. , 6. , 1. ], [ 7. , 8. , 9. , 1. ]]), tensor([[ 0. , 1. , 2. , 3. , 2. , 3. , 4. , 1. ], [ 4. , 5. , 6. , 7. , 4. , 5. , 6. , 1. ], [ 8. , 9. , 10. , 11. , 7. , 8. , 9. , 1. ]]))
【-1】访问最后一个元素,【1:3】选择第一行和第二行的元素(左闭右开)
张量的维度变化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 x = torch.randn(3 ,4 ) 输出: tensor([[ 0.6480 , 1.5947 , 0.6264 , 0.6051 ], [ 1.6784 , 0.2768 , -1.8780 , -0.1133 ], [-0.6442 , 0.8570 , 0.1677 , 0.2378 ]]) mask = x.ge(0.5 ) 输出: tensor([[ True , True , True , True ], [ True , False , False , False ], [False , True , False , False ]]) torch.masked_select(x,mask) 输出: tensor([0.6480 , 1.5947 , 0.6264 , 0.6051 , 1.6784 , 0.8570 ])
删除不必要的维度
1 2 t = torch.zeros(1 ,1 ,3 ,1 ) torch.squeeze(t).shape
输出:
torch.Size([3])
1 2 3 b.squeeze(0 ).shape b.squeeze(-1 ).shape b.squeeze(1 ).shape
unsqueeze手动升维
调用方法1:torch.unsqueeze(t, dim=n)
1 2 3 t = torch.zeros(1 ,2 ,1 ,2 ) torch.unsqueeze(t,dim=0 ).shape
输出:
torch.Size([1, 1, 2, 1, 2])
调用方法2:a.unsqueeze(dim=n)
1 2 3 4 a.unsqueeze(0 ).shape a.unsqueeze(-1 ).shape
expand:broadcasting #只改变理解方式,不增加数据
1 2 b = torch.rand(1 ,32 ,1 ,1 ) b.expand(4 ,32 ,14 ,14 ).shape
输出:
torch.Size([4, 32, 14, 14])
repeat的参数表示重复的次数
1 2 b.repeat(4 ,32 ,1 ,1 ).shape
输出:
torch.Size([4, 1024, 1, 1])
矩阵转置
1 2 3 a = torch.randn(3 ,4 ) a.shape a.t()
输出:
torch.Size([4, 3])
维度转换
1 2 3 a = torch.rand(4 ,3 ,32 ,32 )2 = a.transpose(1 ,3 ).contiguous().view(4 ,3 *32 *32 ).view(4 ,32 ,32 ,3 ).transpose(1 ,3 )
解释:
#transpose包含了要交换的两个维度[b,c,h,w]→[b,w,h,c]
#数据的维度顺序必须与存储顺序一致,用.contiguous把数据变成连续的
#.view(4,33232) [b,whc]
#.view(4,3,32,32) [b,w,h,c]
#.transpose(1,3) [b,c,g,w]
permute维度转换
1 2 b = torch.rand(4 ,3 ,28 ,32 ) b.permute(0 ,2 ,3 ,1 ).shape
输出:
torch.Size([4, 28, 32, 3])