pytorch常用的数据类型如下:
| 描述 | 数据类型 | CPU张量 | GPU张量 |
|---|---|---|---|
| 16位半浮点 | torch.half | torch.HalfTensor | torch.cuda.HalfTensor |
| 32位浮点 | torch.float | torch.FloatTensor | torch.cuda.FloatTensor |
| 64位浮点 | 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 or torch.short | torch.ShortTensor | torch.cuda.ShortTensor |
| 32位整型 | torch.int32 or torch.int | torch.IntTensor | torch.cuda.IntTensor |
| 64位整型 | torch.int64 or torch.long | torch.LongTensor | torch.cuda.LongTensor |
a.type() 查看变量类型;a.cuda() CPU—>GPU;a.cpu() GPU—>CPU;len(a) 返回a的第一维
a.dim() 或 len(a.shape) 返回张量维度;a.size() 或 a.shape 返回张量大小;a.numel() 返回元素个数
方法一:
# 直接转换 a = a.long(),a.int(),a.float(), a.double()...
方法二:
# 直接转换 a = a.type(torch.FloatTensor),a.type(torch.DoubleTensor)...
方法三:
# 将a转换为与b的类型相同 a = torch.randint(1,6,[2,3]) # torch.LongTensor b = torch.rand(4,3) # torch.FloatTensor a = a.type_as(b) print(a.type()) # torch.FloatTensor索引和切片 维度变换
(1)变形
a.view() 函数和a.reshape() 函数两者没有区别,但是要注意view()之后之前的维度就没有了,所以要根据自己的需求判断是否要存储之前的维度。
a = torch.rand(6,7,3) print(a.reshape(3,6,7).shape) # torch.Size([3, 6, 7]) print(a.view(2,3,7,3,1).shape) # torch.Size([2, 3, 7, 3, 1])
(2)插入/压缩维度
a.unsqueeze() 函数 / a.squeeze() 函数
unsqueeze()参数范围从0~a.dim()+1
squeeze()只能压缩等于1的维度,若不给参数则压缩所有等于1的维度
# eg1:为[4,32,14,14]张量加上bias a = torch.rand(32) print(a.unsqueeze(0).unsqueeze(2).unsqueeze(3).shape) # torch.Size([1, 32, 1, 1]), 之后再用expand()函数 # eg2:压缩 f = torch.rand(1,32,1,14) print(f.squeeze().shape) # torch.Size([32, 14]), 不给参数,压缩所有等于1的维度 print(f.squeeze(dim=0).shape) # torch.Size([32, 1,14]) print(f.squeeze(dim=1).shape) # torch.Size([1, 32, 1, 14]), 只能压缩等于1的维度
(3)转置
a.t() 函数,a.transpose() 函数,a.permute() 函数
# t()函数 只适用于2D张量 a = torch.rand(32,21) print(a.t().shape) # torch.Size([21, 32]) # transpose(dim1,dim2) 交换dim1和dim2 a = torch.rand(4,3,32,21) print(a.transpose(0,3).shape) # torch.Size([21, 3, 32, 4]) # permute(, 对应a的维度个数a.dim() , ,) 交换任意维度 a = torch.rand(4,3,32,21) print(a.permute(1,0,3,2).shape) # torch.Size([3, 4, 21, 32]) # 把a的第1维放在第0维,第0维放在第一维,以此类推
(4)扩张
a.expand() 函数(推荐):节省内存,更快速。只能为等于1的维度扩张,-1表示维度不变。
a.repeat() 函数:会把所有的维度都真实copy一遍,参数表示在每个维度上copy几次,1表示维度不变,可以随意复制(更自由)
# 接上面,为[4,32,14,14]张量加上bias a = torch.rand(32) b = a.unsqueeze(0).unsqueeze(2).unsqueeze(3) print(b.expand([4,-1,14,14]).shape) # torch.Size([4, 32, 14, 14]), 参数-1表示维度不变 print(b.repeat([4,1,14,14]).shape) # torch.Size([4, 32, 14, 14]), 参数1表示维度不变 print(b.repeat([4,2,14,14]).shape) # torch.Size([4, 64, 14, 14])进阶操作 boardcast机制
当两个维度不同的张量进行运算时,pytorch会自动调用boardcast机制对张量先进行变形再运算。例如需求:一个学校有6个年级,每个年级7个班,每个学生都有3门课程,案例如下
#eg1: 对全校所有学生的所有课程都加5分 a = torch.rand(6,7,3) b = torch.tensor(5) print((a+b).shape) # torch.Size([6, 7, 3]) #eg2: 对学生的每个课程加不同的分数 a = torch.rand(6,7,3) b = torch.rand(1,3) print((a+b).shape) # torch.Size([6, 7, 3]) #eg3: 学校偏心,对每个班的加分不同 a = torch.rand(6,7,3) b = torch.rand(7,1) print((a+b).shape) # torch.Size([6, 7, 3]) #eg4: 极端例子,展示的boardcast机制的使用限制 a = torch.rand(2,1,7,3) b = torch.rand(6,1,3) print((a+b).shape) # torch.Size([2, 6, 7, 3])
如eg4所示,限制有以下两点:
1. 两个张量从最后一维开始,向前匹配
2. 只有某维度的大小是0或者1时,才能进行扩张
(1)合并
torch.cat() 函数,需保证除了合并维度外的其他维度size一致,默认dim=0
a = torch.rand(2,7,4,2) b = torch.rand(2,7,3,2) print(torch.cat([a,b],dim=2).shape) # torch.Size([2, 7, 7, 2])
(2)分割
torch.stack() 函数,保证两个合并张量size完全一致
a = torch.rand(2,7,4,2) b = torch.rand(2,7,4,2) c = torch.stack([a,b],dim=2) print(c.shape) # torch.Size([2, 7, 2, 4, 2]) print(torch.all(torch.eq(c[:,:,0,:,:],a))) # True print(torch.all(torch.eq(c[:,:,1,...],b))) # True数学运算
(1)运算
| 符号 | 运算 |
|---|---|
| + 等价于 torch.add() | 加法 |
| - 等价于 torch.sub() | 减法 |
| * 等价于 torch.mul() | 乘法 |
| / 等价于 torch.div() | 除法 |
| ** | 乘方 |
| @ 等价于 torch.matmul() | 矩阵乘 |
| torch.exp(a) | e a |
| torch.log(a) | ln(a) |
(2)近似
round() 四舍五入,trunc() 截取整数部分,frac() 截取小数部分
a = torch.tensor(3.14159)
print('floor:%f,ceil:%f,round:%f,trunc:%f,frac:%f'%(a.floor(),a.ceil(),a.round(),a.trunc(),a.frac()))
# 输出 floor:3.000000,ceil:4.000000,round:3.000000,trunc:3.000000,frac:0.141590
(3)裁剪
a.clamp(min,max) 函数,保证a的值在min~max之间
a = torch.randint(1,10,[3,4]) print(a) print(a.clamp(5)) print(a.clamp(3,6))
输出:
tensor([[6, 1, 1, 5],
[5, 6, 5, 2]])
tensor([[6, 5, 5, 5],
[5, 6, 5, 5]])
tensor([[6, 3, 3, 5],
[5, 6, 5, 3]])
统计属性
(1) 范数
a.norm(几范数,dim=) 对a的第几维求几范数
a = torch.randint(1,6,[2,3]) # torch.LongTensor
a = a.float() #转为float才能求范数
print(a)
# tensor([[4., 3., 1.],
#[5., 4., 5.]])
print(a.norm(2)) # tensor(9.5917)
print(a.norm(1,dim=0)) # tensor([9., 7., 6.])
这里注意一点,a是2*3的矩阵,dim=0时消掉第0维,也就是获得3列的一范数。(这里我也很晕@@,有时候是对着那一维求解,有时候是消去,应该是需要死记硬背吧,下面介绍的这些统计函数都是消去)
(2)平均、累加乘
a.mean() 平均; a.sum() 累加; a.prod() 累乘
a = torch.randint(1,6,[2,3]) # torch.LongTensor a = a.float() print(a) # tensor([[4., 3., 4.], # [4., 3., 1.]]) print(a.mean(dim=0)) #tensor([4.0000, 3.0000, 2.5000]) print(a.sum(dim=0)) #tensor([8., 6., 5.]) print(a.norm(1,dim=0)) #tensor([8., 6., 5.]) print(a.prod()) #tensor(576.)
NOTE: dim=规则同上
(3)最大最小
a.max() 最大值,a.min() 最小值,a.argmin() 最大值的索引,a.argmax() 最小值的索引,a.tpok() 前k个最大值/最小值,a.kthvalue() 第k个最小的值。
持续更新。。。。



