TensorFlow基础语句语法个人笔记

1 篇文章 0 订阅
1 篇文章 0 订阅

TensorFlow基础语句语法个人笔记

【TensorFlow】
阅读《TensorFlow深度学习》笔记,供个人查询,记录。



TensorFlow基础

数据类型

张量

  • 维度数dim>2的数组,在TensorFlow中,标量向量,矩阵都统称张量。

  • improt tensorflow as tf
    a=tf.constant(1.1)
    a=tf.constant([1.1,1.2,1.3])
    a=tf.constant([1,2],[3,4])
    a=tf.constant([[[1,2],[3,4],[5,6],[7,8]]])
    

字符串类型

  • (tf.strings)中也提供了常见的字符串工具函数,比如小写化lower(),拼接join(),长度length(),切分split()等。

  • improt tensorflow as tf
    a=tf.constant('Hello,Deep Learning.')
    tf.strings.lower(a)
    

布尔类型

  • improt tensorflow as tf
    a=tf.constant(True)#创建布尔类型标量
    a=tf.constant([True,False])#创建布尔类型向量
    #TensorFlow的布尔类型和Python语言的布尔类型不等价,不能通用
    

数值精度

  • 常见类型有tf.int16,tf.int32,tf.int64,tf.float16,tf.float32,tf.float64等,其中tf.float64即为tf.double。

  • improt tensorflow as tf
    #创建指定精度的张量
    tf.constant(123456789,dtype=tf.int16)
    

读取精度

  • 通过访问张量的 dtype 成员属性可以判断张量的保存精度

  • improt tensorflow as tf
    print('before:',a.dtype) # 读取原有张量的数值精度
    if a.dtype != tf.float32: # 如果精度不符合要求,则进行转换
    	a = tf.cast(a,tf.float32) # tf.cast 函数可以完成精度转换
    print('after :',a.dtype) # 打印转换后的精度
    

类型转换

  • 系统的每个模块使用的数据类型、 数值精度可能各不相同, 对于不符合要求的张量的
    类型及精度, 需要通过 tf.cast 函数进行转换。

  • improt tensorflow as tf
    a = tf.constant(123456789, dtype=tf.int32)
    tf.cast(a, tf.int16) # 转换为低精度整型
    
    a = tf.constant([True, False])
    tf.cast(a, tf.int32) 
    #<tf.Tensor: id=48, shape=(2,), dtype=int32, numpy=array([1, 0])>
    #一般默认 0 表示 False, 1 表示 True,在 TensorFlow 中,将非 0 数字都视为 True
    

待优化张量

  • 为了区分需要计算梯度信息的张量与不需要计算梯度信息的张量, TensorFlow 增加了
    一种专门的数据类型来支持梯度信息的记录: tf.Variable。 tf.Variable 类型在普通的张量类
    型基础上添加了 name, trainable 等属性来支持计算图的构建。 由于梯度运算会消耗大量的
    计算资源,而且会自动更新相关参数,对于不需要的优化的张量,如神经网络的输入𝑿,
    不需要通过 tf.Variable 封装;相反,对于需要计算梯度并优化的张量, 如神经网络层的𝑾
    和𝒃, 需要通过 tf.Variable 包裹以便 TensorFlow 跟踪相关梯度信息

  • improt tensorflow as tf
    a = tf.constant([-1, 0, 1, 2]) # 创建 TF 张量
    aa = tf.Variable(a) # 转换为 Variable 类型
    aa.name, aa.trainable # Variable 类型张量的属性
    #('Variable:0', True)
    
    
  • 其中张量的 name 和 trainable 属性是 Variable 特有的属性, name 属性用于命名计算图中的
    变量,这套命名体系是 TensorFlow 内部维护的, 一般不需要用户关注 name 属性; trainable
    属性表征当前张量是否需要被优化,创建 Variable 对象时是默认启用优化标志,可以设置
    trainable=False 来设置张量不需要优化。
    除了通过普通张量方式创建 Variable, 也可以直接创建,例如

  • a = tf.Variable([[1,2],[3,4]]) # 直接创建 Variable 张量
    

创建张量

  • 在 TensorFlow 中,可以通过多种方式创建张量,如从 Python 列表对象创建,从
    Numpy 数组创建,或者创建采样自某种已知分布的张量等。

