• TensorFlow进阶二(高阶操作)


    ⚠申明: 未经许可,禁止以任何形式转载,若要引用,请标注链接地址。 全文共计3077字,阅读大概需要3分钟
    🌈更多学习内容, 欢迎👏关注👀【文末】我的个人微信公众号:不懂开发的程序猿
    个人网站:https://jerry-jy.co/

    TensorFlow进阶二


    一、任务需求

    对于图片数据的高和宽、序列信号的长度,维度长度可能各不相同。为了方便网络的并行计算,需要将不同长度的数据扩张为相同长度,之前我们介绍了通过复制的方式可以增加数据的长度,但是重复复制数据会破坏原有的数据结构,并不适合于此处。通常的做法是,在需要补充长度的数据开始或结束处填充足够数量的特定数值,这些特定数值一般代表了无效意义,例如 0,使得填充后的长度满足系统要求。那么这种操作就叫作填充(Padding)。本节将要完成张量的填充与复制,数据限幅以及tf.gather、tf.gather_nd、tf.boolean_mark、tf.where、scatter_nd、meshgrid等函数的操作。

    二、任务目标

    1、掌握张量的填充与复制
    2、掌握张量的数据限幅
    3、掌握张量的高阶操作

    三、任务环境

    1、jupyter开发环境
    2、python3.6
    3、tensorflow2.4

    四、任务实施过程

    (四)、高阶操作

    17、通过 tf.gather_nd 函数,可以通过指定每次采样点的多维坐标来实现采样多个点的目的。回到上面的挑战,我们希望抽查第 2 个班级的第 2 个同学的所有科目,第 3 个班级的第 3 个同学的所有科目,第 4 个班级的第 4 个同学的所有科目。那么这 3 个采样点的索引坐标可以记为:[1,1]、[2,2]、[3,3],我们将这个采样方案合并为一个 List 参数,即
    [[1,1],[2,2],[3,3]],通过 tf.gather_nd 函数即可

    tf.gather_nd(x,[[1,1],[2,2],[3,3]])
    
    • 1

    在这里插入图片描述

    可以看到,结果与串行采样方式的完全一致,实现更加简洁,计算效率大大提升

    18、使用 tf.gather_nd 采样多个样本时,例如希望采样𝑖号班级,𝑗个学生,𝑘门科目的成绩,则可以表达为[. . . ,[𝑖,𝑗, 𝑘], . . .],外层的括号长度为采样样本的个数,内层列表包含了每个采样点的索引坐标,如要抽取班级1的学生1的科目、 班级2的学生2的科目、 班级3的学生3的科目的成绩

    tf.gather_nd(x,[[1,1,2],[2,2,3],[3,3,4]])
    
    • 1

    19、除了可以通过给定索引号的方式采样,还可以通过给定掩码(Mask)的方式进行采样。继续以 shape 为[4,35,8]的成绩册张量为例,这次我们以掩码方式进行数据提取。
    考虑在班级维度上进行采样,对这 4 个班级的采样方案的掩码为mask = [True, False, False, True]即采样第 1 和第 4 个班级的数据,通过 tf.boolean_mask(x, mask, axis)可以在 axis 轴上根据
    mask 方案进行采样

    根据掩码方式采样班级,给出掩码和维度索引
    tf.boolean_mask(x,mask=[True, False,False,True],axis=0)

    注意掩码的长度必须与对应维度的长度一致,如在班级维度上采样,则必须对这 4 个班级是否采样的掩码全部指定,掩码长度为 4

    20、如果对 8 门科目进行掩码采样,设掩码采样方案为mask = [True, False, False, True, True, False, False, True],即采样第 1、4、5、8 门科目

    # 根据掩码方式采样科目
    tf.boolean_mask(x,mask=[True,False,False,True,True,False,False,True],axis=2)
    
    • 1
    • 2
    <tf.Tensor: shape=(4, 35, 4), dtype=int32, numpy=
    array([[[54, 15, 81, 19],
            [23, 62,  0, 32],
            [45, 98,  6, 72],
            [18, 99, 76, 51],
            [81, 20, 64, 32],
            [ 5, 43, 30, 80],
            [81, 82, 64, 85],
            [10, 63, 55, 97],
            [68, 86, 35, 60],
            [80, 52, 71, 97],
            [99, 35, 20, 56],
            [27, 94,  0, 44],
            [34, 53, 43, 31],
            [35, 46, 66, 71],
            [17, 77, 81, 65],
            [ 8, 60, 94, 53],
            [66, 60, 31, 51],
            [26, 57, 71, 31],
            [53, 42, 65, 46],
            [25, 31,  2, 75],
            [60, 40, 24, 68],
            [49, 97,  2, 96],
            [76, 68, 45,  7],
            [87, 18, 95, 67],
    ...
            [70,  7, 64, 15],
            [29, 72, 30, 63],
            [34, 26, 75,  4],
            [83, 22, 68, 99],
            [64, 37, 64, 23]]], dtype=int32)>
    Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    21、通过 tf.where(cond, a, b)操作可以根据 cond 条件的真假从参数𝑨或𝑩中读取数据。当对应位置的cond𝑖为 True,𝑜𝑖从𝑎𝑖中复制数据;当对应位置的cond𝑖为 False,𝑜𝑖从𝑏𝑖中复制数据。考虑从 2 个全 1 和全 0 的
    3 × 3大小的张量𝑨和𝑩中提取数据,其中cond𝑖为 True 的位置从𝑨中对应位置提取元素 1,cond𝑖为 False 的位置从𝑩对应位置提取元素 0

    a = tf.ones([3,3]) # 构造 a 为全 1 矩阵
    b = tf.zeros([3,3]) # 构造 b 为全 0 矩阵
    # 构造采样条件
    cond =tf.constant([[True,False,False],[False,True,False],[True,True,False]])
    tf.where(cond,a,b)  #根据条件从a,b中采样
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    可以看到,返回的张量中为 1 的位置全部来自张量 a,返回的张量中为 0 的位置来自张量b。

    22、当参数 a=b=None 时,即 a 和 b 参数不指定,tf.where 会返回 cond 张量中所有 True 的元素的索引坐标

    cond # 构造的 cond 张量
    
    • 1

    array([[ True, False, False],
    [False, True, False],
    [ True, True, False]])>

    其中 True 共出现 4 次,每个 True 元素位置处的索引分别为[0,0]、[1,1]、[2,0]、[2,1],可以直接通过 tf.where(cond)形式来获得这些元素的索引坐标

    tf.where(cond) # 获取 cond 中为 True 的元素索引
    
    • 1

    array([[0, 0],
    [1, 1],
    [2, 0],
    [2, 1]])>

    23、我们需要提取张量中所有正数的数据和索引。首先构造张量 a,并通过比较运算得到所有正数的位置掩码

    x = tf.random.normal([3,3]) # 构造 a
    x
    
    > <tf.Tensor: shape=(3, 3), dtype=float32, numpy=
    array([[ 1.3181536 ,  0.7503586 ,  1.3323568 ],
           [-0.2842348 , -0.11278582,  1.5982385 ],
           [ 1.1395993 , -0.6405513 ,  0.36168438]], dtype=float32)>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    24、通过比较运算,得到所有正数的掩码

    mask=x>0 # 比较操作,等同于 tf.math.greater()
    mask
    
    • 1
    • 2
    <tf.Tensor: shape=(4, 28, 28, 1), dtype=bool, numpy=
    array([[[[False],
             [False],
             [ True],
             ...,
             [ True],
             [ True],
             [ True]],
    
            [[ True],
             [ True],
             [ True],
             ...,
             [ True],
             [False],
             [False]],
    
            [[False],
             [False],
             [ True],
             ...,
             [False],
             [False],
             [False]],
    ...
             [ True],
             ...,
             [ True],
             [ True],
             [False]]]])>
    Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    25、通过 tf.where 提取此掩码处 True 元素的索引坐标

    indices=tf.where(mask) # 提取所有大于 0 的元素索引
    indices
    
    • 1
    • 2
    <tf.Tensor: shape=(1597, 4), dtype=int64, numpy=
    array([[ 0,  0,  2,  0],
           [ 0,  0,  3,  0],
           [ 0,  0,  4,  0],
           ...,
           [ 3, 27, 22,  0],
           [ 3, 27, 25,  0],
           [ 3, 27, 26,  0]])>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    26、拿到索引后,通过 tf.gather_nd 即可恢复出所有正数的元素

    tf.gather_nd(x,indices) # 提取正数的元素值
    
    • 1

    27、通过 tf.scatter_nd(indices, updates, shape)函数可以高效地刷新张量的部分数据,但是这个函数只能在全0的白板张量上面执行刷新操作。
    我们将实现一个向量的刷新实例如下

    # 构造需要刷新数据的位置参数,即为 4、3、1 和 7 号位置
    indices = tf.constant([[4], [3], [1], [7]])
    # 构造需要写入的数据,4 号位写入 4.4,3 号位写入 3.3,以此类推
    updates = tf.constant([4.4, 3.3, 1.1, 7.7])
    # 在长度为 8 的全 0 向量上根据 indices 写入 updates 数据
    tf.scatter_nd(indices, updates, [8])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    可以看到,在长度为 8 的白板上,写入了对应位置的数据,4 个位置的数据被刷新

    28、考虑 3 维张量的刷新例子,白板张量的 shape 为[4,4,4],共有 4 个通道的特征图,每个通道大小为4 × 4,现有 2 个通道的新数据 updates:[2,4,4],需要写入索
    引为[1,3]的通道上

    # 构造写入位置,即 2 个位置
    indices = tf.constant([[1],[3]])
    updates = tf.constant([# 构造写入数据,即 2 个矩阵
     [[5,5,5,5],[6,6,6,6],[7,7,7,7],[8,8,8,8]],
     [[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4]]
    ])
    # 在 shape 为[4,4,4]白板上根据 indices 写入 updates
    tf.scatter_nd(indices,updates,[4,4,4])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    在这里插入图片描述

    可以看到,数据被刷新到第 2 和第 4 个通道特征图上。

    29、通过 tf.meshgrid 函数可以方便地生成二维网格的采样点坐标。通过在 x 轴上进行采样 100 个数据点,y 轴上采样 100 个数据点,然后利用
    tf.meshgrid(x, y)即可返回这 10000 个数据点的张量数据,保存在 shape 为[100,100,2]的张量中。为了方便计算,tf.meshgrid 会返回在 axis=2 维度切割后的 2 个张量𝑨和𝑩,其中张量𝑨包含了所有点的 x 坐标,𝑩包含了所有点的 y 坐标,shape 都为[100,100]

    x = tf.linspace(-8.,8,100) # 设置 x 轴的采样点
    y = tf.linspace(-8.,8,100) # 设置 y 轴的采样点
    x,y = tf.meshgrid(x,y) # 生成网格点,并内部拆分后返回
    x.shape,y.shape # 打印拆分后的所有点的 x,y 坐标张量 shape
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    30、利用生成的网格点坐标张量𝑨和𝑩,Sinc 函数在 TensorFlow 中实现如下

    z = tf.sqrt(x**2+y**2)
    z = tf.sin(z)/z # sinc 函数实现
    
    • 1
    • 2

    31、通过 matplotlib 库即可绘制出函数在𝑥 ∈ [−8,8],𝑦 ∈ [−8,8]区间的 3D 曲面

    import matplotlib
    from matplotlib import pyplot as plt
    # 导入 3D 坐标轴支持
    from mpl_toolkits.mplot3d import Axes3D
    fig = plt.figure()
    ax = Axes3D(fig) # 设置 3D 坐标轴
    # 根据网格点绘制 sinc 函数 3D 曲面
    ax.contour3D(x.numpy(), y.numpy(), z.numpy(), 50)
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    五、任务小结

    本节我们完成了填充、复制,tf.tile()函数实现长度为 1 的维度复制的功能。tf.tile 函数除了可以对长度为 1 的维度进行复制若干份,还可以对任意长度的维度进行复制若干份,进行复制时会根据原来的数据次序重复复制。紧接着介绍了数据的下限幅、上下边界限幅。最后展示了高阶操作如tf.gather、tf.gather_nd、tf.boolean_mask、tf.where等一系列操作。通过本节任务需要掌握以下知识:

    • 掌握张量的填充与复制
    • 掌握张量的数据限幅
    • 掌握张量的高阶操作

    –end–

  • 相关阅读:
    《Flowable流程引擎从零到壹》Flowable流程引擎介绍和实战项目初始化流程引擎实例
    GPT引领前沿与应用突破之GPT4科研实践技术与AI绘图教程
    win server 2012 r2 部署 netcore 站点 500.19
    031Vue3自引用原生方式实现多级数据展示功能-支持树状、级联等需求
    java面试题2019_java面试题及答案_java面试题库
    【LeetCode-中等】238. 除自身以外数组的乘积(详解)
    ssm在线教学质量评价系统毕业设计源码141550
    《分布式服务架构:原理,设计与实战》
    PowerEdge RAID Controller (PERC) types for Dell EMC systems PERC11
    界面控件DevExpress WPF的主题设计器,可轻松完成应用主题研发
  • 原文地址:https://blog.csdn.net/qq_44807756/article/details/138174197