张量的广播和科学运算

文章目录

  • 张量的广播(broadcast)特性
    • 相同形状的张量计算
    • 标量和任意形状的张量
    • 相同维度、不同形状的张量之间计算
    • 不同维度的张量计算过程中广播
  • 逐点运算(Pointwise Ops)
    • 加减乘除
    • Tensor数值调整函数
    • Tensor常用科学计算
  • 规约运算
  • 比较运算


张量的广播(broadcast)特性

相同形状的张量计算

“same shapes are always broadcastable”,相同形状数组总是可以进行广播计算。这里简单强调一下,虽然我们往往觉得不同形状之间的张量计算才是应用到广播特性,但其实相同形状的张量计算,尽管是对应位置元素进行计算,但本质上也是应用到了广播特性。

import torch
t1 = torch.arange(3)   # tensor([0, 1, 2])
t2 = torch.arange(2,5) # tensor([2, 3, 4])
# 对应位置元素依次相加
t1 + t2     # tensor([2, 4, 6])

标量和任意形状的张量

标量可以和任意形状的张量进行计算,计算过程就是标量和张量的每一个元素进行计算。

import torch
t1 = torch.arange(3)   # tensor([0, 1, 2])
# 1是标量,可以看成是零维
t1 + 1                 # tensor([1, 2, 3])
t1 + torch.tensor(1)   # tensor([1, 2, 3])

相同维度、不同形状的张量之间计算

t2的形状是(1, 4),和t1的形状(3, 4)在第一个分量上取值不同,但该分量上t2取值为1,因此可以广播,也就可以进行计算。若该分量上t2取值不为1,则不可进行广播

t1 = torch.zeros(3, 4)
t1.shape   # torch.Size([3, 4])
t2 = torch.ones(1, 4)
t2.shape   # torch.Size([1, 4])
(t1 + t2).shape  # torch.Size([3, 4])

t3的形状是(3, 1),和t1的形状(3, 4)在第二个分量上取值不同,但该分量上t3取值为1,因此可以广播,也就可以进行计算。若该分量上t3取值不为1,则不可进行广播

t1 = torch.zeros((3, 4))
t1.shape   # torch.Size([3, 4])
t3 = torch.ones(3, 1)
t3.shape   # torch.Size([3, 1])
(t1 + t3).shape  # torch.Size([3, 4])

t4的形状是(3, 1),而t5的形状是(1, 3),二者的形状在两个份量上均不相同,但都有存在1的情况,因此也是可以广播的

t4 = torch.arange(3).reshape(3, 1)
print(t4.shape) # torch.Size([3, 1])
t5 = torch.arange(3).reshape(1, 3)
print(t5.shape) # torch.Size([1, 3])
(t4 + t5).shape # torch.Size([3, 3])

不同维度的张量计算过程中广播

对于不同维度的张量,我们首先可以将低维的张量升维,然后依据相同维度不同形状的张量广播规则进行广播。

t6 = torch.arange(6).reshape(3, 2)
print(t6.shape)   # torch.Size([3, 2])
t7 = torch.arange(7,9)
print(t7.shape)   # torch.Size([2])
(t6 + t7).shape   # torch.Size([3, 2])

逐点运算(Pointwise Ops)

逐点运算(Pointwise Ops):指的是针对Tensor中每个元素执行的相同运算操作;

加减乘除

函数 描述
torch.add(t1,t2 ) t1、t2两个张量逐个元素相加,等效于t1+t2
torch.subtract(t1,t2) t1、t2两个张量逐个元素相减,等效于t1-t2
torch.multiply(t1,t2) t1、t2两个张量逐个元素相乘,等效于t1*t2
torch.divide(t1,t2) t1、t2两个张量逐个元素相除,等效于t1/t2
t1 = torch.tensor([1, 2]) # tensor([1, 2])
t2 = torch.tensor([3, 4]) # tensor([3, 4])
torch.add(t1, t2)         # tensor([4, 6])
t1 + t2                   # tensor([4, 6])

Tensor数值调整函数

