
2.2 TensorFlow
2.2.1 TensorFlow简介
TensorFlow是一个采用数据流图(Data Flow Graphs)用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(Edges)表示在节点间相互联系的多维数据数组,即张量(Tensor)。它灵活的架构使用户可以在多种平台上展开计算,如台式计算机中的一个或多个CPU(或GPU)、服务器、移动设备等。TensorFlow最初由Google大脑小组(隶属于Google机器智能研究机构)的研究员和工程师们开发出来,用于机器学习和深度神经网络方面的研究,但这个系统的通用性使其也可广泛用于其他计算领域。
2.2.2 数据流图
如图2.4所示,数据流图用“结点”(Nodes)和“线”(Edges)的有向图来描述数学计算。“节点”一般用来表示施加的数学操作,但也可以表示数据输入(Feed In)的起点/输出(Push Out)的终点,或者是读取/写入持久变量(Persistent Variable)的终点。“线”表示“节点”之间的输入/输出关系。这些数据“线”可以输运“size可动态调整”的多维数据数组,即“张量”。张量从图中流过的直观图像是这个工具取名为“TensorFlow”的原因。一旦输入端的所有张量准备完成,节点将被分配到各种计算设备完成异步并行地执行运算。

图2.4 数据流图
2.2.3 TensorFlow的特点
TensorFlow不是一个严格的“神经网络”库。只要用户可以将计算表示为一个数据流图就可以使用TensorFlow。用户负责构建图,描写驱动计算的内部循环,TensorFlow提供有用的工具来帮助用户组装“子图”,当然用户也可以在TensorFlow基础上写自己的“上层库”。定义新复合操作与写一个Python函数一样容易。TensorFlow的可扩展性相当强,如果用户找不到想要的底层数据操作,也可以自己写一些C++代码来丰富底层的操作。
TensorFlow可在CPU和GPU上运行,如在台式机、服务器、手机移动设备等。TensorFlow支持将训练模型自动在多个CPU上规模化运算,以及将模型迁移到移动端后台。
基于梯度的机器学习算法会受益于TensorFlow自动求微分的能力。作为TensorFlow用户,只需要定义预测模型的结构,将这个结构和目标函数(Objective Function)结合在一起,并添加数据,TensorFlow将自动为用户计算相关的微分导数。计算某个变量相对于其他变量的导数仅仅是通过扩展图来完成的,所以用户能一直清楚看到究竟在发生什么。
TensorFlow还有一个合理的C++使用界面,也有一个易用的Python使用界面来构建和执行graphs。用户可以直接写Python/C++程序,也可以用交互式的Ipython界面来用TensorFlow尝试些想法,它可以帮用户将笔记、代码、可视化等有条理地进行归置。
2.2.4 TensorFlow的计算形式
TensorFlow中的Flow代表流,是其完成运算的基本方式。流是指一个计算图或简单的一个图,图不能形成环路,图中的每个节点代表一个操作,如加法、减法等。每个操作都会形成新的张量。
如图2.5所示一个简单的计算图,所对应的表达式为:e=(a+b)×(b+1),计算图具有属性:叶子顶点或起始顶点始终是张量。意即,操作永远不会发生在图的开头,由此可以推断,图中的每个操作都应该接受一个张量并产生一个新的张量。同样,张量不能作为非叶子节点出现,这意味着它们应始终作为输入提供给操作/节点。计算图总是以层次顺序表达复杂的操作,通过将a+b表示为c,将b+1表示为d,可以分层次组织上述表达式。因此,可以将e写为e=(c)×(d),这里c=a+b且d=b+1,以反序遍历图形而形成子表达式,这些子表达式组合形成最终表达式。当正向遍历时,遇到的顶点总是成为下一个顶点的依赖关系,如没有a和b就无法获得c,同样,如果不解决c和d则无法获得e。同级节点的操作彼此独立,这是计算图的重要属性之一。当按照图中所示的方式构造图时,很自然的是,在同一级中的节点,如c和d,彼此独立,这意味着没有必要在计算d之前计算c。因此它们可以并行执行。

图2.5 计算图
计算图的并行属性是最重要的属性之一,它清楚地表明:同级的节点是独立的,这意味着在c被计算之前不需空闲,可以在计算c的同时并行计算d。TensorFlow充分利用了这个属性。
TensorFlow允许用户使用并行计算设备更快地执行操作。计算的节点或操作自动调度进行并行计算。这一切都发生在内部,例如在图2.5中,可以在CPU上调度操作c,在GPU上调度操作d。图2.6展示了两种分布式执行的过程。

图2.6 TensorFlow并行
图2.6中,第一种是单个系统分布式执行,其中单个TensorFlow会话(将在稍后解释)创建单个worker,并且该worker负责在各设备上调度任务。在第二种系统下,有多个worker,它们可以在同一台机器上或不同的机器上,每个worker都在自己的上下文中运行。图2.6中,worker进程1运行在独立的机器上,并调度所有可用设备进行计算。
计算子图是主图的一部分,其本身就是计算图。如在图2.5中可以获得许多子图,其中之一如图2.7所示。

图2.7 计算子图
图2.7是主图的一部分,从属性2可以看出子图总是表示一个子表达式,因为c是e的子表达式。子图也满足最后一个属性。同一级别的子图也相互独立,可以并行执行。因此可以在一台设备上调度整个子图。
如图2.8所示解释了子图的并行执行。这里有2个矩阵乘法运算,因为它们都处于同一级别,彼此独立,这符合最后一个属性。由于独立性的缘故,节点安排在不同的设备gpu_0和gpu_1上。

图2.8 子图调度
TensorFlow将其所有操作分配到由worker管理的不同设备上。更常见的是,worker之间交换张量形式的数据,如在e=(c)*(d)的图表中,一旦计算出c,就需要将其进一步传递给e,因此Tensor在节点间前向流动,如图2.9所示。

图2.9 worker间信息传递
通过以上介绍,希望读者可以对TensorFlow的一些基本特点和运转方式有大致了解。