TensorFlow快速上手及TensorBoard使用
4.1 编程模型
TensorFlow的命名来源于本身的运行原理。Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算。TensorFlow是张量从图像的一端流动到另一端的计算过程,这也是TensorFlow的编程模型。
4.1.1 了解模型的运行机制
TensorFlow的运行机制属于“定义”与“运行”相分离。从操作层面可以抽象成两种:模型构建和模型运行。
在模型构建过程中,需要先了解几个概念,见表4-1。
● 在模型运行的环节中,“图”会在绘话(session)里被启动。
● session将图的 OP 分发到诸如CPU或GPU之类的设备上, 同时提供执行OP的方法。这些方法执行后,将产生的tensor返回。在Python语言中,返回的tensor是numpy ndarray对象;在C和C++语言中,返回的tensor是TensorFlow::Tensor实例。
如图4-1表示了session与图的工作关系。
图4-1 session与图
在实际环境中,这种运行情况会有三种应用场景,训练场景、测试场景与使用场景。在训练场景下图的运行方式与其他两种不同,具体介绍如下:
(1)训练场景:主要是实现模型从无到有的过程,通过对样本的学习训练,调整学习参数,形成最终的模型。其过程是将给定的样本和标签作为输入节点,通过大量的循环迭代,将图中的正向运算得到输出值,再进行反向运算更新模型中的学习参数。最终使模型产生的正向结果最大化的接近样本标签。这样就得到了一个可以拟合样本规律的模型。
(2)测试场景和使用场景:测试场景是利用图的正向运算得到结果比较与真实值的产别;使用场景也是利用图的正向运算得到结果,并直接使用。所以二者的运算过程是一样的。对于该场景下的模型与正常编程用到的函数特别相似。大家知道,在函数中,可以分为:实参、形参、函数体与返回值。同样在模型中,实参就是输入的样本,形参就是占位符,运算过程就相当于函数体,得到的结果相当于返回值。
另外session与图的交互过程中,还定义了两种数据的流向机制:
● 注入机制(feed):通过占位符向模式中传入数据;
● 取回机制(fetch):从模式中得到结果。
下面通过实例逐个演示session在各种情况下的用法。先从session的建立开始,接着演示session与图的交互机制,最后演示如何在session中指定GPU运算资源。
4.1.2 实例5:编写hello world演示session的使用
先从一个hello world开始来理解Session的作用。
案例描述
建立一个session,在session中输出helloworld。
可以试着在2和3行之间加入print(hello)看一下效果,这时并不能输出hello的内容。
接下来换种写法,使用with语法来开启session。
4.1.3 实例6:演示with session的使用
With session的用法是最常见的了,它沿用了python中with的语法,即当程序介绍后会自动关闭session,而不需要在去写close。代码如下。
案例描述
使用with session方法建立session,并在session中计算两个变量(3和4)的相加与相乘。
扩展上面代码:使用注入机制,将具体的实参注入到相应的placeholder中去。feed只在调用它的方法内有效,方法结束后feed就会消失。
案例描述
定义占位符,使用feed机制将具体数值(3和4)通过占位符传入,并进行运算它们相加和相乘。
建立session还有两种方式:
● 交互式session方式:一般在Jupiter环境下使用较多,具体用法与前面的with session类似。代码如下:
sess = tf.InteractiveSession()
● 使用Supervisor方式:该方式会更为高级一些,使用起来也更加复杂,可以自动来管理session中的具体任务,比如,载入/载出检查点文件、写入TensorBoard等,另外还支持分布式训练的部署(在本书的后文会有介绍)。
4.1.6 实例8:使用注入机制获取节点
在上例中,其实还可以一次将多个节点取出来。例如在最后一句加上如下代码:
案例描述
使用fetch机制将定义在图中的节点数值算出来。
如果下载的是GPU版本,在运行过程中TensorFlow能自动检测。如果检测到GPU,TensorFlow会尽可能地利用找到的第一个GPU来执行操作。
● cpu:0:机器的CPU。
● gpu:0:机器的第一个GPU,如果有的话。
● gpu:1:机器的第二个GPU,以此类推。
类似的还有通过tf.ConfigProto来构建一个config,在config中指定相关的gpu,并且在session中传入参数config=“自己创建的config”来指定gpu操作。
#tf.ConfigProto()的参数如下:
● log_device_placement=True:是否打印设备分配日志;
● allow_soft_placement=True:如果指定的设备不存在,允许TF自动分配设备。
使用举例:
config = tf.ConfigProto(log_device_placement=True,allow_soft_placement=True)
session = tf.Session(config=config, ...)
4.1.8 设置GPU使用资源
上文的tf.ConfigProto()生成config之后,还可以设置其属性来分配GPU的运算资源。如下代码就是按需分配的意思:
config.gpu_options.allow_growth = True
使用allow_growth option,刚一开始分配少量的GPU容量,然后按需慢慢的增加,由于不会释放内存,所以会导致碎片。
同样上述代码也可以放在config创建的时指定,举例:
gpu_options = tf.GPUOptions(allow_growth=True)
config=tf.ConfigProto(gpu_options=gpu_options)
如下代码还可以给GPU分配固定大小的计算资源。
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.7)
代表分配给tensorflow的GPU显存大小为:GPU实际显存*0.7。
(该方法暂时用不到,读者在以后遇到这样的代码明白是什么意思就可以。)
4.1.9 保存和载入模型的方法介绍
一般而言,训练好的模型都是需要保存。这里将举例演示如何保存和载入模型。
1.保存模型
案例描述
在代码“3-1线性回归.py”的基础上,添加模型的保存及载入功能。
通过扩展上一章的例子,来演示一下模型的保存及载入。在“代码3-1线性回归.py”中生成模拟数据之后,加入对图变量的重置,在session创建之前定义saver及保存路径,在session中训练结束后,保存模型。

