pytorch的操作对象-张量。加强的numpy矩阵,重点了解内存分配机制广播机制

  • Numpy是支持大量维度数组与矩阵运算的常用扩展库。但是对于计算图,深度学习或者梯度,Numpy似乎真的有心无力,因为它的计算无法像Tensor一样在GPU上加速。Tensors与Numpy中的 ndarrays类似,但是在PyTorch中 Tensors 可以使用GPU进行计算.

  • 在PyTorch中,torch.Tensor是存储和变换数据的主要工具。如果之前用过NumPy,会发现Tensor和NumPy的多维数组非常类似。然而,Tensor提供GPU计算和自动求梯度等更多功能,这些使Tensor更加适合深度学习。

  • "tensor"这个单词一般可译作“张量”,张量可以看作是一个多维数组。标量可以看作是0维张量,向量可以看作1维张量,矩阵可以看作是二维张量

  • 创建一个 5x3 矩阵, 但是未初始化,empty方法创建的矩阵不是空矩阵,而是未初始化的矩阵,所以里面的值不一定是0。

    • import torch
      x = torch.empty(5, 3)  
      print(x,type(x))x)
      

tensor([[0.0000e+00, 0.0000e+00, 0.0000e+00],
[0.0000e+00, 0.0000e+00, 7.3008e-43],
[7.0295e+28, 6.1949e-04, 4.5095e+27],
[7.6831e+31, 4.7429e+30, 1.7053e+28],
[1.6020e-19, 4.4721e+21, 4.4330e+27]]) <class ‘torch.Tensor’>

  • 创建一个随机初始化的矩阵:

    • x = torch.rand(5, 3)
      print(x)
      
tensor([[0.6972, 0.0231, 0.3087],
        [0.2083, 0.6141, 0.6896],
        [0.7228, 0.9715, 0.5304],
        [0.7727, 0.1621, 0.9777],
        [0.6526, 0.6170, 0.2605]])
  • 创建一个0填充的矩阵,数据类型为long:

    • x = torch.zeros(5, 3, dtype=torch.long)
      print(x,type(x),x.dtype))
      

tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]) <class ‘torch.Tensor’> torch.int64

  • 创建tensor并使用现有数据初始化:

    • x = torch.tensor([5.5, 3])
      print(x,type(x),x.dtype))
      

tensor([5.5000, 3.0000]) <class ‘torch.Tensor’> torch.float32

  • 根据现有的张量创建张量。 这些方法将重用输入张量的属性,例如, dtype,除非设置新的值进行覆盖

    • x = x.new_ones(5, 3, dtype=torch.double)      # new_* 方法来创建对象
      print(x,type(x),x.dtype)
      x = torch.randn_like(x, dtype=torch.float)    # 覆盖 dtype!
      print(x,type(x),x.dtype)                      #  对象的size 是相同的,只是值和类型发生了变化)      
      

tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64) <class ‘torch.Tensor’> torch.float64
tensor([[ 0.4735, -1.4062, 0.6846],
[ 2.1270, 1.0104, -0.6296],
[-1.4242, -1.8123, 1.0814],
[-0.8284, -0.2131, 0.8163],
[-0.7036, -0.0401, 0.4185]]) <class ‘torch.Tensor’> torch.float32

  • 加法运算: 【tips:任何 以_ 结尾的操作都会用结果替换原变量. 例如: x.copy_(y), x.t_(), 都会改变 x.】

    • y = torch.rand(5, 3)
      print("随机生成的y",y)
      print("加法结果",x + y)
      res =torch.zeros_like(x)
      torch.add(x, y,out=res)
      print("加法结果",res,res.size())
      y.add_(x)
      print("新y:",y)
      

