Python+Tensorflow机器学习实战
上QQ阅读APP看书,第一时间看更新

2.1 TensorFlow基础框架

2.1.1 系统框架

虽然TensorFlow框架的版本在不断更新,但是其系统架构并没有发生根本性的改变。它以不同功能需求进行分层处理,以统一接口屏蔽具体实现,从而集中各自的关注层次,更好地提升TensorFlow的适用性,系统架构如图2.1所示。

图2.1 系统框架参考https://tensorflow.google.cn/extend/architecture。

从中可以很明显地看出,TensorFlow系统框架分为三层,由上而下依次是应用层、接口层和核心层。

1.应用层

应用层是TensorFlow框架的最上层,主要提供了机器学习相关的训练库、预测库以及针对Python、C++和Java等编程语言的编程环境,便于不同编程语言在应用层通过接口层调用TensorFlow核心功能以实现相关实验和应用。可以将应用层理解为系统的前端,这样便于使用Python等语言进行编程,主要实现对计算图的构造。

2.接口层

接口层是对TensorFlow功能模块的封装,便于其他语言平台调用。

3.核心层

核心层是TensorFlow进行运算学习的最重要部分,包括设备层、网络层、数据操作层和图计算层。可以将核心层理解为系统的后端,它对前端提出的计算命令进行具体的计算。

(1)设备层

设备层主要包括TensorFlow在不同硬件设备上的实现,主要支持CPU、GPU和Mobile等不同设备。通过在不同的硬件设备上实现计算命令转换,给上层提供统一的接口,实现程序的跨平台功能。

(2)网络层

网络层主要包括RPC(Remote Procedure Call,远程过程调用)和RDMA(Remote Direct Memory Access,远程直接内存访问)通信协议,主要实现不同设备间的数据传输和更新,这些协议都会在分布式计算中用到。

(3)数据操作层

数据操作层以Tensor为处理对象,实现Tensor的各种操作或计算。这些操作包括MatMul等计算操作,也包含Queue等非计算操作。

(4)图计算层

图计算层中主要包括分布式计算图和本地计算图的实现,主要实现了图的创建、编译、优化和执行等部分。

2.1.2 系统的特性

TensorFlow的系统架构具备许多特性,在官网中着重介绍了它的高度灵活性(Deep Flexibility)、真正的可移植性(True Portability)、连接研究与产品(Connect Research and Production)、自动微分(Auto-Differentiation)、多语言选择(Language Options)以及最大化性能(Maximize Performance)六大特性。

1.高度灵活性

TensorFlow不是一个死板的神经网络库,只要能够将计算表示成数据流图,驱动计算的内部循环就可以使用TensorFlow来实现。除了系统提供的神经网络中的常见子图外,还要能编写TensorFlow之上的库,这样可以极大地减少重复代码量。

2.真正的可移植性

TensorFlow可以运行在CPU和GPU上,也可以在桌面端、服务器、移动端、云端服务器和Docker等各类终端上运行。只要有实现机器学习的想法,无需任何特定的硬件就能完成基础的尝试。

3.连接研究与产品

可以让产品研究人员更快地将想法变为产品,可以让学术研究人员更直接地共享代码,具有更大的科学产出率。过去将机器学习想法从研究转变成产品时,一般都需要大量的代码重写工作,现在研究人员在TensorFlow中进行新算法的实验,产品团队用TensorFlow来训练模型并实时地使用模型为真实的消费者服务。

4.自动微分

TensorFlow能够自动完成微分计算操作。在基于梯度的机器学习算法中求微分是重要的步骤,使用TensorFlow完成机器学习,只需要定义预测模型的计算结构、目标函数,然后添加数据便能完成微分计算。

5.多语言选择

TensorFlow附带了Python、C++和Java等接口来构建用户程序,后续还会附带Lua、JavaScript或R等。

6.最大化性能

TensorFlow对线程、队列和异步计算具有一流的支持,可以让你最大限度地利用可用硬件,即使拥有具有32核CPU和4块GPU的工作站,TensorFlow也可以将TensorFlow中的计算需求分配到CPU和GPU中,实现同时计算的效果,从而最大化地利用硬件资源。

2.1.3 编程模型

TensorFlow有自己的设计理念和编程模型,理解其编程模型是后续进行机器学习的基础。

