深度学习|Tensorflow2.0进阶
01
合并和分割
合并是指将多个张量在某个维度上合并为一个张量,比如我们要将某学校所有的考试成绩单进行合并,张量A中记录了该学校1-4班的50名学生的9门科目的成绩,此时对应的shape就是[4,50,9],张量B记录了5-10班的成绩,此时的shape就是[6,50,9],我们合并这两个张量就能够得到该学校全部成绩的张量C为[10,50,9],此时张量合并的用处就得以体现了。
张量的合并可以通过拼接和堆叠来实现,拼接操作并不会产生新的维度,仅在现有的维度上合并,而堆叠会创建新维度。选择使用拼接还是堆叠操作来合并张量,取决于具体的场景是否需要创建新维度。
拼接
我们可以直接使用Tensorflow中的tf.concat(tensors,axis)函数拼接张量:
- tensors:所有需要合并的张量List。
- axis:参数指定需要合并的维度索引。
需要注意的是,拼接的时候我们要保证非合并维度的长度必须是一致的。
对于我们最开始举的例子,代码实现方式如下:
import tensorflow as tf
import numpy as np
a = tf.random.normal([4, 50, 9])
b = tf.random.normal([6, 50, 9])
c = tf.concat([a, b], axis=0)
# print(c.shape)
# (10, 50, 9)
# 尝试对其他的纬度进行拼接
a = tf.random.normal([5, 50, 6])
b = tf.random.normal([5, 50, 7])
c = tf.concat([a, b], axis=2)
# print(c.shape)
# (5, 50, 13)
堆叠
我们上面使用到的拼接操作是在现有的维度上合并数据,并不会创建新的维度,如果我们在合并数据时,希望创建一个新的维度,则需要使用tf.stack操作。比如我们要将两个班级的考试成绩单进行合并,张量A中记录了第一个班级的50名学生的9门科目的成绩,此时对应的shape就是[50,9],张量B记录了第二个班级的成绩,此时的shape也是[50,9],我们合并这两个张量就能够得到该学校全部成绩的张量C为[2,50,9],此时我们就可以使用堆叠的操作来创建一个新的维度。
我们可以直接使用tf.stack(tensors,axis)进行多个张量的堆叠:
- tensors:所有需要合并的张量List。
- axis:指定新维度插入的位置,和expand_dims一致。
需要注意的是,在进行堆叠操作的时候要保证所有张量的纬度是一致的。
axis对应值的插入位置如下图所示:
代码的实现方式如下:
a = tf.random.normal([35, 8])
b = tf.random.normal([35, 8])
c = tf.stack([a, b], axis=0)
# print(c.shape)
# (2, 35, 8)
d = tf.stack([a, b], axis=-1)
# print(d.shape)
# (35, 8, 2)
分割
既然我们可以进行合并操作,那么同样我们也可以进行逆向的分割操作,将一个张量拆分为多个张量,用我们之前的成绩单数据,整个学校的数据为[10,50,9]现在我们把它分为10个张量,每个张量保存对应班级的成绩单。
我们可以直接使用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:制定分割的维度索引。
代码实现方式如下:
x = tf.random.normal([10, 35, 8])
y = tf.split(x, 10, axis=0)
print(len(y))
print(y[0].shape)
# 10
# (1, 35, 8)
02
数据统计
在进行神经网络计算的时候,我们通常需要统计数据的各种属性,如均值、最值、众数等信息,但是对于复杂的张量,我们往往不能通过观察数据来获取有用的信息,下面来学习一下数据统计的方法。
向量范数
向量范数是表征向量“长度”的一种度量方法,它可以推广到张量上,在神经网络中我们通常用来表示张量的权值大小,梯度大小等,常用的向量范数有:
- L1范数:向量x的所有元素绝对值之和。
- L2范数:向量x的所有元素的平方和开根号。
- ∞-范数:向量x的所有元素绝对值的最大值。
我们可以使用tf.norm(x,ord)求解张量的范数:
- x:要求解的张量
- ord:范数选择(1、2代表L1、L2,np.inf代表∞)
代码实现方式如下:
x = tf.ones([2, 2])
# 计算L1范数
tf.norm(x, ord=1)
# 计算L2范数
tf.norm(x, ord=2)
# 计算∞范数
tf.norm(x, ord=np.inf)
# 1.0
其他的数据统计
我们可以使用tensorflow进行简单的数据统计,常用的函数如下:
- 最大值:tf.reduce_max()
- 最小值:tf.reduce_min()
- 均值:tf.reduce_mean()
- 和:tf.reduce_sum()
- 最大值的索引:tf.argmax()
- 最小值的索引:tf.argmin()
x = tf.random.normal([4, 10])
# 计算某个维度上的最大值
tf.reduce_max(x, axis=1)
# 计算全局的最大值
tf.reduce_max(x)
# 计算某个纬度的最小值
tf.reduce_min(x, axis=1)
# 计算全局的最小值
tf.reduce_min(x)
# 计算某个维度的均值
tf.reduce_mean(x, axis=1)
# 计算全局的均值
tf.reduce_mean(x)
# 计算某个维度的和
tf.reduce_sum(x, axis=1)
# 计算全局的和
tf.reduce_sum(x)
# 得到最大值的索引
tf.argmax(x)
# 得到最小值的索引
tf.argmin(x)
03
张量比较
通常我们会涉及到对两个张量进行比较的操作,tensorflow中常用的比较函数如下:
函数 |
比较逻辑 |
---|---|
tf.math.greater |
|
tf.math.less |
|
tf.math.greater_equal |
|
tf.math.less_equal |
|
tf.math.not_equal |
|
tf.equal |
|
tf.math.is_nan |
04
填充和复制
填充
对于很多图片数据来说,长度宽度总是不同的,这也导致我们很难对不同维度之间的数据进行运算,此时就需要我们将不同长度的数据扩充为相同的长度,使得二者之间可以进行运算,通常的做法是,在需要补充长度的数据开始或结束处填充足够数量的特定数值,这些特定数值一般代表了无效意义,例如0,使得填充后的长度满足系统要求。那么这种操作就叫作填充 (Padding)。
举个例子
我们考虑下面两个句子:
- I like python.
- I like python too.
算上标点,我们对其进行数字编码,可以变成如下的形式:
- [1,2,3,4]
- [1,2,3,5,4]
对于第一个句子,我们就需要进行一个填充操作,在末尾填充若干个0变成如下的形式:
- [1,2,3,4,0]
这样我们就能进行运算操作了。
Tensorflow中填充操作可以用tf.pad(x,padding)实现:
- x:需要填充的张量。
- padding:嵌套list,比如[[0,3]]表示在第一个维度左边不填充,右边填充3个单元。
代码的实现方式如下:
a = tf.constant([1, 2, 3, 4])
b = tf.constant([1, 2, 3, 5, 4])
a = tf.pad(a, [[0, 1]])
# 将两个句子堆叠合并
tf.stack([a, b], axis=0)
复制
之前我们了解过,通过tf.tile()函数可以实现长度为1的维度复制功能,其实我们还可以进行任意维度的复制操作。
代码实现方式如下:
x = tf.random.normal([4, 32, 32, 3])
tf.tile(x, [2, 2, 1, 1])
# shape=(8, 64, 32, 3)
05
数据限幅
在很多的场景中,我们需要限制元素的范围。
Tensorflow中也提供了数据限幅的方法,我们可以通过tf.maximum(x,a)实现数据的下限幅,此时的数据将会大于a,同样我们可以通过tf.minimum(x,a)实现数据的上限幅,此时的数据将会小于a,tf.clip_by_value(x,a,b)函数实现上下限幅,此时的数据将会在a和b之间。
代码实现方式如下:
x = tf.range(9)
tf.maximum(x,2)
# [2, 2, 2, 3, 4, 5, 6, 7, 8]
tf.minimum(x,7)
# [0, 1, 2, 3, 4, 5, 6, 7, 7]
tf.clip_by_value(x,2,7)
# [2, 2, 2, 3, 4, 5, 6, 7, 7]
- 猫哥网络编程系列:详解 BAT 面试题
- SpringMVC中@RequestBody引起的400异常处理,返回校验失败具体信息
- 关于primary key和unique index的奇怪问题 (58天)
- 在centos7上安装Jenkins
- Spring resource bundle多语言,单引号format异常
- String的内存模型,为什么String被设计成不可变的
- Ubuntu安装Java8和Java9
- session跟踪失效的问题和分析(57天)
- 第1章:初识编程
- 十分钟学会 tmux
- 网络慢?看看路由器设置对不对
- 为什么房间的 Wi-Fi 信号这么差
- 照着官方文档学习react
- 用R语言写个贝叶斯模型 预测我的妻子是否怀孕
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP实现微信对账单处理
- Win10下配置tensorflow-gpu的详细教程(无VS2015/2017)
- PHP Include文件实例讲解
- ThinkPHP5.1框架页面跳转及修改跳转页面模版示例
- Python Switch Case三种实现方法代码实例
- PHP正则表达式笔记与实例详解
- php实现微信分享朋友链接功能
- python交互模式基础知识点学习
- 浅析Python 抽象工厂模式的优缺点
- 基于PyTorch的permute和reshape/view的区别介绍
- Laravel配置全局公共函数的方法步骤
- PHP5.5基于mysqli连接MySQL数据库和读取数据操作实例详解
- python–shutil移动文件到另一个路径的操作
- PHP正则表达式处理函数(PCRE 函数)实例小结
- yii2的restful api路由实例详解