Head First TensorFlow


In [ ]:

Author: Yue-Wen FANG,

Contact: fyuewen@gmail.com

Revision history: created in late August 2017, at New York Uniersity, Shanghai

New York University, Shanghai

Kyto University

In the begining, I read the book by Jiaxuan Li, but soon I realized it is not good for beginers, and hence I switch to read this book by Caicloud.

1. 深度学习简介


In [ ]:

2. TensorFlow 环境搭建

Please refere to my notes in the directory of JiaxuanLi-book2017

A test code for your environment:


In [1]:
import tensorflow as tf
a = tf.constant([1.0,2.0], name = "a")
b = tf.constant([1.0,2.0], name = "b")
c = a + b
with tf.Session() as sess:
    sess.run(c)
print(c)#


Tensor("add:0", shape=(2,), dtype=float32)

3. TensorFlow 入门

3.1 TensorFlow 计算模型——计算图

计算图是TensorFlow 中最基本的一个概念。TensorFlow 中所有的计算都会被转化成计算图中的节点。(在之后的段落中,我为了省略时常将 TensorFlow 简化为 TF)

3.1.1 计算图的概念

TensorFlow~中,张量可以简单地理解为多维数组,在 3.2 节中将对张量做更加详细的介绍。作者认为,如果 TensorFlow 中的 Tensor 表明了它的数据结构,那么 Flow 则体现了它的计算模型。 Flow 直观地体现了张量之间是通过计算实现相互转化的。TensorFlow 是一个通过计算图的形式来表述计算的编程系统。TensorFlow 中每个计算都是计算图上的一个节点,而节点之间的“边”则描述了计算之间的依赖关系。

3.1.2 计算图的使用

TensorFlow~程序一般可分2阶段:

  1. 定义计算图中的所有计算; 例

In [ ]:
import tensorflow as tf
a = tf.constant([1.0,2.0], name = "a")
b = tf.constant([1.0,2.0], name = "b")
c = a + b

上述这个案例,定义了两个输入 a 和 b, 以及定义了一个“和”计算。


In [ ]:
2. 执行计算这个部分将在 3.3 节中介绍

在 TensorFlow 中,系统会自动维护一个默认的计算图,通过 tf.get_default_graph 函数可以获取默认计算图。


In [4]:
import tensorflow as tf
a = tf.constant([1.0,2.0], name = "a")
b = tf.constant([1.0,2.0], name = "b")
c = a + b
print(a.graph is tf.get_default_graph())


True

上述代码段最后一句,作者说它实现了如何获取默认计算图以及如何查看一个运算所属计算图。当然,这点我有点不明白??

除了使用默认的计算图,TF 支持通过 tf.Graph 函数来生成新的计算图。 不同计算图上的张量和运算都不会共享。以下代码示意了如何在不同计算图上定义和使用变量:


In [13]:
import tensorflow as tf

g1 = tf.Graph()
with g1.as_default():
    #在计算图g1中定义变量 "v", 并初始化为0
    v = tf.get_variable(
    "v", initializer=tf.zeros_initializer(shape=[1]))
    
g2 = tf.Graph()
with g2.as_default():
    #在计算图g1中定义变量 "v", 并初始化为1
    v = tf.get_variable(
    "v", initializer=tf.ones_initializer(shape=[1]))
    
# 在计算图 g1 中读取变量 v 的取值

with tf.Session(graph = g1) as sess:
    tf.initizlize_all_variables().run()
    with tf.variable_scope("", reuse=True):
        #在计算图 g1 中,变量 v 的取值应该为0, 所以下面这行会输出 [0.]
        print(sess.run(tf.get_variable("v")))
        

# 在计算图 g2 中读取变量 v 的取值
with tf.Session(graph = g1) as sess:
    tf.initialize_all_variables().run()
    with tf.variable_scope("", reuse=True):
        #在计算图 g2 中,变量“v"的值应该为1,所以下面会输出[1.]
        print(sess.run(tf.get_variable("v")))


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-13-69578e57c537> in <module>()
      5     #在计算图g1中定义变量 "v", 并初始化为0
      6     v = tf.get_variable(
----> 7     "v", initializer=tf.zeros_initializer(shape=[1]))
      8 
      9 g2 = tf.Graph()

TypeError: __init__() got an unexpected keyword argument 'shape'

可能因为我用的是TF 1.3,上述代码并不能运行通过??!

