Broadcasting
自动扩展,先在大维度上扩张,[B,C,H,W]维度大–>小,然后在维度长度为1的地方扩张。
在下图中,在图中③的情况中,A[3,1]先在小维度上1扩张成3横着扩张,B[1,3]在大维度上扩张1变成3竖着扩张所以broadcast相当于是unsqueeze和expand的结合,先在维度上扩张然后在某维度的尺寸上扩张
为什么需要broadcasting
1满足实际需求: 因为希望某个向量可以和某个标量直接相加,省去自己写多个unsqueeze和expand接口的麻烦。
2节省内存计算:如果使用repeat不使用expand接口会将标量[1]扩展成[4,32,8]4328=1024这样扩大内存,broadcasting可以节约内存。
什么时候可以用broadicasting
假设[class,student,score],[4,32,8]4个班级32个学生8门课,每门成绩加5分即一个标量[1],即实现A和B两个不同维度向量的相加,用broadcasting
#可以使用Broadcasting的情况
A:[4,32,14,14]
B:[1,32,1,1] => [4,32,14,14]
-----------------------------------------------------
A:[4,32,14,14]
B:[14,14] => [1,1,14,14] => [4,32,14,14]
#不可以使用Broadcasting的情况
A:[4,32,14,14]
B:[2,32,14,14]
#Dim 0 has dim,can NOT insert and expand to same
#Dim 0 has distinct dim,NOT size 1
合并与分割
cat
torch.cat([a,b],dim=0).shape#[a,b]第一个参数是合并list,第二个参数dim=0是在哪个维度上合并
对于拼接的维度可以不同,但是非cat的维度上必须保持一致
a=torch.rand(4,32,8)
b=torch.rand(5,32,8)
torch.cat([a,b],dim=0).shape
#合并第1维,
#dim需要一样
#不合并的维度需要一样
#out:torch.Size([9, 32, 8])
a1=torch.rand(4,3,32,32)
a2=torch.rand(4,1,32,32)
torch.cat([a1,a2],dim=0).shape
#此时会报错,因为第二维度不一致
#改
a1=torch.rand(4,3,32,32)
a2=torch.rand(4,1,32,32)
torch.cat([a1,a2],dim=1).shape
#out:torch.Size([4, 4, 32, 32])
stack
torch.stack() :两个维度必须一致,会创建一个新的维度。
两个向量进行拼接ab都是[32,8] ,表示ab两个班级32个学生的8门成绩用cat就是[64,8],这样丢失了2个班级的信息用stack就是[2,32,8]创建一个新的维度,但是stack就是必须两个tensor完全一样,cat允许在连接的dim上尺寸不一样
a1 = torch.rand(4,3,16,16)
a2 = torch.rand(4,3,16,16)
torch.stack([a1,a2],dim = 2).shape #torch.Size([4, 3, 2, 16, 16])
a = torch.rand(32,8)
b = torch.rand(32,8)
torch.stack([a,b],dim = 0).shape #torch.Size([2, 32, 8])
a = torch.rand(32,8)
b = torch.rand(30,8)
torch.stack([a,b],dim = 0).shape #RuntimeError: stack expects each tensor to be equal size, but got [32, 8] at entry 0 and [30, 8] at entry 1
split
torch.split() :按长度拆分
c = torch.rand(2,32,8)
aa,bb = c.split([1,1],dim = 0)
aa.shape #torch.Size([1, 32, 8])
bb.shape #torch.Size([1, 32, 8])
aa,bb = c.split(1,dim = 0)
aa.shape #torch.Size([1, 32, 8])
bb.shape #torch.Size([1, 32, 8])
c = torch.rand(6,32,8)
aa,bb,cc = c.split([3,2,1],dim = 0)
aa.shape #torch.Size([3, 32, 8])
bb.shape #torch.Size([2, 32, 8])
cc.shape #torch.Size([1, 32, 8])
aa,bb = c.split(3,dim = 0) #3代表拆分后每个tensor的0维长度为3
aa.shape #torch.Size([3, 32, 8])
bb.shape #torch.Size([3, 32, 8])
chunk
torch.chunk() :按数量拆分
c = torch.rand(2,32,8)
aa,bb = c.chunk(2,dim = 0) #2代表拆分后的tensor数量
aa.shape #torch.Size([1, 32, 8])
bb.shape #torch.Size([1, 32, 8])
aa,bb = c.split(2,dim = 0) #ValueError: not enough values to unpack (expected 2, got 1)