第二章:TensorFlow环境搭建
* 2.1
TensorFlow的主要依赖包
* 2.1.1
Protocol Buffer
* 2.1.2
Bazel
* 2.2
TensorFlow安装
* 2.2.1
使用Docker安装
* 2.2.2
使用pip安装
* 2.2.3
从源代码编译安装
* 2.3
TensorFlow测试样例
-2.1- TensorFlow的主要依赖包
本节将介绍 TensorFlow依赖的两个最主要的工具包--
ProtocolBuffer
和Bazel
。
虽然 TensorFlow依赖的工具包不仅限于此节中列出来的两个,但 ProtocolBuffer和 Bazel是笔者 认为相对比较 重要 的,在使用 TensorFlow 的过程中很有可能会接触到。
-2.1.1- Protocol Buffer
* 结构化数据 & 序列化
本节中介绍的
结构化数据
指的是拥有多种属性的数据。
比如用户信息中包含名字、 ID和 E-mail地址三种不同属性,那么它就是一个结构化数据。
要将这些结构化的用户信息持久化或者进行网络传输时,就需要先将它们序列化 。
所谓序列化
,是将结构化的数据变成数据流的格式,简单地说就是变为 一个字符串。
将结构化的数据序列化,井从序列化之后的数据流中还原出原来的结构化数据,统称为处理结构化数据
, 这就是Protocol Buffer
解决的主要问题 。
* 常用的结构化数据处理工具
除 ProtocolBuffer之外, XML和 JSON是两种比较常用的结构化数据处理工具。
* Protocol Buffer 数据量更小,解析更快
Protocol Buffer 格式的数据和 XML 或者 JSON 格式的数据有比较大的区别 。
*
首先, Protocol Buffer序列化之后得到的数据不是可读的字符串,而是二进制流
。
*
其次, XML或JSON格式的数据信息都包含在了序列化之后的数据中,不需要任何其他信息就能还原序列化之后的数据。但使用 Protocol Buffer 时需要先定义数据的格式( schema)
。 还原一个序列化之后的数据将需要使用到这个定义好的数据格式 。
因为这样的差别,ProtocolBuffer序列化出来的数据要比XML格式的数据小3到10倍,解析时间要快20到100倍。
* Protocol Buffer 定义数据格式
Protocol Buffer 定义数据格式的文件 一般保存在
.proto
文件中。
每 一个 message 代表了 一类结构化的数据,比如这里的用户信息。
message 里面定义了每一个属性的类型和名字。
* 布尔型、整数型 、 实数型、字符型、另外一个 message
Protocol Buffer 里属性的类型可以是像布尔型、整数型 、 实数型、字符型这样的基本类型, 也可以是另外一个 message。这样大大增加了 Protocol Buffer 的灵活性。
* required、optional、repeated
在 message 中, ProtocolBuffer也定义了一个属性是必需的(required)还是可选的 ~optional),或者是可重复的( repeated)。
如果一个属性是必需的(required)
,那么这个 message 的所有实例都需要 有这个属性
如果一个属性是可选的(optional)
,那么这个属性的取值可以为空
如果一 个属性是可重复的(repeated)
,那么这个属性的取值可以是一个列表。
还是以用户信息为例,所有用户都需要有 D,所以 D 这个属性是必需的:不是所有用户都填写了姓名,所 以姓名这个属性是可选的: 一个用户可能有多个 E-mail 地址,所以 E-mail 地址是可重复的。
Protocol Buffer 是 TensorFlow 系统中使用到的重要工具, TensorFlow 中的数据基本都 是通过 ProtocolBuffer来组织的。
在后面的章节中将看到 ProtocolBuffer是如何被使用的。
分布式 TensorFlow 的通信协议gRPC
也是以 Protocol Buffer作为基础的 。
-2.1.2- Bazel
* Bazel2是自动化构建工具
Bazel2是从谷歌开源的
自动化构建工具
,谷哥大内部绝大部分的应用都是通过它来编译的。
相比传统的 Makefile、 Ant 或者 Maven,Bazel
在速度
、可伸缩性
、灵活性
以及对不同程序语言和平台的支持
上都要更加出色。
* 项目空间(workspace)
项目空间(workspace)是Bazel的一个基本概念。
一个项目空间可以简单地理解为一个文件夹
,在这个文件夹中包含了:
*
编译一个软件所需要的源代码
*
以及输出编译结果的软连接(symbolic link)地址
一个项目空间内可以:
*
只包含一个应用(比如 TensorFlow),这种 、情况在 2.2.3 节中将会用于从源码安装 TensorFlow。
*
一个项目空间也可以包含多个应用。
* WORKSPACE文件
一 个项目空间所对应的文件夹是这个项目的根目录,
在这个根目录中需要有 一个 WORKSPACE 文件,此文件定义了对外部资源的依赖关系
。
空文件
同样也是 一个合法的WORKSPACE 文件 。
* BUILD文件
下面给出了 一个简单的样例来说明 Bazel 是如何工作的: 项目空间中有 4 个文件在一个项目空间内, Bazel通过BUILD文件来找到需要编译的目标。
BUILD文件采用一种类似于 Python 的语法来指定每一个编译目标的输入、输出以及编译方式。
与 Makefile 这种比较开放式的编译工具不同, Bazel 的编译 方式是事先定义好的。
因为 TensorFlow 主 要使用 Python 语 言 ,所以这里都以编译 Python 程序为例 。
Bazel 对 Python 支持的编译方式 只有三种:
*
py_binary,将Python程序编译为可执行文件
*
py_library,将 Python程序编译成库函数
供其他 py_binary 或 py_test调用
*
py_test,编译 Python测试程序
如图所示,在样例项目空间中有 4 个文件:
*
WORKSPACE
*
BUILD
*
hello_main.py
*
hello_lib.py
* WORKSPACE 文件
WORKSPACE 给出此项目的外部依赖关系。
为了简单起见 ,这里使用一个空文件,表明这个项目没有
对外部的依赖
。
* hello_lib.pyv
hello_lib.py 完成打印“ Hello World,,的简单功能,它的代 码如下 :
def print_hello_world():
print("Hello World !")
* hello_main.py文件
hello_main.py通过调用hello_lib.py 中定义的函数来完成输出 ,它的代码如下:
import hello_lib
hello_lib.print_hello_world()
* BUILD 文件
在 BUILD 文件中 定义了两个编译目标 :
py_library(
name = "hello_lib",
srcs = [
"hello_lib.py",
]
)
py_binary(
name = "hello_main",
srcs = [
"hello_main.py"
],
deps = [
":hello_lib",
],
)
从这个样例中可以 看 出, BUILD文件是由 一 系列
编译目标
组成的 。
定义编译目标的先后顺序不会影响编译的结果 。
*
在每一个编译目标的第一行要指定编译方式,在这个样例中 就是 py_library 或者 py_binary。
*
在每一个编译目标中的主体需要给出编译的具体信息 。
编译的具体信息是通过定义 name、 srcs、 deps等属性完成的。
name
是编译目标的名字
, 这个名字将被用来指代这一条编译目标。
srcs
是编译所需要的源代码
,这一项可以是 一个列表。
deps
是编译所需要的依赖关系
,比如样例中 hello_main.py 需要调用 hello_lib.py 中的函数,所以 hello_main 的编译目标中将 hello_lib 作为依赖关系 。
* 编译操作 bazel build :hello_main
在这个项目空间中运行编译操作 bazel build :hello_main 将得到类似以下的结果:
从以上结果可以看到,在原来 4个文件的基础上,
Bazel
生成
了其他一些文件夹。
这些新生成的文件夹就是编译的结果
,它们都是以软连接
的形式放在当前的项目空间里 。
实际的编译结果文件都会保存到~/.cache/bazel
目录下,这是可以通过 output_user_root 或者 output_base参数来改变的 。
在这些编译出来的结果当中:
*
bazel-bin目录
下存放了编译产生 的二进制文件以及运行该 二进制文件所需要的所有依赖关系 。 在当前目录下运行 bazel-bin/hello_main 就会在屏幕输出“ Hello World”。
*
其他编译结果
在本书中使用较少,这 里不再赘述 。
-2.2- TensorFlow安装
-2.2.1- 使用Docker安装
-2.2.2- 使用pip安装
-2.2.3- 从源代码编译安装
-2.3- TensorFlow测试样例
通过2.2节的安装方法安装完TensorFlow之后,本节将给出一个简单的样例:
* 用TensorFlow实现两个向量的求和
TensorFlow本身支持C、C++、Python三种语言,但其对Python的支持是最全面的,本节使用Python来展示这个简单样例:
import tensorflow as tf
a = tf.constant([1.0, 2.0], name="a")
b = tf.constant([2.0, 3.0], name="b")
result = a + b
sess = tf.Session()
sess.run(result)
# 得到输出:
# array([3., 5.], dtype=float32)
在这里将、定义为了两个常量:tf.constant,其中:
*
是shape为的向量:
*
是shape为的向量:
在两个加数定义好之后,将这两个向量加起来,读者会发现,在TensorFlow中,向量的加法也是可以直接通过加号+
来完成的,最后输出相加得到的结果。
要输出相加得到的结果,不能简单地直接输出 result,
而需要先生成一个会话(session)
, 并通过这个会话( session)来计算结果。
到此,就实现了 一个非常简单的 TensorFlow 模型 。
第 3 章将更加深入地介绍 TensorFlow 的基本概念,并将 TensorFlow 的计算模型和神经网络 模型结合起来。
网友评论