Broadcast机制
如果满足以下规则,则两个张量是“可广播的”:
1、每个张量具有至少一个维度。
2、从尾部开始迭代张量时,对应维度的长度要么相等,要么其中一个维度的长度为1,或者不存在。
如果张量x和y可以符合广播的条件,那么:结果张量可以按照下面的方式计算:
1、如果x和y的维度不相同,用1来扩张维度少的那个,使两个张量维度一致。
2、对于每个维度,结果维度是x,y对应维度的最大值。
值得注意的是,通过broadcast扩张的张量在扩张时并不会进行复制,这节省了内存空间
a = torch.rand(5,1,4,1)
b = torch.rand(3,1,1)
print((a+b).shape)
c = torch.rand(1)
d = torch.rand(3,1,7)
print((c+d).shape)
输出
torch.Size([5, 3, 4, 1])
torch.Size([3, 1, 7])
拼接与拆分
cat
在指定的维数进行合并,要求其余维度的长度相同
a = torch.rand(4,3,28,28)
b = torch.rand(5,3,28,28)
print(torch.cat([a,b],0).shape)
输出
torch.Size([9, 3, 28, 28])
stack
在指定的维数进行合并,新生成的张量在指定位置增加一个长度为2的维度,其余维度后移,要求两个张量的shape相同
a = torch.rand(4,3,28,28)
b = torch.rand(4,3,28,28)
print(torch.stack([a,b],1).shape)
print(torch.stack([a,b],3).shape)
输出
torch.Size([4, 2, 3, 28, 28])
torch.Size([4, 3, 28, 2, 28])
split
有两种用法
1.按分配的好的长度在指定的维度上进行分割,可以有多个张量,长度的参数个数要和张量个数相应,且长度之和要和维度的长度相同
c, d, e, f = b.split([2,3,1,2],0)
print(c.shape)
print(d.shape)
print(e.shape)
print(f.shape)
输出
torch.Size([2, 3, 28, 28])
torch.Size([3, 3, 28, 28])
torch.Size([1, 3, 28, 28])
torch.Size([2, 3, 28, 28])
2.按统一的长度在指定的维度上进行均分,可以有多个张量,张量个数和均分的长度相乘的值要和指定维度的长度相同
a = torch.rand(4,3,28,28)
b = torch.rand(8,3,27,28)
c, d = a.split(2,0)
e, f, g = b.split(9,2)
print(c.shape)
print(d.shape)
print(e.shape)
print(f.shape)
print(g.shape)
输出
torch.Size([2, 3, 28, 28])
torch.Size([2, 3, 28, 28])
torch.Size([8, 3, 9, 28])
torch.Size([8, 3, 9, 28])
torch.Size([8, 3, 9, 28])
chunk
在指定的维度上按照张量的个数进行均分,当指定维度的长度不是指定个数的倍数时,会找比这个长度大的最小倍数然后再进行分配
a = torch.rand(4,3,28,29)
b = torch.rand(8,3,27,28)
c, d = a.chunk(2,2)
e, f, g = b.chunk(3,3)
print(c.shape)
print(d.shape)
print(e.shape)
print(f.shape)
print(g.shape)
输出
torch.Size([4, 3, 14, 29])
torch.Size([4, 3, 14, 29])
torch.Size([8, 3, 27, 10])
torch.Size([8, 3, 27, 10])
torch.Size([8, 3, 27, 8])
Tensor运算
基础的数乘
张量之间可以直接使用加减乘除符号(+,-,*,/)进行运算,值得注意的是,这种运算是数乘,且张量之间如果满足Broadcast机制,也可以进行基础运算。也可以使用torch.add(),torch.sub(),torch.mul(),torch.div()来进行运算,结果是一样的。
f = torch.full([2,2],2)
g = torch.full([2,2],3)
h = torch.full([2],8)
print(f+g)
print(f-g)
print(f*g)
print(h/f)
输出
tensor([[5, 5],
[5, 5]])
tensor([[-1, -1],
[-1, -1]])
tensor([[6, 6],
[6, 6]])
tensor([[4., 4.],
[4., 4.]])
matmul
这种乘法是矩阵相乘,torch.mm()仅限二维,torch.matmul()可以适用于多维,所以不管是哪种维度,都推荐使用matmul(),可以直接使用运算符号@
代替matmul。不同维度的张量相乘时,Broadcast机制同样也适用,且多维的张量进行matmul运算时,只会在最后的两个维度进行。
a = torch.rand(4,3,28,64)
b = torch.rand(1,64,32)
print(torch.matmul(a,b).shape)
print((a @ b).shape)
输出
torch.Size([4, 3, 28, 32])
torch.Size([4, 3, 28, 32])
tensor的平方、开方运算
tensor的平方、开放运算也是类似与数乘,和矩阵相乘不同。Tensor.pow(x)和Tensor**x等价,都是Tensor的x次方运算。
Tensor.sqrt()是开方运算,Tensor.rsqrt()是先开方再取倒数。
f = torch.full([2,2],2)
g = torch.full([2,2],9)
print(f.pow(3))
print(f**3)
print(g.sqrt())
print(g.rsqrt())
输出
tensor([[8, 8],
[8, 8]])
tensor([[8, 8],
[8, 8]])
tensor([[3., 3.],
[3., 3.]])
tensor([[0.3333, 0.3333],
[0.3333, 0.3333]])
Exp Log
Exp运算也是与矩阵数乘类似,与矩阵乘法不同,torch.exp()是张量乘以无理数e,torch.log()是张量进行log运算,默认是以e为底
a = torch.exp(torch.ones(2,2,2))
print(a)
print(torch.log(a))
输出
tensor([[[2.7183, 2.7183],
[2.7183, 2.7183]],
[[2.7183, 2.7183],
[2.7183, 2.7183]]])
tensor([[[1., 1.],
[1., 1.]],
[[1., 1.],
[1., 1.]]])
近似值
.floor()是向下取整,.ceil()是向上取整,.round()是四舍五入,.trunc()是整数部分,.frac()是小数部分
a = torch.tensor(3.14)
print(a.floor(),a.ceil(),a.trunc(),a.frac())
b = torch.tensor(3.499)
print(b.round())
c = torch.tensor(3.5)
print(c.round())
输出
tensor(3.) tensor(4.) tensor(3.) tensor(0.1400)
tensor(3.)
tensor(4.)
Clamp
clamp(min)是让张量内小于min的值为min,clamp(min,max)是让张量内的值小于min的为min,大于max的为max。
grad = torch.rand(2,3) * 15
print(grad)
print(grad.clamp(10))
print(grad.clamp(5,12))
输出
tensor([[14.6030, 9.7245, 7.8587],
[ 6.0906, 4.5278, 4.5055]])
tensor([[14.6030, 10.0000, 10.0000],
[10.0000, 10.0000, 10.0000]])
tensor([[12.0000, 9.7245, 7.8587],
[ 6.0906, 5.0000, 5.0000]])
Tensor统计
求范数
pytorch中的torch.norm主要用于计算矩阵和向量的p范数,具体的用法如下所示:
torch.norm(input, p=‘fro’, dim=None, keepdim=False, out=None, dtype=None)
- input (Tensor):
输入的张量,数据类型必须是浮点型或复杂输入。对于复杂输入,使用每个元素的绝对值计算范数。如果输入很复杂,并且未指定dtype或out,则结果的数据类型将是相应的浮点类型 - p (int, float, inf, -inf, ‘fro’,‘nuc’, optional):
表示指定的范数,其中默认类型’fro’为Frobenius范数,'nuc’表示矩阵的核范数 - dim (int, tuple of python:ints, list of python:ints, optional):
指定要计算范数的输入维度。如果dim为None,则将在输入的所有维度上计算范数。 - keepdim (bool, optional): 输出的张量是否保持不变,默认值是False,如果dim = None和out =
None,则该参数会被省略掉 - out (Tensor, optional): 输出的张量,如果dim = None和out = None,则该参数会被省略掉
- dtype (torch.dtype, optional):
返回的张量的所需数据类型。如果指定,则在执行操作时将输入张量转换为dtype。默认值是None
求统计值
min()求最小值, max()求最大值, mean()求平均值, sum求总和, prod()求累乘
argmin()求最小值的索引, argmax()求最大值的索引
a = torch.arange(8).view(2,4).float()
print(a)
print(a.min(),a.max(),a.mean(),a.prod(),a.sum())
print(a.argmax(),a.argmin())
输出
tensor([[0., 1., 2., 3.],
[4., 5., 6., 7.]])
tensor(0.) tensor(7.) tensor(3.5000) tensor(0.) tensor(28.)
tensor(7) tensor(0)
对于min()和max()以及argmin()和argmax()还可以通过dim和keepdim这两个参数控制输出
a = torch.arange(15).view(3,5).float()
print(a)
print(a.max(0,True))
print(a.argmax(0,True))
print(a.max(1,True))
print(a.argmin(1,True))
输出
tensor([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[10., 11., 12., 13., 14.]])
torch.return_types.max(
values=tensor([[10., 11., 12., 13., 14.]]),
indices=tensor([[2, 2, 2, 2, 2]]))
tensor([[2, 2, 2, 2, 2]])
torch.return_types.max(
values=tensor([[ 4.],
[ 9.],
[14.]]),
indices=tensor([[4],
[4],
[4]]))
tensor([[0],
[0],
[0]])
求多个最值
通过topk()可以求最大的几个值或者最小的几个值,通过kthvalue可以求第几大的值
比较
张量可以通过>, >=, <, <=, !=, ==这几个运算符进行比较,返回的是布尔值0或1
torch.eq()比较的是两个张量,返回的是张量形状的布尔值
torch.equal()直接返回的是两个张量是否完全相等
Tensor高阶操作
Where
利用两个张量通过torch.where(condition, x, y)生成新的张量,根据condition的布尔张量决定取哪个张量的值生成新的张量
如果是1则选取x的值,如果是0则选取y的值
condition = torch.tensor([[0.6897,0.7271],
[0.8884,0.4163]])
a = torch.tensor([[0.,0.],
[0.,0.]])
b = torch.tensor([[1.,1.],
[1.,1.]])
print(torch.where(condition > 0.5,a,b))
输出
tensor([[0., 0.],
[0., 1.]])
gather
gather其实是对input的一种映射,index必须是LongTensor类型
b = torch.tensor([[1,2,3],[4,5,6]])
print(b)
index_1 = torch.LongTensor([[0,1],[2,0]])
index_2 = torch.LongTensor([[0,1,1],[0,0,0]])
print(torch.gather(b, dim=1, index=index_1))
print(torch.gather(b, dim=0, index=index_2))
输出
tensor([[1, 2, 3],
[4, 5, 6]])
tensor([[1, 2],
[6, 4]])
tensor([[1, 5, 6],
[1, 2, 3]])
-------------完-------------