1、索引与切片
各种常见索引
=====Indexing
a = torch.rand(4, 3, 28, 28)
a[0].shape ==> torch.size([3,28,28])
a[0,0].shape ==> torch.size([28,28])
a[0, 0, 2, 4] ==> 标量tensor(0.8082)
=====select first/last n
设a.shape ==> torch.size([4, 3, 28, 28])
则a[:2].shape ==> torch.size([2, 3, 28, 28])
a[:2, 1:,:,:] ==> torch.size([2, 2, 28, 28])
a[:2, -1:,:,:] ==> torch.size([2, 1, 28, 28])
[a, b, c]从前往后下标为0 1 2 或者 -3 -2 -1.
-1:相当于从最后一个开始直到最后,那就只有最后一个
===特殊:select by steps
a[:,:, ::2, ::2]==>torch.size([4, 3, 14, 14]) 相当于每隔一点采样一次
===特殊:··· 可以省略任意长度
a[...,:2] ==> torch.size([4, 3, 28, 2])
===小结:冒号":"的通用形式 ==> start:end:step
=====select by specific index
设a.shape ==> torch.size([4, 3, 28, 28])
a.index_select(0, torch.tensor([0,2])):从第0维(batch)选择第0和第2个batch
=====select by mask
x = torch.randn(3,4)
mask = x.ge(0.5):用于挑选元素值大于等于0.5的,设为1,其余为0(mask:掩码)
torch.masked_select(x,mask)得到一维张量,元素为x中大于0.5的
=====select by flatten index
src = torch.tensor([[4, 3, 5],
[6, 7, 8]])
torch.take(src, torch.tensor([0, 2, 5])) ==> tensor([4,5,8])
作用方式:先打平成一维张量,然后取序号为0、2、5的元素
2、维度变换
2.1 常用操作
=====View/reshape
a = torch.rand(4,1,28,28)
a.view(4,28*28) ==> torch.size([4,784])
这种操作会丢失维度信息
=====Squeeze/unsqueeze
挤压
a.shape ==> torch.size([1, 32, 1, 1])
a.squeeze().shape ==> torch.size([32])
a.squeeze(0).shape ==> torch.size([32, 1, 1])
a.squeeze(1).shape ==> torch.size([1, 32, 1, 1])
只能挤压维度值为1的,如果不指定,则把是1的全部挤压。
伸展
a.shape ==> torch.size([4, 3, 28, 28])
a.unsqueeze(4).shape ==> torch.size([4,3,28,28,1])
可以插入范围:[-a.dim-1, a.dim+1)
=====Transpose/t/permute
transpose维度交换
a.shape ==> torch.size([4, 3, 32,32])
a1 = a.transpose(1,3).contiguous().view(4,3*32*32).view(4,3,32,32)
此种方式错误,经过1,3交换后,channel和width换了位置,所以c为第四维,直接让第二维的数为c,造成数据污染
a2 = a.transpose(1,3).contiguous().view(4,3*32*32).view(4,32,32,3).transpose(1,3)
正确
.t()矩阵转置
a = torch.randn(3,4)
a.t() ⇒ 矩阵变为(4,3)
只能用于二维张量
permute直接定义交换后位置
原来bchw
b.permute(0,2,3,1)后变成,bhwc
=====Expand(推荐)/repeat
expand:不会复制数据,速度更快
使用要求:输入和输出同维,只能由1-->N,不能由某个大于1的数expand
a.shape ==> torch.size([1, 32, 1, 1])
a.expand(4,32,14,14).shape ⇒ torch.size([4,32,14,14])
a.expand(-1,32,-1,-1).shape => torch.size([1,32,1,1]) 输入-1代表该维不变
repeat:复制数据
作用效果:乘积方式
a.shape ==> torch.size([1, 32, 1, 1])
a.repeat(4,1,32,32).shape ⇒ torch.size([4,32,32,32])
3、Broadcasting(自动过程,不需要显式使用)
1.1 产生原因
- 高维张量与标量相加,需要繁琐操作将标量扩张到与张量同维才可
- 且扩张会占用大量内存
- broadcasting解决该问题,使得高维张量和标量可以直接相加
1.2 使用规则
https://blog.csdn.net/zhuguiqin1/article/details/119993272[例子]
- 1、同维情况,直接扩展
A.shape : [4,32,14,14]
B.shape : [1,32,1,1]
对于B的Broadcasting过程是直接expand到 [4,32,14,14] - 2、不同维度,从最后开始扩展
A.shape : [4,32,14,14]
B.shape : [14,14]
对于B的Broadcasting过程是先unsqueeze插入新的维度变成 [1,1,14,14],再expand新的维度成[4,32,14,14] - 3、如果对应维度,两者值不同且都不为1,则不能使用