随机生成的y tensor([[0.0976, 0.0699, 0.3251],
[0.9541, 0.2497, 0.7962],
[0.5003, 0.1983, 0.3777],
[0.4165, 0.2731, 0.6123],
[0.5100, 0.7458, 0.3145]])
加法结果 tensor([[ 0.5710, -1.3363, 1.0097],
[ 3.0812, 1.2601, 0.1666],
[-0.9239, -1.6140, 1.4591],
[-0.4119, 0.0599, 1.4286],
[-0.1937, 0.7057, 0.7329]])
加法结果 tensor([[ 0.5710, -1.3363, 1.0097],
[ 3.0812, 1.2601, 0.1666],
[-0.9239, -1.6140, 1.4591],
[-0.4119, 0.0599, 1.4286],
[-0.1937, 0.7057, 0.7329]]) torch.Size([5, 3])
新y: tensor([[ 0.5710, -1.3363, 1.0097],
[ 3.0812, 1.2601, 0.1666],
[-0.9239, -1.6140, 1.4591],
[-0.4119, 0.0599, 1.4286],
[-0.1937, 0.7057, 0.7329]])

  • 可以使用与NumPy索引方式相同的操作来进行对张量的操作

    • print(x[:, 1])
      print(x[2, :])
      print(x[1:3, 0:2])
      

tensor([-1.4062, 1.0104, -1.8123, -0.2131, -0.0401])
tensor([-1.4242, -1.8123, 1.0814])
tensor([[ 2.1270, 1.0104],
[-1.4242, -1.8123]])

  • torch.view: 可以改变张量的维度和大小,torch.view 与Numpy的reshape类似

    • x = torch.randn(4, 4)
      y = x.view(16)
      z = x.view(-1, 8)  #  size -1 从其他维度推断
      print(x.size(), y.size(), z.size())
      

torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])

  • 使用.item()来得到Python数据类型的数值

    • print(x[0][0])
      print(x[0][0].item())
      