从数组,列表对象创建

  • 通过 tf.convert_to_tensor 函数可以创建新 Tensor,并将保存在 Python List 对象或者
    Numpy Array 对象中的数据导入到新 Tensor 中,

  • tf.convert_to_tensor([1,2.]) # 从列表创建张量
    tf.convert_to_tensor(np.array([[1,2.],[3,4]])) # 从数组中创建张量
    

创建全 0 或全 1 张量

  • tf.zeros([]),tf.ones([]) # 创建全 0,全 1 的标量
    tf.zeros([1]),tf.ones([1]) # 创建全 0,全 1 的向量
    tf.zeros([2,2]) # 创建全 0 矩阵,指定 shape 为 2 行 2 列
    tf.ones([3,2]) # 创建全 1 矩阵,指定 shape 为 3 行 2 列
    
  • 通过 tf.zeros_like, tf.ones_like 可以方便地新建与某个张量 shape 一致, 且内容为全 0 或
    全 1 的张量。例如,创建与张量𝑨形状一样的全 0 张量

  • a = tf.ones([2,3]) # 创建一个矩阵
    tf.zeros_like(a) # 创建一个与 a 形状相同,但是全 0 的新矩阵
    
    a = tf.zeros([3,2]) # 创建一个矩阵
    tf.ones_like(a) # 创建一个与 a 形状相同,但是全 1 的新矩阵
    

创建自定义数值张量

  • 通过 tf.fill(shape, value)可以创建全为自定义数值 value 的张量,形状由 shape 参数指
    定。 例如,创建元素为-1的标量:

  • tf.fill([], -1) # 创建-1 的标量
    tf.fill([1], -1) # 创建-1 的向量
    tf.fill([2,2], 99) # 创建 2 行 2 列,元素全为 99 的矩阵
    

创建已知分布的张量

  • 通过 tf.random.normal(shape, mean=0.0, stddev=1.0)可以创建形状为 shape,均值为
    mean,标准差为 stddev 的正态分布𝒩(mean, stddev2)。例如,创建均值为 0,标准差为 1
    的正态分布:

  • tf.random.normal([2,2]) # 创建标准正态分布的张量
    tf.random.normal([2,2], mean=1,stddev=2) # 创建正态分布的张量
    
  • 通过 tf.random.uniform(shape, minval=0, maxval=None, dtype=tf.float32)可以创建采样自
    [minval, maxval)区间的均匀分布的张量。例如创建采样自区间[0,1), shape 为[2,2]的矩
    阵:

  • tf.random.uniform([2,2]) # 创建采样自[0,1)均匀分布的矩阵
    tf.random.uniform([2,2],maxval=10) # 创建采样自[0,10)均匀分布的矩阵
    # 如果需要均匀采样整形类型的数据,必须指定采样区间的最大值 maxval 参数,同时指
    # 定数据类型为 tf.int*型:
    
    # 创建采样自[0,100)均匀分布的整型矩阵
    tf.random.uniform([2,2],maxval=100,dtype=tf.int32)
    

创建序列

  • 在循环计算或者对张量进行索引时,经常需要创建一段连续的整型序列,可以通过
    tf.range()函数实现。 tf.range(limit, delta=1)可以创建[0, limit)之间,步长为 delta 的整型序
    列,不包含 limit 本身。例如,创建 0~10,步长为 1 的整型序列:

  • tf.range(10) # 0~10,不包含 10
    tf.range(10,delta=2) # 创建 0~10,步长为 2 的整形序列
    
  • 通过 tf.range(start, limit, delta=1)可以创建[start, limit),步长为 delta 的序列,不包含
    limit 本身:

  • tf.range(1,10,delta=2) # 1~10
    

张量的典型应用

标量

  • 在 TensorFlow 中,标量最容易理解,它就是一个简单的数字,维度数为 0, shape 为
    []。
  • 标量的一些典型用途是误差值的表示、 各种测量指标的表示,比如准确度(Accuracy,
    简称 acc),精度(Precision)和召回率(Recall)等,方便直接化为曲线图。

向量

  • 向量是一种非常常见的数据载体,如在全连接层和卷积神经网络层中,偏置张量𝒃就
    使用向量来表示。
  • 待补充

