PyTorch——Tensor的介绍(三)in-place操作和广播机制和运算

489 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情


上一篇文章中,我们介绍了pytorch的属性和算术运算。

今天,我们来介绍pytorch中的in-place操作和广播机制、取整/取余运算、比较运算、三角函数和其他数学函数


  • 3.1 操作和广播机制

    • 3.1.1 in-place操作
      • “就地”操作,即不允许使用临时变量。
      • 也称为原位操作。
      • x=x+y
      • add_,sub_,mul_等
    • 3.1.2 广播机制
      • 张量参数可以自动扩展为相同大小
      • 广播机制需要满足两个条件
        • 每个张量至少有一个维度
        • 满足右对齐
        • 例子:torch.rand(2,1,1)+torch.rand(3);对3进行补1,补完之后就是(1,1,3),看是否满足右对齐,从右向左看,如果对应的维度上它的值满足两个条件,要么相等,要么等于1,那么就满足右对齐。因为前面是补1,所以前面的一定是对齐的,而最后一个维度有一个=1.
a = torch.rand(2, 3)
b = torch.rand(3)

# a, 2*3
# b, 1*3
# c, 2*3
c = a + b
print(a)
print(b)
print(c)
print(c.shape)

运行结果:

tensor([[0.8919, 0.5506, 0.2826],
        [0.3355, 0.3600, 0.7230]])
tensor([0.4779, 0.1849, 0.9695])
tensor([[1.3697, 0.7356, 1.2521],
        [0.8134, 0.5450, 1.6925]])
torch.Size([2, 3])

如果b的维度改成2,则是无法进行相加的

b = torch.rand(2)

运行结果:

The size of tensor a (3) must match the size of tensor b (2) at non-singleton dimension 1

广播机制可以简化编程的流程。

  • 3.2 Tensor的取整/取余运算

    • .floor() 向下取整数
    • .ceil() 向上取整数
    • .round() 四舍五入 >=0.5 向上取整,<0.5向下取证
    • .trunc() 裁剪,只取整数部分
    • .frac() 只取小数部分
    • % 取余
a = torch.rand(2, 2)
a = a * 10
print(a)

print(torch.floor(a))
print(torch.ceil(a))
print(torch.round(a))
print(torch.trunc(a))
print(torch.frac(a))
print(a % 2)

运行结果:

tensor([[7.5668, 8.6525],
        [7.1386, 4.5063]])
tensor([[7., 8.],
        [7., 4.]])
tensor([[8., 9.],
        [8., 5.]])
tensor([[8., 9.],
        [7., 5.]])
tensor([[7., 8.],
        [7., 4.]])
tensor([[0.5668, 0.6525],
        [0.1386, 0.5063]])
  • 3.3 Tensor的比较运算

2.png 3.png 4.png

a = torch.rand(2, 3)
b = torch.rand(2, 3)

print(a)
print(b)

print(torch.eq(a, b))
print(torch.equal(a, b))

print(torch.ge(a, b))
print(torch.gt(a, b))
print(torch.le(a, b))
print(torch.lt(a, b))
print(torch.ne(a, b))

运行结果:

tensor([[0.5013, 0.5989, 0.0065],
        [0.3775, 0.7701, 0.2574]])
tensor([[0.8954, 0.8053, 0.0653],
        [0.8692, 0.3829, 0.0577]])
tensor([[False, False, False],
        [False, False, False]])
False
tensor([[False, False, False],
        [False,  True,  True]])
tensor([[False, False, False],
        [False,  True,  True]])
tensor([[ True,  True,  True],
        [ True, False, False]])
tensor([[ True,  True,  True],
        [ True, False, False]])
tensor([[True, True, True],
        [True, True, True]])

其中,a,b的shape必须是一样的,否则无法进行比较

a = torch.tensor([[1, 4, 4, 3, 5],
                  [2, 3, 1, 3, 5]])
print(a.shape)
print(torch.sort(a, dim=1,
                 descending=False))

运行结果:

torch.Size([2, 5])
torch.return_types.sort(
values=tensor([[1, 3, 4, 4, 5],
        [1, 2, 3, 3, 5]]),
indices=tensor([[0, 3, 1, 2, 4],
        [2, 0, 1, 3, 4]]))

topk的操作:

a = torch.tensor([[2, 4, 3, 1, 5],
                  [2, 3, 5, 1, 4]])
print(a.shape)

print(torch.topk(a, k=2, dim=1, largest=False))

运行结果:

torch.Size([2, 5])
torch.return_types.topk(
values=tensor([[1, 2],
        [1, 2]]),
indices=tensor([[3, 0],
        [3, 0]]))

返回指定维度上的第k个最小值

print(torch.kthvalue(a, k=2, dim=0))
print(torch.kthvalue(a, k=2, dim=1))

运行结果:

torch.return_types.kthvalue(
values=tensor([2, 4, 5, 1, 5]),
indices=tensor([1, 0, 1, 1, 0]))
torch.return_types.kthvalue(
values=tensor([2, 2]),
indices=tensor([0, 0]))

判断是否有界:

a = torch.rand(2, 3)
print(a)
print(a/0)
print(torch.isfinite(a))
print(torch.isfinite(a/0))
print(torch.isinf(a/0))
print(torch.isnan(a))

运行结果:

tensor([[0.9258, 0.2591, 0.1212],
        [0.0824, 0.1743, 0.1271]])
tensor([[inf, inf, inf],
        [inf, inf, inf]])
tensor([[True, True, True],
        [True, True, True]])
tensor([[False, False, False],
        [False, False, False]])
tensor([[True, True, True],
        [True, True, True]])
tensor([[False, False, False],
        [False, False, False]])

定义一个存在None的情况,采用numpy来定义,判断是否是空

import numpy as np
a = torch.tensor([1, 2, np.nan])
print(torch.isnan(a))

None也是我们在数据处理的时候经常遇到的数据,这就是我们所谓的脏数据,所以我们在进行脚本清洗的时候,也经常会处理到这样的数据

tensor([False, False,  True])
  • 3.4 Tensor的三角函数

5.png

例子:

a = torch.zeros(2, 3)
b = torch.cos(a)
print(a)
print(b)

运行结果:

tensor([[0., 0., 0.],
        [0., 0., 0.]])
tensor([[1., 1., 1.],
        [1., 1., 1.]])
  • 3.5 Tensor的其他数学函数

6.png

  • 其中abs(绝对值)、sigmoid、sign(符号)函数是要进行深度学习必须要掌握的函数

  • 符号函数可以类比来看分段函数,x<0,等于-1,x=0,等于0,x>0,等于1.可以用来表示分类问题,但是没有办法进行求导和优化,

  • 所以有了sigmoid函数,当x无限趋近于无穷小的时候,逼近于0,当x无限趋近于无穷大的时候,无限趋近于1.

    • 通过sigmoid函数,我们的数据会被无限映射到0和1之间去,
    • 可以发现,对于sigmoid函数,它的值域大多数会分布在0和1这两条线的附近,而0和1中间的对应的值是比较少的,
    • 从函数外观上来看,和符号函数的是非常相似的,所以也称sigmoid函数是符号函数的一种连续化的逼近
    • 我们可以使用sigmoid来代替sign,进而来完成对函数的求导,通过求导就能求解最优化问题,
    • 对于sigmoid也称为激活函数。sigmoid经常被用于二分类问题当中。

9JQ4ZCQY3M({Q$KEN%9BFQX.png