【Tensorflow】菜鸟学TensorFlow 2.0:TensorFlow2.0基础知识讲解
1. 简介
TensorFlow 是一种用于表达机器学习算法的接口,也是一种用于执行此类算法的实现。它是端到端的方式进行机器学习开发,可以帮助我们开发和训练机器学习模型。
- 可用于表达各种各样的算法(包括用于深度神经网络模型的训练和推理算法),并且已用于进行研究以及将机器学习系统部署到计算机科学等十几个领域中,包括
语音识别
、计算机视觉
、机器人
、信息检索
、自然语言处理
、地理信息提取
和计算药物发现
。 - 可以使用
Sequential API
来使用TensorFlow
,也可以使用Keras API
调用TensorFlow
开源库。初学者推荐使用Keras API
,功能完善,便于开发。 - 在TensorFlow2版本之前,TensorFlow1.x和Keras是分开的,但很多开发者觉得Keras API更友好,开发起来更高效,原生的TensorFlow API过于麻烦;后来TensorFlow2.x合并了Keras,在TensorFlow中能直接使用Keras API。
这里提一下Keras,它是一个独立可以pip安装的库,后端可以选择Mxnet、Theano、TensorFlow;它也是TensorFlow从1.x版本就内置的一个子模块,通过tf.keras使用,这种方法使用只能使用TensorFlow作为运算后端。推荐使用后一种方法使用keras,它和TensorFlow是密不可分的,keras的简洁和TF的灵活必须配合使用,缺一不可。
- 常用的应用开发有:神经网络、推荐系统、生成对抗网络
- TensorFlow使用数据流计算图来表示计算、共享状态以及使该状态发生改变的运算。
全局变量:TensorFlow1.x依赖隐式全局命名空间。当我们调用tf.Variable创建变量时,该变量就会被放进默认的图中,即使我们忘记了指向它的Python变量,它也会留在那里。当我们想恢复这些变量时,我们必须知道该变量的名称,如果我们没法控制这些变量的创建,也就无法做到这点。TensorFlow 1.x中有各种机制旨在帮助用户再次找到他们所创建的变量,而在2.0中则取消了所有这些机制,支持默认的机制:跟踪变量。当我们不再用到创建的某个变量时,该变量就会被自动回收(这和Python的回收机制类似)
2. TensorFlow的特点
轻松地构建模型
:使用Keras
等直观的高阶 API 轻松地构建和训练机器学习模型,该环境使我们能够快速迭代模型并轻松地调试模型。支持多语言
:支持Python、C++、Java等主流语言。灵活开发
:支持云端、本地、浏览器中或设备上轻松地训练和部署模型。强大的研究经验
:一个简单而灵活的架构,可以更快地将新想法从概念转化为代码,然后创建出先进的模型,并最终对外发布。
3. TensorFlow的发展历程
- 高层API,将Keras库整合进其中
很多TensorFlow1.x的API在2.0中被删除或者改变位置,有不少原来的API被全新的API取代了。官方提供了一个工具,可以将1.x的代码升级到2.0,不过不是很实用,很多时候需要人工修改。
- 动态图机制:Eager Execution
Eager execution(动态图机制)从TensorFlow1.8就加入了,但是作为可选操作,默认的一直是Graph execution(静态图机制)。TensorFlow2.0中Eager execution被设置为默认模式。该模式最大的好处在于用户能够更轻松的编写和调试代码,可以使用原生的Python控制语句(原来的TF1只能使用TensorFlow封装的控制语句),大大降低了学习和使用TensorFlow的门槛。在TensorFlow2.0中,图(Graph)和会话(Session)都是底层的实现,用户不需要过多关心。
- 面向移动智能终端:TensorFlow Lite
- 面向网页前端:TensorFlow.js
- 自动生成计算图:AutoGraph
2019:TensorFlow 2.0,目前最新版本是2.5
4. TensorFlow 2 的框架
该框架分为两大部分,左边为训练部分,右边为模型部署。
- read&preprocess data
首先,在读取数据方面,可以使用tf.data加载数据。
使用输入管道读取训练数据,输入管道使用tf.data创建。使用 tf.feature_column描述特征特性,例如离散特征,密集特征乃至于交叉特征。支持从多种文件格式中读取数据。此外还支持内存数据的便捷输入(如Numpy)。之后根据需求对数据进行预处理操作,如数据清洗,归一化等。 - tf.keras
使用tf.keras构建、训练并验证模型。
Keras API使得上手TensorFlow非常容易。重要的是,Keras提供了几个模型构建API(Sequential、Functional以及Subclassing),因此用户可以选择正确的抽象化(abstraction)级别,TensorFlow的实现包含增强功能,包括eager execution
、立即迭代(immediate iteration
)和直观调试(intuitive debugging
),以及tf.data
,用于构建可扩展的输入pipeline。 - Premade Estimators
Estimators评估器
是TensorFlow用于实现一个完整的模型的最高层表示,它可以处理参数初始化、日志记录、保存和恢复模型等功能。另外,TensorFLow提供了很多的预先写好的评估器,包括DNNClassifier
,DNNRegressor
,LinearClassifier
。一开始学习的时候可以直接使用TF提供的这些评估器,有经验之后也可以自己实现一个。
要使用TF预先写好的Estimator,必须依次完成以下工作:- 创建一个或多个输入函数
- 定义模型的特征列
- 实例化estimator对象,并指定特征列和各种超参数
- 在estimator对象上调用一个或多个方法,传递适当的输入函数作为数据源。
- distribution strategy
使用分布式策略进行分布式训练。
对于大型机器学习训练任务,分布式策略API可以轻松地在不同硬件配置上分配和训练模型,无需更改模型的定义。由于TensorFlow支持各种硬件加速器,如CPU,GPU和TPU,因此用户可以将训练负载分配到单节点/多加速器以及多节点/多加速器配置上(包括TPU Pod)。这个API支持多种群集化配置,也提供了在本地或云环境中部署Kubernetes群集训练的模板。 - SaveModel
TensorFlow将对Saved Model进行标准化,作为TensorFlow服务的一部分,它将成为TensorFlow Lite、TensorFlow.js、TensorFlow Hub等格式的可互换格式。
TensorFlow始终为生产提供了直接部署方式。无论是部署在服务器、边缘设备还是Web上,TensorFlow都可以让用户对模型实现轻松训练和部署。无论用户使用何种语言或平台。在TensorFlow 2.0中,我们通过标准化互换格式和API对齐来提高跨平台和组件的兼容性。- TensorFlow服务:TensorFlow库,允许通过HTTP/REST或gRPC/协议缓冲区提供模型。
- TensorFlow Lite:TensorFlow针对移动和嵌入式设备的轻量级解决方案提供了在Android,iOS和嵌入式系统(如Raspberry Pi和Edge TPU)上部署模型的功能。
- TensorFlow.js:允许在JavaScript环境下部署模型,如在Web浏览器或服务器端通过Node.js实现部署。TensorFlow.js还支持使用类似Keras的API在JavaScript中定义模型并直接在Web浏览器中进行训练。
- TensorFlow还支持其他语言,包括C,Java,Go,C#,Rust,Julia,R等。
5. TensorFlow的开发流程
6. TensorFlow为研究提供强大的实验工具
TensorFlow使得从概念到代码和从模型到出版物中获取新想法变得更加容易。TensorFlow 2.0 结合了很多功能,能够在不牺牲速度或性能的情况下定义和训练最先进的模型:
- Keras功能API和Model子类API:允许创建复杂的拓扑,包括使用
残差层
、自定义多输入/输出模型
以及强制编写的正向传递。 - 自定义训练逻辑:用
tf.GradientTape
和tf.custom_gradient
对梯度计算进行细粒度控制。 - 为了获得更强的灵活性和控制,低级 TensorFlow API 始终可用,并与更高级别的抽象一起工作,以实现完全可定制的逻辑。
- TensorFlow 2.0新添了一些附加功能,让研究人员和高级用户可以使用丰富的插件来进行实验,如
Ragged Tensors
、Tensor2Tensor
等。
除了这些功能之外,TensorFlow还提供了易于制作原型和调试的eager execution
,可以大规模训练的 Distribution Strategy API
和 AutoGraph,以及对 TPU 的支持,使 TensorFlow 2.0 成为一个易于使用、可定制和高度可扩展的平台,用于展开最先进的机器学习研究并将该研究转化为生产流水线。
7. 入门案例
使用经典的数据集MNIST,识别手写数字。
# -*- coding: utf-8 -*-#
# -------------------------------------------------------------------------------
# Name: TF0701
# Description:
# Author: PANG
# Date: 2021/7/2
# -------------------------------------------------------------------------------
import tensorflow as tf
if __name__ == '__main__':
# 准备MNIST数据
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 将样本从整数转化为浮点数,由于图片的像素范围是0~255,需要把它变成0~1的范围。
x_train, x_test = x_train / 255.0, x_test / 255.0
# 将模型的各层堆叠起来,以搭建kf.keras.Sequential模型
# 为训练选择优化器和损失函数
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# 训练并验证模型
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test, verbose=2)
8. TensorFlow常见基本概念
这里,只对TensorFlow中的一些基本概念做一个简单的介绍,希望进一步了解这些概念及其实现的读者,可以参考官方的白皮书(主要是15年的)以及TensorFlow官网的一些文档。需要注意的是,这些资料中的部分内容对于TensorFlow2.0来说已经不适用了,读者在阅读的时候需要留意。
1. 计算图
计算图(computation graph)
是一个有向图(directed graph),是对TensorFlow中计算任务的抽象描述,也称为数据流图(data flow graph)
。TensorFlow使用计算图将计算表示成了独立的指令之间的依赖关系,在计算图中,节点表示计算单元(即一个独立的运算操作),图中的边表示计算使用或产生的数据。在TensorFlow1.x版本中,当我们使用TensorFlow低级API进行编程时,我们首先需要定义好计算图,然后创建TensorFlow会话(session)来执行计算图。
在TensorFlow1.x版本中采用的是静态图机制,我们需要预先定义好计算图,然后再可以反复的调用它(1.x版本有提供Eager Execution接口,让用户可以使用动态图)。TensorFlow2.0则采用了动态图机制(1.x版本的Eager Execution在2.0中成为了默认的执行方式),我们可以像执行普通的python程序一样执行TensorFlow的代码,而不再需要自己预先定义好静态图,调试代码也更加容易。TensorFlow1.x的静态图机制一直被用户所诟病,调整为动态图机制是TensorFlow2.0一个最重大的改进,并且其也提供了一些方法来保留静态计算图的一些优势。
TensorFlow1.x中计算图的使用:
- 在TensorFlow程序中,系统会自动维护一个默认的计算图,通过tf.get_default_graph函数可以获取当前默认的计算图。
- 除了使用默认的计算图,TensorFlow还支持通过tf.Graph函数来生成新的计算图。不同计算图上的张量和运算都不会共享。
- TensorFlow中的计算图还提供了管理张量和计算的机制,通过集合(collection)来管理不同类别的资源。
2. 张量
张量(tensor)
可以看作是一个多维的数组或列表,它是对矢量和矩阵的更高维度的泛化,张量由“tf.Tensor”类定义。计算图中的一个运算操作可以获得零个或多个张量作为输入,运算后会产生零个或多个张量输出。这些张量在计算图的边中流动(flow),从一个节点(运算操作)到另一个节点,TensorFlow也因此而得名。
张量具有以下3个属性:
- 名字(name)
- 数据类型(type, 同一个张量中的每个元素都具有相同的数据类型,例如float32、int32以及string)
- 形状(shape, 即张量的维数以及每个维度的大小)
TensorFlow中有一些特殊的张量,以下是一些主要的特殊张量:
tf.Variable
(变量,TensorFlow中的张量一般都不会被持久化保存,参与一次运算操作后就会被丢弃了。变量(variable)是一种特殊的运算操作,它可以将一些需要持久化保存的张量存储在内存或显存中,并会返回一个可以对该变量所引用的张量进行一系列特定操作的句柄,例如Assign和AssignAdd(等同于“+=”)等。模型的参数是保存在变量中的,在模型的训练过程中,参数在不断地更新。变量的值可以修改,但是维度不可以变。)tf.constant
(常量,常量定义时必须初始化值,且定义后其值和维度不可再改变。)tf.placeholder
(占位符,在执行“session.run()”方法时传入具体的值,TensorFlow2.0中不再使用,但依然可以在“tensorflow.compat.v1”模块中找到。)tf.SparseTensor
(稀疏张量)
张量的使用主要可以总结为两大类:
- 对中间计算结果的引用
- 当计算图构造完成之后,张量可以用来获得计算结果。
3. 会话
在1.x版本中,会话(session)
是客户端程序与TensorFlow系统进行交互的接口,我们定义好的计算图必须在会话中执行。当会话被创建时会初始化一个空的图,客户端程序可以通过会话提供的“Extend”方法向这个图中添加新的节点来创建计算图,并通过“tf.Session”类提供的“run”方法来执行计算图。大多数情况下我们只需要创建一次会话和计算图,之后我们可以在会话中反复执行整个计算图或者其中的某些子图。TensorFlow2.0采用了动态图机制,我们不需要在会话中执行计算图了,“tf.Session”类被放到了兼容模块“tensorflow.compat.v1”中,这个模块里有完整的TensorFlow1.x的API。为了保留静态图的优势(例如性能优化和可移植性等),TensorFlow2.0提供了“tf.function”方法,使用“tf.function”修饰的python函数,TensorFlow可以将其作为单个图来运行。
4. 运算操作和运算核
计算图中的每一个节点就是一个运算操作(operation,通常简称op),每一个运算操作都有名称,并且代表了一种类型的抽象运算,例如“MatMul”代表矩阵的乘法。每个运算操作都可以有自己的属性,但是所有的属性都必须被预先设置,或者能够在创建计算图时根据上下文推断出来。
通过设置运算操作的属性可以让运算操作支持不同的张量(tensor)元素类型,例如让向量加法操作运算只接受浮点类型的张量。
运算核(kernel)是一个运算操作在某个具体的硬件(比如CPU或GPU)上的实现,在TensorFlow中可以通过注册机制
加入新的运算操作或者为已有的运算操作添加新的运算核。
运算类型 | 运算示例 |
---|---|
标量运算 | Add, Sub, Mul, Div, Exp, Log, Greater, Less, Equal, … |
向量运算 | Concat, Slice, Split, Constant, Rank, Shape, Shuffle,… |
矩阵运算 | MatMul, MatrixInverse, MatrixDeterminant, … |
带状态的运算 | Variable, Assign, AssignAdd, … |
神经网络组件 | SoftMax, Sigmoid, ReLU, Convolution 2D, MaxPool, … |
模型的保存和恢复 | Save, Restore |
队列及同步运算 | Enqueue, Dequeue, MutexAcquire, MutexRelease, … |
控制流 | Merge, Switch, Enter, Leave, NextIteration |
参考资料
- 《TensorFlow:实战Google深度学习框架》
- https://cloud.tencent.com/developer/article/1824591
- https://blog.csdn.net/sjyttkl/article/details/105926584
- http://www.imooc.com/article/287278
- https://zhuanlan.zhihu.com/p/78589541