矩阵

  • 矩阵也是非常常见的张量类型,比如全连接层的批量输入张量𝑿的形状为[𝑏, 𝑑in],其
    中𝑏表示输入样本的个数,即 Batch Size, 𝑑in表示输入特征的长度。 例如特征长度为 4,一
    共包含 2 个样本的输入可以表示为矩阵:

  • x = tf.random.normal([2,4]) # 2 个样本,特征长度为 4 的张量
    
  • 令全连接层的输出节点数为 3,则它的权值张量𝑾的 shape 为[4,3],我们利用张量𝑿、 𝑾和
    向量𝒃可以直接实现一个网络层,代码如下:

  • w = tf.ones([4,3]) # 定义 W 张量
    b = tf.zeros([3]) # 定义 b 张量
    o = x@w+b # X@W+b 运算
    
  • 其中𝑿和𝑾张量均是矩阵,上述代码实现了一个线性变换的网络层,激活函数为空。 一般
    地, 𝜎(𝑿@𝑾 + 𝒃)网络层称为全连接层, 在 TensorFlow 中可以通过 Dense 类直接实现, 特
    别地,当激活函数𝜎为空时, 全连接层也称为线性层。 我们通过 Dense 类创建输入 4 个节
    点,输出 3 个节点的网络层, 并通过全连接层的 kernel 成员名查看其权值矩阵𝑾:

  • fc = layers.Dense(3) # 定义全连接层的输出节点为 3
    fc.build(input_shape=(2,4)) # 定义全连接层的输入节点为 4
    fc.kernel # 查看权值矩阵 W
    
    <tf.Variable 'kernel:0' shape=(4, 3) dtype=float32, numpy=
    array([[ 0.06468129, -0.5146048 , -0.12036425],
    [ 0.71618867, -0.01442951, -0.5891943 ],
    [-0.03011459, 0.578704 , 0.7245046 ],
    [ 0.73894167, -0.21171576, 0.4820758 ]], dtype=float32)>
    

三维张量

  • 三维的张量一个典型应用是表示序列信号,它的格式是

  • 𝑿 = [𝑏, sequence len, feature len]

  • 其中𝑏表示序列信号的数量, sequence len 表示序列信号在时间维度上的采样点数或步数,feature len 表示每个点的特征长度。

  • # 自动加载 IMDB 电影评价数据集
    (x_train,y_train),(x_test,y_test)=keras.datasets.imdb.load_data(num_words=10000)
    # 将句子填充、截断为等长 80 个单词的句子
    x_train = keras.preprocessing.sequence.pad_sequences(x_train,maxlen=80)
    x_train.shape
    #Out : (25000, 80)
    
    # 创建词向量 Embedding 层类
    embedding=layers.Embedding(10000, 100)
    # 将数字编码的单词转换为词向量
    out = embedding(x_train)
    out.shape
    #Out: TensorShape([25000, 80, 100])
    

四维张量

  • 四维张量在卷积神经网络中应用非常广泛,它用于保存特征图(Feature maps)数据,格
    式一般定义为
  • [𝑏, ℎ, , 𝑐]
  • 其中𝑏表示输入样本的数量, ℎ/ 分别表示特征图的高/宽, 𝑐表示特征图的通道数, 部分深
    度学习框架也会使用[𝑏, 𝑐, ℎ, ]格式的特征图张量。

索引与切片

  • 通过索引与切片操作可以提取张量的部分数据, 它们的使用频率非常高。

索引

  • 在 TensorFlow 中, 支持基本的[𝑖][𝑗] ⋯标准索引方式,也支持通过逗号分隔索引号的索
    引方式。

  • x[0][1][2]
    x[1,9,2]
    #两种方法都可
    

切片

  • 通过start: end: step切片方式可以方便地提取一段数据,其中 start 为开始读取位置的索
    引, end 为结束读取位置的索引(不包含 end 位), step 为采样步长。

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rg10vKum-1613714959718)(C:\Users\WangQi\AppData\Roaming\Typora\typora-user-images\image-20210215115039150.png)]

  • 特别地, step 可以为负数,考虑最特殊的一种例子, 当step = -1时, start: end: -1表
    示从 start 开始, 逆序读取至 end 结束(不包含 end),索引号𝑒𝑛𝑑 ≤ 𝑠𝑡𝑎𝑟𝑡。

  • 为了避免出现像 [: , : , : ,1]这样过多冒号的情况,可以使用⋯符号表示取多个维度上所
    有的数据, 其中维度的数量需根据规则自动推断:当切片方式出现⋯符号时, ⋯符号左边
    的维度将自动对齐到最左边, ⋯符号右边的维度将自动对齐到最右边,此时系统再自动推
    断⋯符号代表的维度数量,它的切片方式总结

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XEtOfXYO-1613714959719)(C:\Users\WangQi\AppData\Roaming\Typora\typora-user-images\image-20210215115418027.png)]