函数 描述
torch.abs(t) 返回绝对值
torch.ceil(t) 向上取整
torch.floor(t) 向下取整
torch.round(t) 四舍五入取整
torch.neg(t) 返回相反的数
torch.manual_seed(123)
t = torch.randn(5) # tensor([-0.1115,  0.1204, -0.3696, -0.2404, -1.1969])
torch.abs(t)       # tensor([0.1115, 0.1204, 0.3696, 0.2404, 1.1969])

注:虽然此类型函数是数值调整函数,但并不会对原对象进行调整,而是输出新的结果。
而若要对原对象本身进行修改,则可考虑使用方法_()的表达形式,对对象本身进行修改。此时方法就是上述同名函数。

torch.manual_seed(123)
t = torch.randn(5) # tensor([-0.1115,  0.1204, -0.3696, -0.2404, -1.1969])
t.abs_()       # tensor([0.1115, 0.1204, 0.3696, 0.2404, 1.1969])
t.exp_()   # tensor([1.1179, 1.1279, 1.4472, 1.2718, 3.3099])

Tensor常用科学计算

tensor的大多数科学计算只能作用于tensor对象

数学运算函数 数学公式 描述
幂运算
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) 返回一个加自然对数的输入数组。
torch.pow(torch.tensor(2), 2) #tensor(4)
t = torch.arange(1, 4).float()
t.dtype  # torch.float32
torch.exp(t) # tensor([ 2.7183,  7.3891, 20.0855])
torch.exp(torch.log(t)) # tensor([1., 2., 3.])

规约运算

规约运算指的是针对某张量进行某种总结,最后得出一个具体总结值的函数。此类函数主要包含了数据科学领域内的诸多统计分析函数,如均值、极值、方差、中位数函数等等。

函数 描述
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个值对应的指标
# 生成浮点型张量
t = torch.arange(10).float()
# 计算均值
torch.mean(t) # tensor(4.5000)
# 计算标准差、均值
torch.std_mean(t) # (tensor(3.0277), tensor(4.5000))
# 计算最大值
torch.max(t)   # tensor(9.)
# 返回最大值的索引
torch.argmax(t) # tensor(9)
# 求和
torch.sum(t)   # tensor(45.)

dist函数可计算闵式距离(闵可夫斯基距离),通过输入不同的p值,可以计算多种类型的距离,如欧式距离、街道距离等。

t1 = torch.tensor([1.0, 2])
t2 = torch.tensor([3.0, 4])
torch.dist(t1, t2, 2)  # 计算欧式距离
torch.dist(t1, t2, 1)  # 计算街道距离

由于规约运算是一个序列返回一个结果,因此若是针对高维张量,则可指定某维度进行计算。

# 按照第一个维度求和(每次计算三个)、按列求和
t2 = torch.arange(12).float().reshape(3, 4)
torch.sum(t2, dim = 0) # tensor([12., 15., 18., 21.])
# 按照第二个维度求和(每次计算四个)、按行求和
torch.sum(t2, dim = 1) # tensor([ 6., 22., 38.])

比较运算

比较运算是一类较为简单的运算类型,和Python原生的布尔运算类似,常用于不同张量之间的逻辑运算,最终返回逻辑运算结果(逻辑类型张量)。

函数 描述
torch.eq(t1, t2) 比较t1、t2各元素是否相等,等效==
torch.equal(t1, t2) 判断两个张量是否是相同的张量
torch.gt(t1, t2) 比较t1各元素是否大于t2各元素,等效>
torch.lt(t1, t2) 比较t1各元素是否小于t2各元素,等效<
torch.ge(t1, t2) 比较t1各元素是否大于或等于t2各元素,等效>=
torch.le(t1, t2) 比较t1各元素是否小于等于t2各元素,等效<=
torch.ne(t1, t2) 比较t1、t2各元素是否不相同,等效!=
t1 = torch.tensor([1.0, 3, 4])
t2 = torch.tensor([1.0, 2, 5])
t1 == t2  # tensor([ True, False, False])
# 判断t1、t2是否是相同的张量
torch.equal(t1, t2)  # False 
torch.eq(t1, t2) # tensor([ True, False, False])
t1 > t2          # tensor([False,  True, False])

你可能感兴趣的:(Pytorch基础)