TensorFlow的设计理念以数据流为核心,当构建相应的机器学习模型后,使用训练数据在模型中进行数据流动,同时将结果以反向传播的方式反馈给模型中的参数,以进行调整,使用调整后的参数对训练数据再次进行迭代计算。

所以,可以将TensorFlow理解为一张计算图中“张量的流动”,其由Tensor和Flow两部分组成。Tensor(张量)代表了计算图中的边,Flow(流动)代表了计算图中因节点所做的操作而形成的数据流动。

下面通过一张基础的数据流图来说明数据流图中的各个要素,如图2.2所示。

该图的计算过程是回归模型计算,在图中数据由下向上运行,主要包括输入(Input)、重塑(Reshape)、ReLu层(ReLu Layer)、Logit层(Logit Layer)、Softmax方法、交叉熵(Cross Entropy)、梯度(Gradient)、SGD训练(SGD Trainer)等步骤。

计算过程从输入开始,经过重塑成为统一格式,然后进行下一步运算。

在ReLu层有两个参数:Wh1bh1。使用ReLu层的激活函数进行非线性计算处理后,进入Logit层。

在Logit层有另外两个学习参数:Wsmbsm,用于存储计算的结果。

完成计算后使用Softmax方法计算出各类输出结果的概率分布。同时,用交叉熵度量源样本概率分布和输出结果概率分布之间的相似性。然后使用Wh1bh1Wsmbsm以及交叉熵结果来计算梯度,随后进入SGD训练。

在SGD训练中,通过梯度计算值反向传播,依次更新bsmWsmbh1Wh1,然后再次进行计算,不断地进行迭代学习。

图2.2 数据流图参考http://tensorfly.cn/images/tensors_flowing.gif。

2.1.4 编程特点

TensorFlow除了以数据流为核心外,在编程实现过程中还具备两大特点。

1.将图的定义和图的运行完全分开

使用TensorFlow进行编程与使用Python等进行编程有明显的区别。在使用Python进行编程时,只要定义了相关变量以及运算,在程序运行时就会直接执行相关运算得到结果。但是,在TensorFlow中,需要预先定义各种变量,建立相关数据流图,在数据流图中定义各种变量之间的计算关系,以此完成图的定义。此时,图只是运算规则,没有任何实际数据,需要把运算的输入数据放进去后,才会形成输出值。

2.图的计算在会话中执行

TensorFlow的相关计算在图中进行定义,而图的具体运行环境在会话(Session)中。只有开启会话后,才可以使用相关数据去填充节点,这样才能开始计算;关闭会话后,就不能再进行计算了。

为了更直观地感受TensorFlow编程的特点,下面分别使用Python的编程思路和TensorFlow的编程思路来实现简单的数学计算。

例如,我们需要计算y=a*b+c,其中a=3,b=4,c=5。

在Python中,直接进行变量以及运算的定义,最后打印输出,具体实现如下:

  
     01 a=3
     02 b=4
     03 c=5
     04 y=a*b+c
     05 print(y)

运行上述代码后会直接输出最终的计算结果17。

在TensorFlow中,我们也输入类似的代码:

  
     01 import tensorflow as tf
     02 a=3
     03 b=4
     04 c=5
     05 y=tf.add(a*b、c)
     06 print(y)

运行上述代码,具体输出如下:

  
     Tensor("Add:0"、 shape=()、 dtype=int32)

可以看出并没有输出运算结果,而是输出了一个Tensor,这是因为我们仅仅完成了图的定义,而没有具体进行运算。

如果需要在TensorFlow中实现该运算,就需要满足TensorFlow中计算的几个阶段,首先定义计算图,然后创建会话,最后完成计算。具体实现如下:

为了便于对比,在完成图的创建后以及计算完成后分别输出了结果,详细的代码含义将在后续章节中讲解,运行结果如下:

  
     Tensor("Add_2:0"、 shape=()、 dtype=float32)
     17.0

可以看出,只有在会话中完成计算后才会输出计算结果17。

TensorFlow采用这样的设计主要是因为它是针对机器学习的框架,消耗最多的是对输入数据的训练。这样设计的好处在于当进行计算时,图已经确定,计算就是一个不断迭代优化的过程。