tensor(1.6635)
1.6634777784347534

  • 函数功能
    Tensor(*sizes)基础构造函数
    tensor(data,)类似np.array的构造函数
    ones(*sizes)全1Tensor
    zeros(*sizes)全0Tensor
    eye(*sizes)对角线为1,其他为0
    arange(s,e,step)从s到e,步长为step
    linspace(s,e,steps)从s到e,均匀切分成steps份
    rand/randn(*sizes)均匀/标准分布
    normal(mean,std)/uniform(from,to)正态分布/均匀分布
    randperm(m)随机排列
  • 函数功能
    index_select(input, dim, index)在指定维度dim上选取,比如选取某些行、某些列
    masked_select(input, mask)例子如上,a[a>0],使用ByteTensor进行选取
    nonzero(input)非0元素的下标
    gather(input, dim, index)根据index,在dim维度上选取数据,输出的size与index一样
  • 更多关于tensor的操作可查看官方文档:torch — PyTorch 1.13 documentation

  • # 创建相同元素的Tensor
    torch_tensor1  = torch.full([2,3],2)
    # 创建全为1的Tensor
    torch_tensor2 = torch.ones([2,3])
    # 创建全为0的Tensor
    torch_tensor3 = torch.zeors([2,3])
    # 创建对角阵的Tensor
    torch_tensor4  = torch.eye(3)
    # 在区间[1,10]中随机创建Tensor
    torch_tensor5 = torch.randint(1,10,[2,2])
    
  • tensor与NumPy 转换

    • Torch Tensor与NumPy数组共享底层内存地址,修改一个会导致另一个的变化。将一个Torch Tensor转换为NumPy数组:

    • a = torch.ones(5)
      print(a)
      b = a.numpy()
      print(b)
      b[2]=6
      print(a,b)  
      ############
      tensor([1., 1., 1., 1., 1.])
      [1. 1. 1. 1. 1.]
      tensor([1., 1., 6., 1., 1.]) [1. 1. 6. 1. 1.]   
      ###########
      a.add_(1)
      print(a,type(a),b,type(b))  
      ###########  
      tensor([2., 2., 7., 2., 2.]) <class 'torch.Tensor'> [2. 2. 7. 2. 2.] <class 'numpy.ndarray'>
      
  • NumPy Array 转化成 Torch Tensor,使用from_numpy自动转化

    • import numpy as np
      a = np.ones(5)
      b = torch.from_numpy(a)
      np.add(a, 1, out=a)
      print("a:",a,a.dtype,type(a))
      print("b:",b,b.dtype,type(b))
      a: [2. 2. 2. 2. 2.] float64 <class 'numpy.ndarray'>
      b: tensor([2., 2., 2., 2., 2.], dtype=torch.float64) torch.float64 <class 'torch.Tensor'>
      
    • 直接用torch.tensor()将NumPy数组转换成Tensor该方法总是会进行数据拷贝,返回的Tensor和原来的数据不再共享内存

    • # 用torch.tensor()转换时不会共享内存
      import numpy as np
      a = np.ones((3,2))
      c = torch.tensor(a)
      a += 1
      print(a, c)
      
    • [[2. 2.]
       [2. 2.]
       [2. 2.]] tensor([[1., 1.],
              [1., 1.],
              [1., 1.]], dtype=torch.float64)
      
  • 所有的 Tensor 类型默认都是基于CPU, CharTensor 类型不支持到 NumPy 的转换. CUDA 张量使用.to 方法 可以将Tensor移动到任何设备中。

  • 如果不想共享内存,推荐先用clone创造一个副本然后再使用view

    • x_cp = x.clone().view(15)
      x -= 1
      print(x)
      print(x_cp)
      
    • tensor([[-1., -1., -1.],
              [-1., -1., -1.],
              [-1., -1., -1.],
              [-1., -1., -1.],
              [-1., -1., -1.]])
      tensor([8.9082e-39, 1.0194e-38, 9.1837e-39, 8.4490e-39, 1.0102e-38, 1.0653e-38,
              9.9184e-39, 5.9695e-39, 8.9082e-39, 1.0194e-38, 9.1837e-39, 8.4490e-39,
              1.0102e-38, 1.0561e-38, 9.0918e-39])
      
  • Tensor的广播机制:当对两个形状不同的Tensor按元素运算时,可能会触发广播机制(broadcasting)机制:先适当复制元素使这两个Tensor形状相同后再按元素运算

    • x = torch.arange(1, 3).view(1, 2)
      print(x)
      y = torch.arange(1, 4).view(3, 1)
      print(y)
      print(x + y)
      

tensor([[1, 2]])
tensor([[1],
[2],
[3]])
tensor([[2, 3],
[3, 4],
[4, 5]])

  • tensor运算的内存开销:索引,view()是不会开辟新的内存的,而像y=x+y这样的运算是会开辟新的内存的,然后y指向新的内存。

    • x = torch.tensor([1, 2])
      y = torch.tensor([3, 4])
      id_before = id(y)
      torch.add(x, y, out=y) 
      print(id(y) == id_before)
      y += x          # 与y=y+x不同
      print(id(y) == id_before)
      y.add_(x)
      print(id(y) == id_before)
      y[:] = y + x       # 索引
      print(id(y) == id_before)
      y = y+ x
      print(id(y) == id_before)
      

True
True
True
True
False

  • 另外,PyTorch还支持一些线性函数,这里提一下,免得用起来的时候自己造轮子,具体用法参考官方文档。如下表所示:

    • 函数功能
      trace对角线元素之和(矩阵的迹)
      diag对角线元素
      triu/tril矩阵的上三角/下三角,可指定偏移量
      mm/bmm矩阵乘法,batch的矩阵乘法
      addmm/addbmm/addmv/addr/baddbmm…矩阵运算
      t转置
      dot/cross内积/外积
      inverse求逆矩阵
      svd奇异值分解
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羞儿

写作是兴趣,打赏看心情

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值