• 【PyTorch】PyTorch基础知识——张量


    一、张量简介

    张量是基于向量和矩阵的推广,其对应关系如下表所示:

    张量维度含义
    0维标量
    1维向量
    2维矩阵
    3维时间序列数据 股价 文本数据 单张彩色图片(RGB)

    其本质是一个数据容器,一些常见数据类型与张量的对应关系如下:

    • 3维 = 时间序列
    • 4维 = 图像
    • 5维 = 视频

    例如,一个图像可以用三个字段表示:

    (width, height, channel) = 3D

    但是,在机器学习工作中,我们经常要处理不止一张图片或一篇文档——我们要处理一个集合。我们可能有10,000张郁金香的图片,这意味着,我们将用到4D张量:

    (batch_size, width, height, channel) = 4D

    在PyTorch中, torch.Tensor 是存储和变换数据的主要工具。Tensor 和NumPy的多维数组非常类似,但Tensor 提供GPU计算和自动求梯度等更多功能,使其更加适合深度学习。

    二、实战

    2.1 创建tensor

    方法一:随机初始化矩阵
    torch.rand

    import torch
    x = torch.rand(4, 3) 
    print(x)
    
    >>tensor([[0.7575, 0.2039, 0.5049],
            [0.9079, 0.9716, 0.3000],
            [0.6575, 0.4854, 0.1494],
            [0.5582, 0.1834, 0.8660]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    方法二:构造全0矩阵
    我们可以通过torch.zeros()构造一个矩阵全为 0,并且通过dtype设置数据类型为 long。除此以外,我们还可以通过torch.zero_()torch.zeros_like()将现有矩阵转换为全0矩阵。

    x = torch.zeros(4, 3, dtype=torch.long)
    print(x)
    
    >>tensor([[0, 0, 0],
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    x = torch.rand(4, 3) 
    print(torch.zeros_like(x))
    
    >>tensor([[0., 0., 0.],
            [0., 0., 0.],
            [0., 0., 0.],
            [0., 0., 0.]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    方法三:直接使用数据构建

    x = torch.tensor([5.5, 3]) 
    print(x)
    
    >>tensor([5.5000, 3.0000])
    
    • 1
    • 2
    • 3
    • 4

    方法四:基于存在的tensor创建tensor

    x = torch.ones(4, 3, dtype=torch.double)
    # 创建一个全1,数据类型为double的tensor
    x = torch.randn_like(x, dtype=torch.float)
    # 随机生成tensor并重置数据类型
    print(x)
    # 结果会有一样的size
    # 获取它的维度信息
    print(x.size())
    print(x.shape)
    print("tensor length:"+str(x.shape[0]))
    print("tensor width:"+ str(x.shape[1]))
    
    >>tensor([[ 1.4150, -0.4839, -0.2232],
            [-1.3060,  0.5646, -0.0978],
            [-0.2836, -2.3955,  0.9513],
            [-0.0435, -0.0328, -0.2242]])
    torch.Size([4, 3])
    torch.Size([4, 3])
    tensor length:4
    tensor width:3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    常见的tensor构造方法,如下表所示:

    函数功能
    Tensor(sizes)基础构造函数
    tensor(data)类似于np.array
    ones(sizes)全1
    zeros(sizes)全0
    eye(sizes)对角为1,其余为0
    arange(s,e,step)从s到e,步长为step
    linspace(s,e,steps)从s到e,均匀分成step份
    rand/randn(sizes)rand是[0,1)均匀分布;randn是服从N(0,1)的正态分布
    normal(mean,std)正态分布(均值为mean,标准差是std)
    randperm(m)随机排列

    2.2 张量的操作

    1. 加法

    # 方式1
    y = torch.rand(4, 3) 
    print(x + y)
    
    # 方式2
    print(torch.add(x, y))
    
    # 方式3 in-place,原值修改
    y.add_(x) 
    print(y)
    
    >>tensor([[ 2.2148, -0.0407,  0.7405],
            [-0.8507,  1.3077,  0.1737],
            [-0.2455, -1.7526,  1.2445],
            [ 0.0583,  0.7089,  0.5562]])
    tensor([[ 2.2148, -0.0407,  0.7405],
            [-0.8507,  1.3077,  0.1737],
            [-0.2455, -1.7526,  1.2445],
            [ 0.0583,  0.7089,  0.5562]])
    tensor([[ 2.2148, -0.0407,  0.7405],
            [-0.8507,  1.3077,  0.1737],
            [-0.2455, -1.7526,  1.2445],
            [ 0.0583,  0.7089,  0.5562]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    2. 索引

    x = torch.rand(4,3)
    # 取第二列
    print(x[:, 1]) 
    
    >>tensor([0.6757, 0.8069, 0.4068, 0.3438])
    
    • 1
    • 2
    • 3
    • 4
    • 5

    需要注意的是:索引出来的结果与原数据共享内存,修改一个,另一个会跟着修改。如果不想修改,可以考虑使用copy()等方法。

    y = x[0,:]
    print(y)
    y += 1
    print(y)
    print(x[0, :]) # 源tensor也被改了了
    >> tensor([0.5997, 0.6757, 0.7756])
    tensor([1.5997, 1.6757, 1.7756])
    tensor([1.5997, 1.6757, 1.7756])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3. 维度变换

    张量的维度变换常见的方法有torch.view()torch.reshape(),下面我们将介绍第一种方法torch.view()

    x = torch.randn(4, 4)
    y = x.view(16)
    z = x.view(-1, 8) # -1是指这一维的维数由其他维度决定
    print(x.size(), y.size(), z.size())
    
    >> torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注: torch.view() 返回的新tensor与源tensor共享内存(其实是同一个tensor),更改其中的一个,另外一个也会跟着改变。(顾名思义,view()仅仅是改变了对这个张量的观察角度)

    x += 1
    print(x)
    print(y) # 也加了了1
    >> tensor([[ 1.7383,  1.4008,  1.4836, -0.5713],
            [ 0.9463,  2.5714, -0.0831,  0.4281],
            [ 3.1267, -0.2381,  0.9456,  0.1616],
            [ 0.4377, -0.0866,  0.6249, -0.7795]])
    tensor([ 1.7383,  1.4008,  1.4836, -0.5713,  0.9463,  2.5714, -0.0831,  0.4281,
             3.1267, -0.2381,  0.9456,  0.1616,  0.4377, -0.0866,  0.6249, -0.7795])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    如果我们希望原张量和变换后的张量互不影响,可以使用第二种方法torch.reshape(), 同样可以改变张量的形状,但是此函数并不能保证返回的是其拷贝值,所以官方不推荐使用。推荐的方法是我们先用 clone() 创造一个张量副本然后再使用 torch.view()进行函数维度变换 。

    注:使用 clone() 还有一个好处是会被记录在计算图中,即梯度回传到副本时也会传到源 Tensor 。

    4. 取值操作

    如果我们有一个元素 tensor ,我们可以使用 .item() 来获得这个 value,而不获得其他性质:

    x = torch.randn(1) 
    print(x)
    print(type(x)) 
    print(x.item())
    print(type(x.item()))
    
    >>tensor([-1.3117])
    <class 'torch.Tensor'>
    -1.3117058277130127
    <class 'float'>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    PyTorch中的 Tensor 支持超过一百种操作,包括转置、索引、切片、数学运算、线性代数、随机数等等,具体使用方法可参考官方文档

    2.3 广播机制

    当对两个形状不同的 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]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    从查询语句执行流程看MySQL架构
    el-popover 通过js手动控制弹出框显示、隐藏
    pip cryptography 遇到的 OpenSSL 问题
    Web学习笔记-HTML
    从零开始:新手快速在国产操作系统中搭建高可用K8S(V1.28)集群落地实践
    【Leetcode HOT100】积最大子数组 c++
    Oracle根据主键获取对应表和修改序列器当前值
    java计算机毕业设计新闻网站MyBatis+系统+LW文档+源码+调试部署
    YOLOv6、PP-YOLOE、PicoDet选择TOOD
    MATLAB算法实战应用案例精讲-【优化算法】树木生长算法(TGA)(附MATLAB代码实现)
  • 原文地址:https://blog.csdn.net/qq_42251120/article/details/126835591