维度变换

  • 基本的维度变换操作函数包含了改变视图 reshape、 插入新维度 expand_dims,删除维
    度 squeeze、 交换维度 transpose、 复制数据 tile 等函数。

改变视图

  • 我们通过 tf.range()模拟生成一个向量数据,并通过 tf.reshape 视图改变函数产生不同的
    视图,例如:

  • x=tf.range(96) # 生成向量
    x=tf.reshape(x,[2,4,4,3]) # 改变 x 的视图,获得 4D 张量,存储并未改变
    
    Out: # 可以观察到数据仍然是 0~95 的顺序,可见数据并未改变,改变的是数据的结构
    <tf.Tensor: id=11, shape=(2, 4, 4, 3), dtype=int32, numpy=
    array([[[[ 0, 1, 2],
    [ 3, 4, 5],
    [ 6, 7, 8],
    [ 9, 10, 11]],…
    
    
    tf.reshape(x,[2,-1])
    #其中的参数−1表示当前轴上长度需要根据张量总元素不变的法则自动推导, 从而方便用户
    #书写。
    Out:<tf.Tensor: id=520, shape=(2, 48), dtype=int32, numpy=
    array([[ 0, 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,80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95]])>
    

增、 删维度

  • 增加维度

    • 考虑一个具体例子,一张28 × 28大小的灰度图片的数据保存为 shape 为[28,28]的张
      量, 在末尾给张量增加一新维度, 定义为通道数维度,此时张量的 shape 变为[28,28,1],实现如下:

    • # 产生矩阵
      x = tf.random.uniform([28,28],maxval=10,dtype=tf.int32)
      #通过 tf.expand_dims(x, axis)可在指定的 axis 轴前可以插入一个新的维度:
      x = tf.expand_dims(x,axis=2) # axis=2 表示宽维度后面的一个维度
      
      <tf.Tensor: id=13, shape=(28, 28, 1), dtype=int32, numpy=
      array([[[6],
      [2],
      [0],
      [0],
      [6],
      [7],
      [3],
    • 插入一个新维度后,数据的存储顺序并没有改变,依然按着6,2,0,0,6,7, ⋯的顺
      序保存,仅仅是在插入一个新的维度后,改变了数据的视图

    • x = tf.expand_dims(x,axis=0) # 高维度之前插入新维度
      
    • 需要注意的是, tf.expand_dims 的 axis 为正时,表示在当前维度之前插入一个新维度; 为负时,表示当前维度之后插入一个新的维度。 以[𝑏, ℎ, , 𝑐]张量为例,不同 axis 参数的实际插入位置如图

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cMPR8wK1-1613714959720)(C:\Users\WangQi\AppData\Roaming\Typora\typora-user-images\image-20210215125934630.png)]

  • 删除维度

    • 是增加维度的逆操作,与增加维度一样,删除维度只能删除长度为 1 的维
      度,也不会改变张量的存储。 继续考虑增加维度后 shape 为[1,28,28,1]的例子,如果希望将图片数量维度删除,可以通过 tf.squeeze(x, axis)函数, axis 参数为待删除的维度的索引号,例如, 图片数量的维度轴 axis=0:

    • x = tf.squeeze(x, axis=0) # 删除图片数量维度
      #如果不指定维度参数 axis,即 tf.squeeze(x), 那么它会默认删除所有长度为 1 的维度
      
    • 建议使用 tf.squeeze()时逐一指定需要删除的维度参数,防止 TensorFlow 意外删除某些长度为 1 的维度,导致计算结果不合法。

交换维度

  • 改变视图、 增删维度都不会影响张量的存储。在实现算法逻辑时, 在保持维度顺序不
    变的条件下, 仅仅改变张量的理解方式是不够的,有时需要直接调整的存储顺序,即交换
    维度(Transpose)。通过交换维度操作,改变了张量的存储顺序,同时也改变了张量的视
    图。

  • 我们以[𝑏, ℎ, w, 𝑐]转换到[𝑏, 𝑐, ℎ, w]为例,介绍如何使用 tf.transpose(x, perm)函数完成维度交换操作,其中参数 perm表示新维度的顺序 List。

  • 考虑图片张量 shape 为[2,32,32,3], “图片数量、行、列、通道数” 的维度索引分别为 0、 1、 2、 3,如果需要交换为[𝑏, 𝑐, ℎ, w]格式,则新维度的排序为“图片数量、通道数、行、列”,对应的索引号为[0,3,1,2], 因此参数 perm 需设置为[0,3,1,2], 实现如下:

  • x = tf.random.normal([2,32,32,3])
    tf.transpose(x,perm=[0,3,1,2]) # 交换维度
    
  • 需要注意的是, 通过 tf.transpose 完成维度交换后,张量的存储顺序已经改变, 视图也
    随之改变, 后续的所有操作必须基于新的存续顺序和视图进行。 相对于改变视图操作,维
    度交换操作的计算代价更高。

复制数据

  • 可以通过 tf.tile(x, multiples)函数完成数据在指定维度上的复制操作, multiples 分别指
    定了每个维度上面的复制倍数,对应位置为 1 表明不复制,为 2 表明新长度为原来长度的
    2 倍,即数据复制一份,以此类推。

  • b = tf.constant([1,2]) # 创建向量 b
    b = tf.expand_dims(b, axis=0) # 插入新维度,变成矩阵
    b = tf.tile(b, multiples=[2,1]) # 样本维度上复制一份
    

Broadcasting

数学运算

加减乘除运算

  • 加、 减、 乘、 除是最基本的数学运算,分别通过 tf.add, tf.subtract, tf.multiply, tf.divide
    函数实现, TensorFlow 已经重载了+、 - 、 ∗ 、 /运算符,一般推荐直接使用运算符来完成
    加、 减、 乘、 除运算。整除和余除也是常见的运算之一,分别通过//和%运算符实现。

  • a = tf.range(5)
    b = tf.constant(2)
    a//b # 整除运算
    
    a%b # 余除运算
    

乘方运算

  • 通过 tf.pow(x, a)可以方便地完成𝑦 = 𝑎的乘方运算,也可以通过运算符**实现 ∗∗ 𝑎运
    算,实现如下:

  • x = tf.range(4)
    tf.pow(x,3) # 乘方运算
    
    x**2 # 乘方运算符
    
    x**(0.5) # 平方根
    
  • 特别地,对于常见的平方和平方根运算,可以使用 tf.square(x)和 tf.sqrt(x)实现。平方运算
    实现如下:

  • x = tf.range(5)
    x = tf.cast(x, dtype=tf.float32) # 转换为浮点数
    x = tf.square(x) # 平方
    
    tf.sqrt(x) # 平方根
    

指数和对数运算

  • 通过 tf.pow(a, x)或者**运算符也可以方便地实现指数运算𝑎𝑥,例如:

  • x = tf.constant([1.,2.,3.])
    2**x # 指数运算
    
    #特别地,对于自然指数e𝑥, 可以通过 tf.exp(x)实现,例如:
    tf.exp(1.) # 自然指数运算
    
    #在 TensorFlow 中,自然对数loge 可以通过 tf.math.log(x)实现,例如:
    x=tf.exp(3.)
    tf.math.log(x) # 对数运算
    

矩阵相乘运算

  • 神经网络中间包含了大量的矩阵相乘运算,前面我们已经介绍了通过@运算符可以方便的实现矩阵相乘,还可以通过 tf.matmul(a, b)函数实现。需要注意的是, TensorFlow 中的
    矩阵相乘可以使用批量方式,也就是张量𝑨和𝑩的维度数可以大于 2。当张量𝑨和𝑩维度数大
    于 2 时, TensorFlow 会选择𝑨和𝑩的最后两个维度进行矩阵相乘,前面所有的维度都视作
    Batch 维度。

  • 矩阵相乘函数同样支持自动 Broadcasting 机制。

  • a = tf.random.normal([4,28,32])
    b = tf.random.normal([32,16])
    tf.matmul(a,b) # 先自动扩展,再矩阵相乘
    

TensorFlow进阶

合并与分割

合并

  • 张量的合并可以使用拼接(Concatenate)和堆叠(Stack)操作实现,拼接操作并不会产生新
    的维度, 仅在现有的维度上合并, 而堆叠会创建新维度。 选择使用拼接还是堆叠操作来合并张量,取决于具体的场景是否需要创建新维度。

  • 拼接

    • 在 TensorFlow 中,可以通过 tf.concat(tensors, axis)函数拼接张量,其中参数
      tensors 保存了所有需要合并的张量 List, axis 参数指定需要合并的维度索引。

    • a = tf.random.normal([4,35,8]) # 模拟成绩册 A
      b = tf.random.normal([6,35,8]) # 模拟成绩册 B
      tf.concat([a,b],axis=0) # 拼接合并成绩册
      # <tf.Tensor: id=13, shape=(10, 35, 8), dtype=float32, numpy=
      # array([[[ 1.95299834e-01, 6.87859178e-01, -5.80048323e-01, ...,
      # 1.29430830e+00, 2.56610274e-01, -1.27798581e+00],
      # [ 4.29753691e-01, 9.11329567e-01, -4.47975427e-01, ...,
      
    • 从语法上来说,拼接合并操作可以在任意的维度上进行,唯一的约束是非合并维度的
      长度必须一致 。

  • 堆叠

    • 拼接操作直接在现有维度上合并数据, 并不会创建新的维度。 如果在合并数据
      时,希望创建一个新的维度,则需要使用 tf.stack 操作。考虑张量𝑨保存了某个班级的成绩册, shape 为[35,8], 张量𝑩保存了另一个班级的成绩册, shape 为[35,8]。合并这 2 个班级的数据时, 则需要创建一个新维度,定义为班级维度, 新维度可以选择放置在任意位置,一般根据大小维度的经验法则,将较大概念的班级维度放置在学生维度之前, 则合并后的张量的新 shape 应为[2,35,8]。

    • a = tf.random.normal([35,8])
      b = tf.random.normal([35,8])
      tf.stack([a,b],axis=0) # 堆叠合并为 2 个班级,班级维度插入在最前
      

分隔

  • 通过 tf.split(x, num_or_size_splits, axis)可以完成张量的分割操作, 参数意义如下
    • x 参数:待分割张量。
    • num_or_size_splits 参数:切割方案。当 num_or_size_splits 为单个数值时,如 10,表示等长切割为 10 份;当 num_or_size_splits 为 List 时, List 的每个元素表示每份的长度,如[2,4,2,2]表示切割为 4 份,每份的长度依次是 2、 4、 2、 2。
    • axis 参数:指定分割的维度索引号。

数据统计

向量范数

  • 向量范数(Vector Norm)是表征向量“长度”的一种度量方法, 它可以推广到张量上。
    在神经网络中,常用来表示张量的权值大小,梯度大小等。常用的向量范数有:

  • 在 TensorFlow 中,可以通过 tf.norm(x, ord)求解张量的 L1、 L2、 ∞等范数,其中参数
    ord 指定为 1、 2 时计算 L1、 L2 范数,指定为 np.inf 时计算∞ -范数,例如:

  • x = tf.ones([2,2])
    tf.norm(x,ord=1) # 计算 L1 范数
    
    tf.norm(x,ord=2) # 计算 L2 范数
    
    import numpy as np
    tf.norm(x,ord=np.inf) # 计算∞范数
    

最值、均值、和

  • 通过 tf.reduce_max、 tf.reduce_min、 tf.reduce_mean、 tf.reduce_sum 函数可以求解张量
    在某个维度上的最大、最小、 均值、和,也可以求全局最大、最小、均值、和信息。

  • x = tf.random.normal([4,10]) # 模型生成概率
    tf.reduce_max(x,axis=1) # 统计概率维度上的最大值
    tf.reduce_min(x,axis=1) # 统计概率维度上的最小值
    tf.reduce_mean(x,axis=1) # 统计概率维度上的均值
    
    #当不指定 axis 参数时, tf.reduce_*函数会求解出全局元素的最大、最小、 均值、和等数据
    
    # 统计全局的最大、最小、均值、和,返回的张量均为标量
    tf.reduce_max(x),tf.reduce_min(x),tf.reduce_mean(x)
    
    #tf.reduce_sum(x, axis), 它可以求解张量在 axis 轴上所有特征的和
    tf.reduce_sum(out,axis=-1) # 求最后一个维度的和
    
    #通过 tf.argmax(x, axis)和 tf.argmin(x, axis)可以求解在 axis 轴上, x 的最大值、 最小值所在的索引号
    pred = tf.argmax(out, axis=1) # 选取概率最大的位置
    

张量比较

  • 为了计算分类任务的准确率等指标,一般需要将预测结果和真实标签比较,统计比较
    结果中正确的数量来计算准确率。

  • 通过 tf.equal(a, b)(或 tf.math.equal(a,b),两者等价)函数可以比较这 2 个张量是否相等,例如:

  • out = tf.equal(pred,y) # 预测值与真实值比较,返回布尔类型的张量
    
    #tf.equal()函数返回布尔类型的张量比较结果,只需要统计张量中 True 元素的个数,即可知道预测正确的个数。为了达到这个目的,我们先将布尔类型转换为整形张量,即 True 对应为 1, False 对应为 0, 再求和其中 1 的个数, 就可以得到比较结果中 True 元素的个数:
    
    out = tf.cast(out, dtype=tf.float32) # 布尔型转 int 型
    correct = tf.reduce_sum(out) # 统计 True 的个数
    
  • 在这里插入图片描述

填充与复制

填充

  • 重复复制数据会破坏原有的数据结构,并不适合于此处。通常的做法是,在需要补充长度的数据开始或结束处填充足够数量的特定数值, 这些特定数值一般代表了无效意义,例如 0,使得填充后的长度满足系统要求。那么这种操作就叫作填充(Padding)。

  • 填充操作可以通过 tf.pad(x, paddings)函数实现, 参数 paddings 是包含了多个[Left Padding, Right Padding]的嵌套方案 List,如[[0,0], [2,1], [1,2]]表示第一个维度不填充, 第二个维度左边(起始处)填充两个单元, 右边(结束处)填充一个单元, 第三个维度左边填充一个单元, 右边填充两个单元。

  • a = tf.constant([1,2,3,4,5,6]) # 第一个句子
    b = tf.constant([7,8,1,6]) # 第二个句子
    b = tf.pad(b, [[0,2]]) # 句子末尾填充 2 个 0
    
  • 在这里插入图片描述

  • 上述填充方案可以表达为[[0,0], [2,2], [2,2], [0,0]], 实现如下:

  • x = tf.random.normal([4,28,28,1])
    # 图片上下、左右各填充 2 个单元
    tf.pad(x,[[0,0],[2,2],[2,2],[0,0]])
    

复制

  • 通过 tf.tile 函数可以在任意维度将数据重复复制多份,如 shape 为[4,32,32,3]的数据,
    复制方案为 multiples=[2,3,3,1],即通道数据不复制,高和宽方向分别复制 2 份,图片数再复制 1 份,实现如下:

数据限幅

  • 在 TensorFlow 中,可以通过 tf.maximum(x, a)实现数据的下限幅,即𝑥 ∈ [𝑎, +∞);可
    以通过 tf.minimum(x, a)实现数据的上限幅,即𝑥 ∈ (-∞, 𝑎],举例如下:

  • x = tf.range(9)
    tf.maximum(x,2) # 下限幅到 2
    tf.minimum(x,7) # 上限幅到 7
    
    基于 tf.maximum 函数,我们可以实现 ReLU 函数如下:
    def relu(x): # ReLU 函数
    	return tf.maximum(x,0.) # 下限幅为 0 即可
    
    tf.minimum(tf.maximum(x,2),7) # 限幅为 2~7
    
    更方便地,我们可以使用 tf.clip_by_value 函数实现上下限幅:
    x = tf.range(9)
    tf.clip_by_value(x,2,7) # 限幅为 2~7
    

高级操作

tf.gather

  • tf.gather 可以实现根据索引号收集数据的目的。考虑班级成绩册的例子, 假设共有 4个班级,每个班级 35 个学生, 8 门科目,保存成绩册的张量 shape 为[4,35,8]。

  • x = tf.random.uniform([4,35,8],maxval=100,dtype=tf.int32) # 成绩册张量
    tf.gather(x,[0,1],axis=0) # 在班级维度收集第 1~2 号班级成绩册
    tf.gather(x,[0,3,8,11,12,26],axis=1)# 收集第 1,4,9,12,13,27 号同学成绩
    tf.gather(x,[2,4],axis=2) # 第 3, 5 科目的成绩
    
    其中索引号可以乱序排列,此时收集的数据也是对应顺序,例如:
    tf.gather(a,[3,1,0,2],axis=0) # 收集第 4,2,1,3 号元素
    

tf.gather_nd

  • 通过 tf.gather_nd 函数,可以通过指定每次采样点的多维坐标来实现采样多个点的目
    的。

  • # 根据多维坐标收集数据
    tf.gather_nd(x,[[1,1],[2,2],[3,3]])
    
  • 一般地,在使用 tf.gather_nd 采样多个样本时, 例如希望采样𝑖号班级, 𝑗个学生, 𝑘门
    科目的成绩,则可以表达为[. . . , [𝑖, 𝑗, 𝑘], . . . ], 外层的括号长度为采样样本的个数,内层列表包含了每个采样点的索引坐标。

tf.boolean_mask

  • 除了可以通过给定索引号的方式采样,还可以通过给定掩码(Mask)的方式进行采样。

  • mask = [True, False, False, True]
    tf.boolean_mask(x,mask=[True, False,False,True],axis=0)
    

tf.where

  • 通过 tf.where(cond, a, b)操作可以根据 cond 条件的真假从参数𝑨或𝑩中读取数据, 条件判定规则如下:

  • 其中𝑖为张量的元素索引, 返回的张量大小与𝑨和𝑩一致, 当对应位置的cond𝑖为 True, 𝑜𝑖从𝑎𝑖中复制数据;当对应位置的cond𝑖为 False, 𝑜𝑖从𝑏𝑖中复制数据。

  • 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 中采样
    
  • 当参数 a=b=None 时, 即 a 和 b 参数不指定, tf.where 会返回 cond 张量中所有 True 的元素的索引坐标。

scatter_nd

  • 通过 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])
    
    Out:<tf.Tensor: id=467, shape=(8,), dtype=float32, numpy=array([0. ,
    1.1, 0. , 3.3, 4.4, 0. , 0. , 7.7], dtype=float32)>
    

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
    Out: (TensorShape([100, 100]), TensorShape([100, 100]))
    

经典数据集加载

对于常用的经典数据集, 例如:
❑ Boston Housing, 波士顿房价趋势数据集,用于回归模型训练与测试。
❑ CIFAR10/100, 真实图片数据集,用于图片分类任务。
❑ MNIST/Fashion_MNIST, 手写数字图片数据集,用于图片分类任务。
❑ IMDB, 情感分类任务数据集,用于文本分类任务。

通过 datasets.xxx.load_data()函数即可实现经典数据集的自动加载,其中 xxx 代表具体
的数据集名称,如“CIFAR10”、“MNIST”。 TensorFlow 会默认将数据缓存在用户目录下
的.keras/datasets 文件夹,

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import datasets # 导入经典数据集加载模块
# 加载 MNIST 数据集
(x, y), (x_test, y_test) = datasets.mnist.load_data()
print('x:', x.shape, 'y:', y.shape, 'x test:', x_test.shape, 'y test:',
y_test)
  • 数据加载进入内存后,需要转换成 Dataset 对象, 才能利用 TensorFlow 提供的各种便
    捷功能。通过 Dataset.from_tensor_slices 可以将训练部分的数据图片 x 和标签 y 都转换成
    Dataset 对象:

  • train_db = tf.data.Dataset.from_tensor_slices((x, y)) # 构建 Dataset 对象
    

随机打散

  • 通过 Dataset.shuffle(buffer_size)工具可以设置 Dataset 对象随机打散数据之间的顺序,
    防止每次训练时数据按固定顺序产生,从而使得模型尝试“记忆”住标签信息,代码实现
    如下:

  • train_db = train_db.shuffle(10000) # 随机打散样本,不会打乱样本与标签映射关系
    

批训练

  • 为了利用显卡的并行计算能力,一般在网络的计算过程中会同时计算多个样本,我们
    把这种训练方式叫做批训练,其中一个批中样本的数量叫做 Batch Size。为了一次能够从
    Dataset 中产生 Batch Size 数量的样本,需要设置 Dataset 为批训练方式,实现如下:

  • train_db = train_db.batch(128) # 设置批训练, batch size 为 128
    

预处理

  • 从 keras.datasets 中加载的数据集的格式大部分情况都不能直接满足模型的输入要求,
    因此需要根据用户的逻辑自行实现预处理步骤。 Dataset 对象通过提供 map(func)工具函
    数, 可以非常方便地调用用户自定义的预处理逻辑, 它实现在 func 函数里。例如,下方代
    码调用名为 preprocess 的函数完成每个样本的预处理

  • # 预处理函数实现在 preprocess 函数中,传入函数名即可
    train_db = train_db.map(preprocess)
    

循环训练

  • for epoch in range(20): # 训练 Epoch 数
    	for step, (x,y) in enumerate(train_db): # 迭代 Step 数
    		# training...
    #此外, 也可以通过设置 Dataset 对象,使得数据集对象内部遍历多次才会退出,实现如下:
    train_db = train_db.repeat(20) # 数据集迭代 20 遍才终止
    

总结

TensorFlow基本语句,和张量概念,一些预处理函数,但无整体神经网络搭建逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值