【CS20-TF4DL】01 Tensorflow 快速入门

第一讲主要是介绍 Tensorflow 的基本概念,介绍为何选择 TF 以及 Graph 和 Session 这两个重要概念。


更新历史

  • 2019.08.03: 完成初稿

快速问答

啥是 TensorFlow?

官方定义为:Open source software library for numerical computation using data flow graphs,翻译过来就是使用数据流图来进行数值计算的开源软件包。用人话讲就是:一个用来算数的计算框架,通常用来做深度学习。

注:google 内部使用的会与开源版本不同,因为要与内部的其他工具对接。

为啥要用 Tensorflow?

各种机器学习的软件包层出不穷,基本上每周就会有某个公司发布一个,之所以选 Tensorflow 主要是看上它(虽然现在 PyTorch 正在快速追赶):

  • 灵活可扩展:由 google 开发
  • 最热门:大部分深度学习项目用 TF 开发,大公司们都在用(Google/Uber/OpenAI/Airbnb/Snapchat/NVIDIA/INTEL/DeepMind/AIRBUS …)
  • Python API
  • 支持可视化 Tensorboard
  • 可以保存模型与 Graph
  • 社区活跃

这门课学啥?

  • 理解 Tensorflow 的计算图
  • 探索 TF 内置的函数与类
  • 学习如何去构建一个深度学习模型

遇到不会的问题怎么办?

左转 StackOverflow

推荐书籍都有哪些?

这门课程没有课本,因为现在 TF 变化太快。官方推荐如下,如果要问我最推荐哪一本,我推荐 《Deep Learning with Python》

  • Aurélien Géron’s Hands-On Machine Learning with Scikit-Learn and TensorFlow (O’Reilly,March 2017)
  • François Chollet’s Deep Learning with Python (Manning Publications, November 2017)
  • Nishant Shukla’s Machine Learning with TensorFlow (Manning Publications, January 2018)
  • Lieder et al.’s Learning TensorFlow A Guide to Building Deep Learning Systems (O’Reilly, August 2017)

都说 Tensorflow,啥是 Tensor?

Tensor 中文是张量(不好意思不是麻辣烫),可以理解为一个 n 维的数组,其中低维的张量有另外的名字:

  • 0 维张量称为标量 Scalar,也就是数字
  • 1 维张量称为向量 Vector
  • 2 维张量称为矩阵 Matrix
  • 再高维的就叫张量

Graph 与 Sessions

一切的一切开始之前,请 import tensorflow as tf。别问,问就是先 import。

然后我们来说一下 TF 中最重要的一个概念,就是 Data Flow Graph(数据流图)。通过数据流图,我们可以把计算的描述和实际的执行分离,图本身的结构描述了要做什么计算,真正的计算可以在数据到来之后再执行。

比如,我们要计算的公式为 $(a\times b) +(a+b)$,转化成数据流图就如下所示

然后当我们真的有了 a 和 b 的值,需要计算的时候,我们就通过 Session 来完成这个操作,5 和 3 就被输送到 input 节点,经过一系列计算,得到最终答案 23。于是我们可以总结出,在 TF 中做计算需要 2 步:

  1. 组装一个数据流图
  2. 通过 Session 来执行图中的各种操作

当然,凡事都有例外,在 eager mode 中,计算会在定义图之后就进行,就不需要两步。这个模式主要用于调试算法,后续会介绍,这里只要记得分两步就好。

理论讲完,可以上手了,进入我们之前配置好的虚拟环境,然后进入 python 命令行,输入如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import tensorflow as tf
a = tf.add(3, 5)
# 在 Tensorboard 的显示里,节点表示操作、变量和常量,边表示张量
print(a)
# 显示 Tensor("Add:0", shape=(), dtype=int32)
# 那么我们如何得到 a 的值呢,需要创建一个 session,然后对图进行计算,像这样
sess = tf.Session()
print(sess.run(a)) # run 之后就得到 a 实际的值
sess.close() # 注意要关闭

# 每次都关闭太麻烦,建议用 with 来进行
with tf.Session() as sess:
print(sess.run(a))
# session 对象封装了用于处理 Operation 和 Tensor 的环境(分配内存、处理计算等)

# 一个更复杂的图,结构如下图所示
x = 2
y = 3
add_op = tf.add(x, y)
mul_op = tf.multiply(x, y)
useless = tf.multiply(x, add_op)
pow_op = tf.pow(add_op, mul_op)
with tf.Session() as sess:
z = sess.run(pow_op) # 只计算 pow_op,useless 节点不会进行计算
# 我们也可以同时计算多个,因为本质上我们传入的是需要获取的操作列表,也就是 fetches,是一个 List
# tf.Session.run(fetches, feed_dict=None, options=None, run_metadata=None)
z, not_useless = sess.run([pow_op, useless])

因为是计算图,我们可以知道不同计算的依赖关系,TF 就可以充分利用计算资源,在多个计算设备上分配计算任务,最后组装得到结果(当然,这里会有数据交换的开销)。

如果我们想要指定某些计算在特定的设备上执行,可以像这样:

1
2
3
4
5
6
7
8
9
# 指定计算设备
with tf.device('/gpu:2'):
a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], name='a')
b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], name='b')
c = tf.multiply(a, b)

# 创建 session,并设置记录设备信息
with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
print(sess.run(c))

以上的计算都是在同一个 Graph 进行的,那么如果想要创建多个 Graph 可以吗?可以,但没必要,也不推荐,原因如下:

  • 多个 Graph 就需要多个 session,每个 session 默认是会占用所有可用资源,没必要
  • 多个 Graph 之前只能通过 python/numpy 传输数据,这是无法进行分布式计算的
  • 如果需要多个 subgraph,放到一个 graph 中,然后不要相连就好

最后总结一下为什么要用 Graph 机制来处理计算,因为:

  1. 节省计算资源。通过图结构的最短路径来执行计算,获取所需的值
  2. 能够把计算分成小块且可微的任务,更好的利用自动微分
  3. 可以利用分布式计算,把计算任务放到多个 CPU/GPU/TPU 上
  4. 很多机器学习模型是通过有向图来进行训练和可视化的,非常契合

下期预告

  1. 基础 Operation
  2. 常量与变量
  3. Data Pipeline
  4. Tensorboard 的使用

学习资源

一点打赏,十分感谢,百分动力