张量的广播和科学运算
作为pytorch中执行深度学习的基本数据类型,张量也拥有非常多的数学与运算函数和方法,以及对应的一系列计算规则。在pytorch中,能够作用于tensor的运算被统一称作为算子
- 逐点运算(pointwise ops)对tensor中每个元素执行相同的运算操作
- 规约运算(reduction ops)对某一张两进行操作得出某种总结值
- 比较运算(comparison ops)对多个张量进行比较运算的相关方法
- 谱运算(spectral ops)涉及信号处理傅里叶变化的操作
- BLAS和LAPACK运算 基础线性代数程序集(Basic Linear Algeria Subprograms)和线性代数包(Linear Algeria Package)中定义的、主要用于现行代数科学计算的函数和方法
- 其他运算 其他未被归类的数学运算
一、张量的广播(broadcast)特性
允许不同形状的张量之间进行计算
1.相同形状的张量计算
1 2
| import torch import numpy as np
|
tensor([0, 1, 2])
tensor([0, 2, 4])
tensor([0, 1, 4])
tensor([1, 1, 4])
tensor([nan, 1., 1.])
[0, 1, 2, 0, 1, 2]
2. 不同形状的张量计算
广播的特性是在不同形状的张量进行计算时,一个或多个张量通过隐式转化为相同形状的两个张量,但是,并非任何两个不同形状的张量都可以通过广播特性进行计算
2.1 标量和任意形状的张量
标量可以和任意形状的张量进行计算,计算过程就是标量和张量的每一个元素进行计算
tensor([1, 2, 3])
tensor([0, 2, 4])
tensor([1, 4, 9])
2.2 相同维度、不同形状的计算
1 2
| t2=torch.zeros(3,4) t2.shape
|
torch.Size([3, 4])
1 2
| t3=torch.zeros(3,4,5) t3
|
tensor([[[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]]])
tensor([[1., 1., 1., 1.]])
tensor([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
此处的广播相当于将t21的形状(1,4)拓展成了t2(3,4)
即复制了第一行三次,然后二者相加
也可理解为 t21的第一行和t2的三行分别进行相加
tensor([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
1 2
| t22=torch.arange(9).reshape(3,3) t22
|
tensor([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
torch.Size([3, 3])
torch.Size([3, 4])
广播规则:
- 两个张量在一个维度一致,另一个维度上其中一个张量为1
1 2
| t3=torch.ones(3,1) t3.size()
|
torch.Size([3, 1])
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
- t3的形状为(3,1),t31的形状为(1,3),二者的形状在两个分量上均不同,但都有1存在,因此也可以广播
tensor([[1., 1., 1.]])
tensor([[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]])
三维张量的广播
1 2
| t3=torch.zeros(3,4,5) t3
|
tensor([[[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]],
[[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]]])
1 2
| t31=torch.ones(3,4,1) t31
|
tensor([[[1.],
[1.],
[1.],
[1.]],
[[1.],
[1.],
[1.],
[1.]],
[[1.],
[1.],
[1.],
[1.]]])
tensor([[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]],
[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]],
[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]]])
1 2
| t32=torch.ones(3,1,5) t32
|
tensor([[[1., 1., 1., 1., 1.]],
[[1., 1., 1., 1., 1.]],
[[1., 1., 1., 1., 1.]]])
tensor([[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]],
[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]],
[[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]]])
tensor([[[2., 2., 2., 2., 2.],
[2., 2., 2., 2., 2.],
[2., 2., 2., 2., 2.],
[2., 2., 2., 2., 2.]],
[[2., 2., 2., 2., 2.],
[2., 2., 2., 2., 2.],
[2., 2., 2., 2., 2.],
[2., 2., 2., 2., 2.]],
[[2., 2., 2., 2., 2.],
[2., 2., 2., 2., 2.],
[2., 2., 2., 2., 2.],
[2., 2., 2., 2., 2.]]])
2.3不同维度的张量计算过程中的广播
低维张量升维,只需要将更高维度上填充1即可
1 2
| t2=torch.arange(4).reshape(2,2) t2
|
tensor([[0, 1],
[2, 3]])
tensor([[[0, 1],
[2, 3]]])
tensor([[[[0, 1],
[2, 3]]]])
1 2
| t3=torch.zeros(3,2,2) t3+t2
|
tensor([[[0., 1.],
[2., 3.]],
[[0., 1.],
[2., 3.]],
[[0., 1.],
[2., 3.]]])
tensor([[1.],
[1.]])
1 2
| t3=torch.zeros(3,2,3) t3+t2
|
tensor([[[1., 1., 1.],
[1., 1., 1.]],
[[1., 1., 1.],
[1., 1., 1.]],
[[1., 1., 1.],
[1., 1., 1.]]])
二、逐点运算
tensor基本数学运算
函数 |
描述 |
torch.add(t1,t2) |
t1+t2 |
torch.subtract(t1,t2) |
t1-t2 |
torch.multiply(t1,t2) |
t1*t2 |
torch.divide(t1,t2) |
t1/t2 |
1 2
| t1=torch.tensor([1,2]) t1
|
tensor([1, 2])
1 2
| t2=torch.tensor([3,4]) t2
|
tensor([3, 4])
tensor([4, 6])
tensor([3, 8])
tensor数值调整函数
函数 |
描述 |
torch.abs() |
返回绝对值 |
torch.ceil() |
向上取整 |
torch.floor() |
向下取整 |
torch.round() |
四舍五入 |
torch.neg() |
取反 |
tensor([-0.4222, -2.3513, -2.0652, -0.3838, -0.2116])
tensor([-0., -2., -2., -0., -0.])
tensor([0.4222, 2.3513, 2.0652, 0.3838, 0.2116])
tensor([-0.4222, -2.3513, -2.0652, -0.3838, -0.2116])
数学运算函数 |
数学公式 |
描述 |
幂运算 |
|
|
torch.exp(t) |
$ y_{i} = e^{x_{i}} $ |
返回以e为底、t中元素为幂的张量 |
torch.expm1(t) |
$ y_{i} = e^{x_{i}} $ - 1 |
对张量中的所有元素计算exp(x) - 1 |
torch.exp2(t) |
$ y_{i} = 2^{x_{i}} $ |
逐个元素计算2的t次方。 |
torch.pow(t,n) |
$\text{out}_i = x_i ^ \text{exponent} $ |
返回t的n次幂 |
torch.sqrt(t) |
$ \text{out}{i} = \sqrt{\text{input}{i}} $ |
返回t的平方根 |
torch.square(t) |
$ \text{out}_i = x_i ^ \text{2} $ |
返回输入的元素平方。 |
对数运算 |
|
|
torch.log10(t) |
$ y_{i} = \log_{10} (x_{i}) $ |
返回以10为底的t的对数 |
torch.log(t) |
$ y_{i} = \log_{e} (x_{i}) $ |
返回以e为底的t的对数 |
torch.log2(t) |
$ y_{i} = \log_{2} (x_{i}) $ |
返回以2为底的t的对数 |
torch.log1p(t) |
$ y_i = \log_{e} (x_i $ + 1) |
返回一个加自然对数的输入数组。 |
1
| torch.pow(torch.tensor(2),2)
|
tensor(4)
- tensor的大多数科学运算具有一定的静态性
静态性就是对输入的张量类型有明确的要求,例如部分函数只能输入浮点型张量,而不能输入整形张量
1 2
| t=torch.arange(1,4) t.dtype
|
torch.int64
tensor([1, 2, 3])
tensor([ 2.7183, 7.3891, 20.0855])
tensor([1., 2., 3.])
tensor([ 2.7183, 7.3891, 20.0855])
tensor([ 1.7183, 6.3891, 19.0855])
tensor([1, 4, 9])
tensor([1.0000, 1.4142, 1.7321])
1
| torch.exp(torch.log(t1))
|
tensor([1., 2., 3.])
- 排序运算:sort
在pytorch中,sort函数将同时返回排序结果和对应的索引值的排列
1 2
| t=torch.tensor([1,3,2,4]) t
|
tensor([1, 3, 2, 4])
torch.return_types.sort(
values=tensor([1, 2, 3, 4]),
indices=tensor([0, 2, 1, 3]))
1
| torch.sort(t,descending=True)
|
torch.return_types.sort(
values=tensor([4, 3, 2, 1]),
indices=tensor([3, 1, 2, 0]))
三、规约运算
规约运算指针对某张量进行某种总结,最后得出一个具体总结值的函数。主要包含数据科学领域内的诸多统计分析函数,如均值、极值、方差、中位数函数等等。
函数 |
描述 |
torch.mean(t) |
返回张量均值 |
torch.var(t) |
返回张量方差 |
torch.std(t) |
返回张量标准差 |
torch.var_mean(t) |
返回张量方差和均值 |
torch.std_mean(t) |
返回张量标准差和均值 |
torch.max(t) |
返回张量最大值 |
torch.argmax(t) |
返回张量最大值索引 |
torch.min(t) |
返回张量最小值 |
torch.argmin(t) |
返回张量最小值索引 |
torch.median(t) |
返回张量中位数 |
torch.sum(t) |
返回张量求和结果 |
torch.logsumexp(t) |
返回张量各元素求和结果,适用于数据量较小的情况 |
torch.prod(t) |
返回张量累乘结果 |
torch.dist(t1, t2) |
计算两个张量的闵式距离,可使用不同范式 |
torch.topk(t) |
返回t中最大的k个值对应的指标 |
1 2
| t=torch.arange(10).float() t
|
tensor([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
(tensor(3.0277), tensor(4.5000))
1
| torch.prod(torch.tensor([1,2,3,4]))
|
tensor(24)
- dist计算距离
dist函数可计算闵式距离(闵可夫斯基距离),通过输入不同的p值,可以计算多种类型的距离,如欧式距离,街道距离等。闵可夫斯基距离公式表示如下:
$$D(x,y)=(\sum_{u=1}^{n}{|x_{u}-y_{u}|}^{p} )^{1/p}$$
p取值为2时,计算欧式距离
1 2
| t1=torch.tensor([1.0,2]) t2=torch.tensor([3.0,4])
|
tensor(2.8284)
1
| torch.sqrt(torch.tensor(8.0))
|
tensor(2.8284)
tensor(4.)
- 规约运算的维度
由于规约运算是一个序列返回一个结果,因此若是针对高维张良,则可能指定某维度进行计算。
1 2
| t2=torch.arange(12).float().reshape(3,4) t2
|
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
torch.Size([3, 4])
tensor([12., 15., 18., 21.])
tensor([ 6., 22., 38.])
1 2
| t3=torch.arange(24).float().reshape(2,3,4) t3
|
tensor([[[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]],
[[12., 13., 14., 15.],
[16., 17., 18., 19.],
[20., 21., 22., 23.]]])
torch.Size([2, 3, 4])
tensor([[12., 14., 16., 18.],
[20., 22., 24., 26.],
[28., 30., 32., 34.]])
tensor([[12., 15., 18., 21.],
[48., 51., 54., 57.]])
tensor([[ 6., 22., 38.],
[54., 70., 86.]])
1 2
| t22=torch.randn(3,4) t22
|
tensor([[-0.1265, 0.2807, 0.7180, 0.8772],
[ 1.9022, 0.3509, -0.4520, -2.3835],
[-0.5028, -0.8871, -2.2325, 0.7211]])
torch.return_types.sort(
values=tensor([[-0.1265, 0.2807, 0.7180, 0.8772],
[-2.3835, -0.4520, 0.3509, 1.9022],
[-2.2325, -0.8871, -0.5028, 0.7211]]),
indices=tensor([[0, 1, 2, 3],
[3, 2, 1, 0],
[2, 1, 0, 3]]))
1
| torch.sort(t22,dim=1,descending=True)
|
torch.return_types.sort(
values=tensor([[ 0.8772, 0.7180, 0.2807, -0.1265],
[ 1.9022, 0.3509, -0.4520, -2.3835],
[ 0.7211, -0.5028, -0.8871, -2.2325]]),
indices=tensor([[3, 2, 1, 0],
[0, 1, 2, 3],
[3, 0, 1, 2]]))
四、比较运算
比较运算是一类较为简单的运算类型,和python原生的布尔运算类似,常用于不同张量之间的逻辑运算,最终返回逻辑运算结果(逻辑类型张量)基本比较运算函数如下所示:
函数 |
描述 |
torch.eq(t1,t2) |
等效== |
torch.equal(t1,t2) |
判断两个张量是否是相同的张量 |
torch.gt(t1,t2) |
等效> |
torch.lt(t1,t2) |
等效于< |
torch.ge(t1,t2) |
等效>= |
torch.le(t1,t2) |
等效<= |
torch.ne(t1,t2) |
等效!= |
1 2 3
| t1=torch.tensor([1.0,3,4]) t2=torch.tensor([1.0,2,5]) t1==t2
|
tensor([ True, False, False])
False
tensor([ True, False, False])
tensor([False, False, True])