跳过了深度学习和TensorFlow安装的两章
TensorFlow入门
3.1 TensorFlow计算模型计算图
3.1.1计算图的概念
TensorFlow这个名字中Tensor意思是张量,表面TensorFlow的数据结构。Flow是流,表示张量之间通过计算相互转换。TensorFlow是一个通过计算图来表述计算的编程系统。其中每一个计算都是图上的一个节点,节点之间的边描述了的依赖关系
途中a,b,add三个圈代表三个节点,三个计算,其中a和b不依赖与其他的ji节点(计算),而add依赖于a和b的计算
3.1.1 计算图的使用
TensorFlow程序分为两个阶段:
(1)定义计算图中的所有计算
(2)执行阶段
定义计算阶段样例如下:
import tensorflow as tf
a = tf.constant([1.0, 2.0], name="a1") # 常量的创建方法
b = tf.constant([2.0, 3.0], name="b1")
result = a + b
print(a.graph is tf.get_default_graph())
# 通过变量名.graph可以获取变量所在的计算图,get_default_graph()可以获取more你的计算图
True
通过constant()方法可以定义张量,并给张量起名字
其次,通过变量名.graph属性可以看到节点所属的计算图,不给计算图起名字的情况下就是tf的默认计算图
通过tf.Graph()方法可以创建一个新的计算图,不同计算图上的张量和运算不会共享,以下代码说明在不同计算图上定义和使用张量
g1 = tf.Graph() # 计算图的创建
with g1.as_default(): # 打开这张图
# 从图中创建变量,维度为1,命名为v,初始化方法为zeros_initializer,即所有值为0
v = tf.get_variable("v", [0], initializer=tf.zeros_initializer())
g2 = tf.Graph()
with g2.as_default():
# 从图中创建变量,维度为1,命名为v,初始化方法使用ones_initializer,即所有值为1
v = tf.get_variable("v", [1], initializer=tf.ones_initializer())
# 打开tf的会话,然后才可以读取变量
with tf.Session(graph=g1) as sess:
# 初始化该图所有蓝图变量,每次运行必须有
# 新版本不再使用initializer_all_variables(), 而是使用global_variables_initializer()
tf.global_variables_initializer().run()
# 使用get_variable()创建的变量必须搭配variable_scope()使用,且reuse=True时,之前必须定义V
with tf.variable_scope("", reuse=True):
# get_variables()通过所给的名字创建或是返回一个变量,必须使用会话运行说明是在哪个会话内
print(sess.run(tf.get_variable("v")))
with tf.Session(graph=g2) as sess:
tf.global_variables_initializer().run()
with tf.variable_scope("", reuse=True):
print(sess.run(tf.get_variable("v")))
[]
[ 1.]
g = tf.Graph()
# 使用device可以指定使用哪个设备运行这张图
with g.device('/gpu:0'):
result = a + b
在一个计算图中,还可以使用集和来管理不同类别的资源,资源包括张量、变量或者运行TensorFlow所需要的队列资源
加入集和的方法是tf.add_to_collection(),获取集和的方法是tf.get_collection()
以下是几种常用的集和
3.2数据模型——张量
3.2.1 张量的概念
张量可以简单理解为多维数组,零阶张量表示张量,也就是一个数字,一阶张量表示一个一维向量(数组),n阶向量就表示n维数组。但是张量在TensorFlow中的实现不是采用数组的形式,它只是对TensorFlow中运算结果的引用。张量中不保存数字,值保存如何计算得到这些数字的计算过程,如下列运算:
import tensorflow as tf
a = tf.constant([1.0, 2.0], name='a')
b = tf.constant([2.0, 3.0], name='b')
result = tf.add(a, b, name='add')
print(result)
Tensor("add_3:0", shape=(2,), dtype=float32)
由上可见TensorFlow计算获取的张量只显示名字,维度和类型,不显示数组,只显示结构
同时,shape=(2,)的意思是:result是一个一维数组,数组长度为2,dtype是类型,当TensorFlow中发现计算类型不匹配的时候会报错
创建变量或者常量的时候不指定类型就会默认使用float32,指定方法是dtype=”float32”
3.2.2 张量的使用
张量的使用可以分为两大类:
第一类用途是对中间计算结果的引用(记录),方便重复使用。下面为使用张量和不使用张量记录中间结果的计算
# 使用张量记录中间结果
a = tf.constant([1.0, 2.0], name="a")
b = tf.constant([2.0, 3.0], name="b")
result = a + b
print(result)
# 直接计算,不使用张量
result = tf.constant([1.0, 2.0], name="a") + tf.constant([2.0, 3.0], name="b")
print(result)
Tensor("add_4:0", shape=(2,), dtype=float32)
Tensor("add_5:0", shape=(2,), dtype=float32)
其中a和b就是对常量生成这个运算结果的引用。当计算的复杂度增加的时候通过张量来引用计算的中间结果可以提高代码的可阅读性。同时方便获取中间结果。在网络中,可以yogaresult.get_shape()来获取某一层的维度信息而不用人工计算
第二类用途是,当计算图构造完成之后,张量可以用来获取计算结果(得到数字但是本书不存储数字),使用tf.Session.run(result)来获取结果
3.3 TensorFlow运行模型——会话
使用会话可以执行定义好的运算,会话拥有并管理TensorFlow运行的时候的所有资源,当所有计算结束之后需要关闭会话来回收资源,否则会有资源泄漏的问题
使用会话模式有两种,下面是第一种
sess = tf.Session() # 创建一个会话
sess.run(result) # 通过会话使用张量,张量是计算过程,等于再次计算
sess.close() # 关闭会话,释放资源
使用这种模式需要明确使用close()来关闭会话,但是程序出现异常的时候不会自动关闭导致资源泄漏,所以一般采用第二种方法。这种方式即使报错也会自动关闭会话
with tf.Session() as sess:
sess.run(result)
TensorFlow有默认的计算图和默认的会话,在没有指定计算图的情况下,计算会被加入到默认计算图中,且默认计算图自动生成。但是会话不会自动生成,需要手动指定sess.as_deafult(),同时可以使用张量.eval()函数来计算一个张量的取值。
sess = tf.Session()
with sess.as_default():
print(result.eval())
# 这两个方法也有同样的效果
sess = tf.Session()
print(sess.run(result))
print(result.eval(session=sess))
[ 3. 5.]
[ 3. 5.]
[ 3. 5.]
总而言之,要获取张量的计算结果就要使用会话
无论使用哪张方法生成的会话都可以通过ConfigConfigProto()来指定配置,配置包括:
allow_soft_placement,当他为True的时候只要满足下面任意一个条件就可以自动把GPU上的运算放到CPU上面,默认为False
(1)运算无法再GPU上运行
(2)没有GPU资源
(3)运算输入包括对CPU计算结果的引用
第二个参数是log_device_placement()。为True的时候将会记录每个节点被安排在哪个设备上方便调试,在生产环境中通常设置为False减少日志量
ConfigProto()的使用如下:
config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)
sess1 = tf.Session(config=config)