再重启一个session,并命名为sess2,在代码里通过使用saver的restore函数,将模型载入。
4.1.11 实例10:分析模型内容,演示模型的其他保存方法
下面再来详细介绍下关于模型保存的其他细节。
案例描述
将上一节生成的模型里面的内容打印出来,观察其存放的具体数据方式。同时演示将指定内容保存到模型文件中去。
1.模型内容
虽然模型已经保存了。但是仍然对我们不透明。现在通过编写代码来将模型里面的内容打印出来,看看到底保存了哪些东西,都是什么样子。
2.保存模型的其他方法
前面的例子中saver的创建比较简单,其实tf.train.Saver()里面开可以放参数来实现更高级的功能,可以指定存储变量名字与变量的对应关系。可以写成这样:
saver = tf.train.Saver({'weight': W, 'bias': b})
代表将w变量的值放到weight名字中去。类似的写法还有两种:
saver = tf.train.Saver([W, b]) # 放到一个list里.
saver = tf.train.Saver({v.op.name: v for v in [W, b]}) # 将op的名字当作key:
下面扩展一下上述的例子,给b和w指定个固定值,并将他们颠倒放置。
4.1.12 检查点(Checkpoint)
模型的保存场景并不限于在训练之后,在训练之中更需要保存,因为TensorFlow训练模型时难免会出现中断的情况。我们自然就希望能够将辛辛苦苦得到的中间参数保留下来,不然下次又要重新开始。
TensorFlow的命名来源于本身的运行原理。Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算。TensorFlow是张量从图像的一端流动到另一端的计算过程,这也是TensorFlow的编程模型。
4.1.1 了解模型的运行机制
TensorFlow的运行机制属于“定义”与“运行”相分离。从操作层面可以抽象成两种:模型构建和模型运行。
在模型构建过程中,需要先了解几个概念,见表4-1。
表4-1 模型构建中的概念
● 在模型运行的环节中,“图”会在绘话(session)里被启动。
● session将图的 OP 分发到诸如CPU或GPU之类的设备上, 同时提供执行OP的方法。这些方法执行后,将产生的tensor返回。在Python语言中,返回的tensor是numpy ndarray对象;在C和C++语言中,返回的tensor是TensorFlow::Tensor实例。
如图4-1表示了session与图的工作关系。
在实际环境中,这种运行情况会有三种应用场景,训练场景、测试场景与使用场景。在训练场景下图的运行方式与其他两种不同,具体介绍如下:
(1)训练场景:主要是实现模型从无到有的过程,通过对样本的学习训练,调整学习参数,形成最终的模型。其过程是将给定的样本和标签作为输入节点,通过大量的循环迭代,将图中的正向运算得到输出值,再进行反向运算更新模型中的学习参数。最终使模型产生的正向结果最大化的接近样本标签。这样就得到了一个可以拟合样本规律的模型。
(2)测试场景和使用场景:测试场景是利用图的正向运算得到结果比较与真实值的产别;使用场景也是利用图的正向运算得到结果,并直接使用。所以二者的运算过程是一样的。对于该场景下的模型与正常编程用到的函数特别相似。大家知道,在函数中,可以分为:实参、形参、函数体与返回值。同样在模型中,实参就是输入的样本,形参就是占位符,运算过程就相当于函数体,得到的结果相当于返回值。
另外session与图的交互过程中,还定义了两种数据的流向机制:
● 注入机制(feed):通过占位符向模式中传入数据;
● 取回机制(fetch):从模式中得到结果。
下面通过实例逐个演示session在各种情况下的用法。先从session的建立开始,接着演示session与图的交互机制,最后演示如何在session中指定GPU运算资源。
4.1.2 实例5:编写hello world演示session的使用
先从一个hello world开始来理解Session的作用。
案例描述
建立一个session,在session中输出helloworld。
代码4-1 sessionhello
运行代码4-1会得到如下输出:
可以试着在2和3行之间加入print(hello)看一下效果,这时并不能输出hello的内容。
接下来换种写法,使用with语法来开启session。
4.1.3 实例6:演示with session的使用
With session的用法是最常见的了,它沿用了python中with的语法,即当程序介绍后会自动关闭session,而不需要在去写close。代码如下。
案例描述
使用with session方法建立session,并在session中计算两个变量(3和4)的相加与相乘。
代码4-2 with session
运行后得到如下输出:
扩展上面代码:使用注入机制,将具体的实参注入到相应的placeholder中去。feed只在调用它的方法内有效,方法结束后feed就会消失。
案例描述
定义占位符,使用feed机制将具体数值(3和4)通过占位符传入,并进行运算它们相加和相乘。
代码4-3 withsessionfeed
运行代码,输出:
注意:
关于feed中的feed_dict还有其他的方法,例如update等,在后文例子中用到时还会介绍。这里只是介绍最常用的方法。
4.1.5 建立session 的其他方法建立session还有两种方式:
● 交互式session方式:一般在Jupiter环境下使用较多,具体用法与前面的with session类似。代码如下:
sess = tf.InteractiveSession()
● 使用Supervisor方式:该方式会更为高级一些,使用起来也更加复杂,可以自动来管理session中的具体任务,比如,载入/载出检查点文件、写入TensorBoard等,另外还支持分布式训练的部署(在本书的后文会有介绍)。
4.1.6 实例8:使用注入机制获取节点
在上例中,其实还可以一次将多个节点取出来。例如在最后一句加上如下代码:
案例描述
使用fetch机制将定义在图中的节点数值算出来。
代码4-3 withsessionfeed(续)
如果下载的是GPU版本,在运行过程中TensorFlow能自动检测。如果检测到GPU,TensorFlow会尽可能地利用找到的第一个GPU来执行操作。
如果机器上有超过一个可用的GPU,除第一个外的其他GPU默认是不参与计算的。为了让TensorFlow使用这些GPU,必须将OP明确指派给它们执行。with……Device语句用来指派特定的CPU或GPU执行操作:
● cpu:0:机器的CPU。
● gpu:0:机器的第一个GPU,如果有的话。
● gpu:1:机器的第二个GPU,以此类推。
类似的还有通过tf.ConfigProto来构建一个config,在config中指定相关的gpu,并且在session中传入参数config=“自己创建的config”来指定gpu操作。
#tf.ConfigProto()的参数如下:
● log_device_placement=True:是否打印设备分配日志;
● allow_soft_placement=True:如果指定的设备不存在,允许TF自动分配设备。
使用举例:
config = tf.ConfigProto(log_device_placement=True,allow_soft_placement=True)
session = tf.Session(config=config, ...)
4.1.8 设置GPU使用资源
上文的tf.ConfigProto()生成config之后,还可以设置其属性来分配GPU的运算资源。如下代码就是按需分配的意思:
config.gpu_options.allow_growth = True
使用allow_growth option,刚一开始分配少量的GPU容量,然后按需慢慢的增加,由于不会释放内存,所以会导致碎片。
同样上述代码也可以放在config创建的时指定,举例:
gpu_options = tf.GPUOptions(allow_growth=True)
config=tf.ConfigProto(gpu_options=gpu_options)
如下代码还可以给GPU分配固定大小的计算资源。
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.7)
代表分配给tensorflow的GPU显存大小为:GPU实际显存*0.7。
(该方法暂时用不到,读者在以后遇到这样的代码明白是什么意思就可以。)
4.1.9 保存和载入模型的方法介绍
一般而言,训练好的模型都是需要保存。这里将举例演示如何保存和载入模型。
1.保存模型
首先需要建立一个saver,然后在session中通过saver的save即可将模型保存起来。代码如下:
将模型保存好以后,载入也比较方便。在session中通过调用saver的restore函数,会从指定的路径找到模型文件,并覆盖到相关参数中。如下所示:
案例描述
在代码“3-1线性回归.py”的基础上,添加模型的保存及载入功能。
通过扩展上一章的例子,来演示一下模型的保存及载入。在“代码3-1线性回归.py”中生成模拟数据之后,加入对图变量的重置,在session创建之前定义saver及保存路径,在session中训练结束后,保存模型。
代码4-4 线性回归模型保存及载入
再重启一个session,并命名为sess2,在代码里通过使用saver的restore函数,将模型载入。
代码4-4 线性回归模型保存及载入(续)
为了测试效果,可以将前面一个session注释掉,运行之后可以看到如下输出:
4.1.11 实例10:分析模型内容,演示模型的其他保存方法
下面再来详细介绍下关于模型保存的其他细节。
案例描述
将上一节生成的模型里面的内容打印出来,观察其存放的具体数据方式。同时演示将指定内容保存到模型文件中去。
1.模型内容
虽然模型已经保存了。但是仍然对我们不透明。现在通过编写代码来将模型里面的内容打印出来,看看到底保存了哪些东西,都是什么样子。
代码4-5 模型内容
运行上面代码,打印如下信息:
2.保存模型的其他方法
前面的例子中saver的创建比较简单,其实tf.train.Saver()里面开可以放参数来实现更高级的功能,可以指定存储变量名字与变量的对应关系。可以写成这样:
saver = tf.train.Saver({'weight': W, 'bias': b})
代表将w变量的值放到weight名字中去。类似的写法还有两种:
saver = tf.train.Saver([W, b]) # 放到一个list里.
saver = tf.train.Saver({v.op.name: v for v in [W, b]}) # 将op的名字当作key:
下面扩展一下上述的例子,给b和w指定个固定值,并将他们颠倒放置。
代码4-5 模型内容(续)
运行上面代码,输出如下信息:
4.1.12 检查点(Checkpoint)
模型的保存场景并不限于在训练之后,在训练之中更需要保存,因为TensorFlow训练模型时难免会出现中断的情况。我们自然就希望能够将辛辛苦苦得到的中间参数保留下来,不然下次又要重新开始。
这种在训练中保存模型,习惯上称之为保存检查点。
全部内容来源于《深入学习之TensorFlow:入门、原理与进阶实战》一书,欢迎支持