1.5 TensorFlow的主要依赖包
本节将介绍TensorFlow依赖的两个最主要的工具包——Protocol Buffer和Bazel。虽然TensorFlow依赖的工具包不仅限于这两个,但Protocol Buffer和Bazel是相对比较重要的,用户在使用TensorFlow的过程中很有可能会接触到。
1.5.1 Protocol Buffer包
Protocol Buffer包是谷歌公司开发的一种数据描述语言,可用于数据存储、通信协议等方面。它不依赖于语言和平台且可扩展性很强。Protocol Buffer的结构化数据是什么呢?假设要记录一些用户信息,包括每个用户的名字、ID 和 E-mail 地址等信息,那么其结构形式为:
上面的用户信息就是一个结构化数据。此处介绍的结构化数据指的是拥有多种属性的数据,如上述用户信息中包含名字、ID 和 E-mail 地址 3 种不同属性,那么它就是一个结构化数据。要将这些结构化的用户信息持久化或者进行网络传输,就需要先将它们序列化。何为序列化?就是将结构化的数据变成数据流的格式(变为一个字符串)。将结构化的数据序列化,并从序列化之后的数据流中还原出原来的结构化数据,统称为处理结构化数据,这就是Protocol Buffer包解决的主要问题。
除Protocol Buffer之外,XML和JSON是两种比较常用的结构化数据处理工具。
Protocol Buffer格式的数据和XML或JSON格式的数据有比较大的区别:首先,Protocol Buffer序列化之后得到的数据是二进制流;其次,XML或JSON格式的数据信息都包含在了序列化之后的数据中,不需要任何其他信息就能还原序列化之后的数据。
Protocol Buffer是TensorFlow系统中使用到的重要工具,TensorFlow中的数据基本都是通过Protocol Buffer来组织的。
1.5.2 Bazel包
Bazel是从谷歌开源的自动化构成工具,谷歌内部大部分的应用都是通过它来编译的。Bazel 在速度、可伸缩性、灵活性以及对不同程序语言和平台的支持上都要更加出色。本节将简单介绍Bazel是怎样工作的。
workspace(工作空间)是Bazel的一个基本概念。一个workspace可以简单地理解为一个文件夹,在这个文件夹中包含了编译一个软件所需要的源代码以及输出编译结果的链接地址。一个 workspace 所对应的文件夹是这个项目的根目录,在这个根目录中需要有一个workspace文件,此文件定义了对外部资源的依赖关系。
在一个workspace内,Bazel通过BUILD文件来找到需要编译的目标。BUILD文件采用一种类似于Python的语法来指定每一个编译目标的输入、输出以及编译方式。Bazel的编译方式是事先定义好的。Bazel对Python支持的编译方式有3种:py_binary、py_library和by_test。其中py_binary将Python程序编译为可执行文件,py_test将Python编译为测试程序,py_library将Python程序编译为库函数,供其他py_binary或py_test调用。
下面给出一个简单的样例来说明 Bazel 是如何工作的。如下面的代码所示,在样例项目空间中有4个文件:workspace、BUILD、hello_world.py和hello.lib.py。
workspace 给出此项目的外部依赖关系。为了简单起见,这里使用一个空文件,表明这个项目没有对外部的依赖。hello_lib.py完成打印“Hello World”的简单功能,它的代码为:
hello_world.py通过调用hello_lib.py中定义的函数来完成输出,它的代码为:
在BUILD文件中定义的两个编译目标:
从这个样例中可看出,BUILD文件是由一系列编译目标组成的。定义编译目标的先后顺序不会影响编译的结果。在每一个编译目标的第一行要指定编译方式,在这个样例中就是py_library或者py_binary。在样例中hello_world.py需要调用hello_lib.py中的函数,所以hello_world的编译目标中将hello_lib作为依赖关系。