char5-TF高阶操作
第五章主要是介绍了TensorFlow2
的几个高阶操作,包含:
- 合并与分割
- 数据统计
- 张量比较
- 填充与复制
- 数据限幅
- 张量的高级操作
- 数据加载及预处理
合并与分割
合并
将多个张量在一个维度上合并成一个张量。合并有分为两种:拼接concatenate
和堆叠stack
。
- 拼接
tf.concat(x, axis)
- 不会产生新的维度
- 约束条件是:非合并的维度必须是一致的
axis
指定拼接的轴;x
条件是待合并的张量
1 | import tensorflow |
- 堆叠
tf.stack(x, axis)
- 创建新的维度,新维度的位置是任意的
- 可以同时堆叠多个张量
- 进行堆叠的张量维度必须一致
axis
的用法和tf.expand_dims
中相同:- $axis \geq 0$ 表示当前维度之前插入
- $axis < 0$表示当前维度之后插入
1 | import tensorflow |
分割
合并的逆操作,将一个张量分成多个张量,通过tf.split(x,axis,num_or_size_splits)
实现
x
:待分割张量axis
:分割的维度索引号num_or_size_splits
:切割方案- 当
num_or_size_splits
为单个数值时,如10,表示切割 为 10 份 - 当
num_or_size_splits
为List
时,每个元素表示每份的长度,如[2,4,2,2]表示 切割为 4 份,每份的长度分别为 2,4,2,2
- 当
1 | x = tf.random.normal([10,35,8]) |
如果希望在某个维度上全部按照长度为1进行分割,使用tf.unstack
,切割长度固定为1。
1 | x = tf.random.normal([10,35,8]) |
数据统计
向量范数Vector norm
通过函数tf.norm(x, ord)
x
:表示张量norm
:指定范数类型
常见的3
种范数有:
-
$L_1$范数:所有元素绝对值之和
$$
||x||1=\sum{i=1}|x_i|
$$ -
$L_2$范数:所有元素的平方和,再开根号
$$
||x||_2=\sqrt{\sum_i|x_i|^2}
$$
- 无穷范数:所有元素绝对值的最大值
$$
||x||_\infin = max_i(|x_i|)
$$
1 | import numpy as np |
最大/最小、均值、和
函数 | 作用 |
---|---|
tf.reduce_max | 最大 |
tf.reduce_min | 最小 |
tf.reduce.mean | 均值 |
tf.reduce_sum | 和 |
上述的函数都可以指定axis
;如果不指定,tf.reduce_.*
函数会求解出全局元素的最大、最小、均值、和。
1 | out = tf.random.normal([4,10]) |
最值的索引号
通过tf.argmax(x, axis)
和tf.argmin(x, axis)
1 | out = tf.random.normal([2,10]) |
张量比较
tf.equal(a,b)
和tf.math.equal(a,b)
比较两个张量是否相等,返回的是布尔型张量
1 | out = tf.random.normal([100,10]) |
填充与复制
填充tf.pad
需要补充的信号开始或者结束处填充足够的特定数值;通过tf.pad(x, axis)
实现
1 | a = tf.constant([1,2,3,4,5]) |
在NLP中,需要加载不同长度的句子,需要设定一个阈值来固定最大的句子长度
1 | total_words = 10000 |
keras.preprocessing.sequence.pad_sequences
迅速完成句子的填充与截断工作
复制tf.tile
tf.tile()
函数实现长度为1的维度复制的功能;tf.tile()
函数可以在任意维度将数据重复复制多份
1 | x = tf.random.normal([4,32,32,3]) |
数据限幅
tf.maximum()
实现下限幅tf.minimum()
实现上限幅tf.clip_by_vlaue
实现双边限幅
1 | x = tf.range(9) |
高级操作
tf.gather
根据索引号收集数据tf.gather
;对于不规则的索引也非常适合。索引从0开始
1 | x = tf.random.uniform([4,35,8],maxval=100,dtype=tf.int32) |
假设希望:抽查第 2 个班级的第 2 个同学的所有科目, 第 3 个班级的第 3 个同学的所有科目,第 4 个班级的第 4 个同学的所有科目。那么怎么实现呢?
方法1
分别取出3个,再进行堆叠stack操作
1 | x = tf.random.uniform([4,35,8],maxval=100,dtype=tf.int32) |
tf.gather_nd
指定每次采样点的坐标来实现采样多个点的目的。上面问题的解决
1 | tf.gather_nd(x, [[1,1], [2,2], [3,3]]) |
tf.boolean_mask
通过掩码的方式来获取数据采样;掩码的长度必须和对应维度的长度一致
1 | x = tf.random.uniform([4,35,8],maxval=100,dtype=tf.int32) |
多维度掩码采样方式
希望采样第 1 个班级的第 1-2 号学生,第 2 个班级的第 2-3 号学生
1 | x = tf.random.uniform([2,3,8],maxval=100,dtype=tf.int32) |
tf.where
- 通过
tf.where(cond, a, b)
操作可以根据cond
条件的真假从a
或b
中读取数据 - 当
a=b=None
即a,b
参数不指定时,``tf.where会返回
cond张量中所有
True`的元素的索引坐标
1 | a = tf.ones([3,3]) # 构造 a 为全 1 |
demo
获取张量中的正数及其索引
1 | x = tf.random.normal([3,3]) # 构造 a |
scatter_nd
通过tf.scatter_nd(indices, updates,shape)
实现刷新张量的部分数据。只能在全0张量的白板上进行刷新,可能需要结合其他操作来实现现有张量的数据刷新功能。
- shape:白板的形状
- indices:需要刷新数据的索引
- updates:需要插入进去的新数据
1 | indices = tf.constant([[4], [3], [1], [7]]) # 索引位置 |
tf.meshgrid
通过tf.meshgrid
方便地生成二维网格采样点坐标,方便可视化
1 | x = tf.linspace(-8.,8,100) # 设置 x 坐标的间隔 |
数据加载操作
常用数据
Boston Housing
波士顿房价趋势数据集,用于回归模型训练与测试- CIFAR10/100 真实图片数据集,用于图片分类任务
- MNIST/Fashion_MNIST 手写数字图片数据集,用于图片分类任务
- IMDB 情感分类任务数据集
数据处理过程
在TF中,keras.datasets
模块提供经典数据的自动下载、管理、加载等功能
- 数据集合对象
tf.data.Dataset
- 数据加载
datasets.xxx.load_data()
其中,CIFAR10、MNIST
数据集返回的是两个元组,一个保存训练的数据,一个保存的是测试的数据。
1 | import tensorflow as tf |
- 数据转成
Dataset
对象
数据加载进入内存后,需要转换成 Dataset
对象,以利用TensorFlow
提供的各种便捷功能
1 | train_db = tf.data.Dataset.from_tensor_slices((x, y)) |
- 随机散打
通过函数Dataset.shuffle(buffer_size)
来实现,buffer_size
指定缓冲池的大小,一般设置成一个较大的数字
- 批训练
一般在网络的计算过程中会同时计算多个样本,这种方式叫做批训练
- 样本数量:batch size
1 | train_db = train_db.batch(128) # 将Dataset设置成批训练方式 |
- 预处理
Dataset
对象通过提供map(func)
工具函数来实现预处理
1 | # 预处理函数实现在 preprocess 函数中,传入函数引用即可 |
- 循环训练
- step:完成一个batch的数据训练
- 通过多个step来完成整个训练集的一次迭代
1 | for epoch in range(20): # 训练 Epoch 数 |