不过原书对上述代码有这样的讨论:TF的计算图不仅仅可以用来隔离张量和计算,还提供了管理张量和计算的控制。

3.2 TensofrFlow 数据模型——张量

3.2.1 张量的概念

虽然这个小节叫做“张量的概念”,但其实这本书并未介绍什么是张量。张量的概念是数学中的,请参考数学书籍。不过本书告诉了我们,TF中的的数据和张量的关系:所有的TF数据都是以张量的方式表示的。从功能上看,张量可以被简单地理解为多维数组。例如零阶张量表示scalar,也就是一个数;第一阶张量为vector,也就是一个一维数组;第 n 阶张量理解为一个 n 为数组。

然而在TF中,张量的实现并不是直接采用数组的形式,它只是对TF中运算结果的引用。在张量中并没有真正保存数组,它保存的是如何得到这些数字的计算过程。

例如下面这个例子进行加法运算,最后运行出来的结果并不是加法的结果,而是对结果的一个引用:


In [16]:
import tensorflow as tf
a = tf.constant([1.0, 2.0], name = 'a')
b = tf.constant([2.0, 3.0], name = 'b')
sum = tf.add(a, b, name='add')
print(sum)


Tensor("add_6:0", shape=(2,), dtype=float32)

从上可以看出 TF 中的张量和 Numpy 中的数组是不同的,TF中计算的结果,并非数字结果,而是一个张量的结构:即 name、shape、和 type

3.2.2 张量的使用

相对计算模型,数据模型相对简单。张量使用主要分两大类。

第一类用途是对中间计算结果的引用。当一个计算包含很多中间结果时,使用张量可以提高可读性。 例如


In [ ]:
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

# 直接用向量计算,可读性相对较差
result = tf.constant([1.0, 2.0], name = 'a') + tf.constant([2.0, 3.0], name = 'b')

用张量进行计算的好处在深度学习中会尤其体现出来,因为神经网络层次越多,所需要的计算就越复杂。直接的数组计算会使得代码可读性很差。

这样做的好处还体现在一些其他方面,例如在卷积神经网络中,卷阶层和池化层可能涉及张量变维,通过result.get_shape 函数来获取结果张量的维度信息可以免去人工计算的麻烦。

第二类用途是当计算图构造完成之后,张量可以用力获得计算结果,也就是得到真实的数字。虽然张量本身没有存储具体数字,不过通过session可以得到具体的数字。下面3.3节会进行具体介绍。

3.3 TensorFlow 运行模型——会话

本节主要介绍利用session 会话来执行定义好的运行。session拥有并管理TF程序运行时的所有资源。当素有计算完成之后需要关闭会话才能回收资源,否则可能会造成资源泄露问题。

TF 中使用会话的模式一般有两种,第一种模式需要明确调用会话生成函数和关闭会话函数,例如


In [22]:
import tensorflow as tf
a = tf.constant([1.0, 2.0], name = 'a')

sess = tf.Session()

sess.run(a)

sess.close()

使用上述模式时,计算完成后必须关闭session。为了使用方便,可以通过第二种模式,即可利用 Python 上下文管理器来使用session:


In [ ]:
import tensorflow as tf
a = tf.constant([1.0, 2.0], name = 'a')

with tf.Session() as sess:
    sess.run(a)

这样既解决了因为异常退出导致的资源释放问题,也解决了因为忘记调用 Session.close 函数所导致的资源泄漏。

这一节在P45,仍然需要复习一下增加些笔记。

3.4 TensorFlow 实现神经网络

上面 3 节从不同角度计算了 TF 的基本概念。在这一节中,将结合神经网络的功能进一步介绍如何通过 TF 实现神经网络。

3.4.1 小节将通过 TF上的playground来简单介绍神经网络的主要功能和计算流程; 3.4.2 小节将介绍神经网络的前向传播算法即forward-propagation,并给出使用 TF 的代码实现; 3.4.4 小姐中将介绍神经网络的反向传播即 back-propagation 算法的原理以及 TF 对反向传播算法的支持。最后 3.4.5 小杰将给出一个完整的 TF 程序在随机的数据上训练一个简单的神经网络。

3.4.1 TensorFlow 游乐场以及神经网络简介

Playground的网站是:http://playground.tensorflow.org/

一些名词:学习率 learnning reate; 激活函数 activation; 正则化 regularization

关于 TF 游乐场训练结果的解读: Page 49