在上一篇文章中我们学习了TensorFlow(TF)中的Tensor和Operation。今天继续学习TF中的其他几个重要的概念。
先看下面一段代码:
尽管我创建了一个input tensor( [5, 3] )以及一系列操作(
tf.reduce_prod
, tf.reduce_sum
, tf.add
),可是并不能马上看到结果,这是我第一次接触TF时最不习惯的地方。究竟怎样才能运行这个graph,让tensor真正流动起来呢?
Session
一个完整的TF代码主要可以分成2个部分:定义(definition)和运行(run)。而此时我们仅仅是完成了graph的定义,不会立刻执行。为了运行这个图,让tensor真正流动起来,我们需要创建一个Session对象,然后调用它的run
方法。当执行完毕后,最好调用close
方法将Session关闭:
当我们把图中的一个节点(node)传递给Session.run( )的时候,实际上就是在对TF说:“Hi,我想要这个node的输出,请帮我运行相应的操作来得到它,谢谢!” 这时,Session会找到这个node所依赖的所有操作,然后按照从前到后的顺序依次进行计算,直到得出你所需要的结果。
写到这里,我突然想到这和linux中的软件包管理器十分类似,当你install一个软件包的时候,它会自动帮你把所有依赖包都装好,而这背后的安装过程对用户来说都是透明的。虽然我不知道软件包管理器是怎么实现的,但我猜测其内部也有一个graph。
Session.run
方法有2个参数,分别是fetches
和feed_dict
。参数名有时候可以省略,比如sess.run(fetches=d)
和前面的sess.run(d)
是一样的。传递给fetches
参数的既可以是Tensor也可以是Operation。如果传给fetches
的是一个list,run
返回的结果也是一个与之对应的list:
feed_dict
参数的作用是替换图中的某个tensor的值。例如:
当我们利用
feed_dict
直接提供某个tensor值(a=15)的时候,就不需要再去执行为计算这个tensor所需的所有操作(2+5=7)。这样做的好处是在某些情况下可以避免一些不必要的计算。除此之外,feed_dict
还可以用来设置graph的输入值,这就引入了placeholder的概念。
placeholder
我们将文章开头部分的代码做了一点修改:
此时的
a
不是一个tensor,而是一个placeholder。我们定义了它的type和shape,但是并没有具体的值。在后面定义graph的代码中,placeholder看上去和普通的tensor对象一样。在运行程序的时候我们用feed_dict
的方式把具体的值提供给placeholder,达到了给graph提供input的目的。
placeholder有点像在定义函数的时候用到的参数。我们在写函数内部代码的时候,虽然用到了参数,但并不知道参数所代表的值。只有在调用函数的时候,我们才把具体的值传递给参数。
Variable
前面介绍的Tensor对象是不可改变的(immutable),可以认为它们是常量(constant)。程序中还需要一类可以改变自身值的变量(variables),下面我们就来创建Variable对象:
code6.png
Oops!报错了?为什么看不到变量的值呢?
Variable对象的状态是由Session来管理的,所以我们必须在Session中对Variable对象进行初始化操作:
code7.png
也可以对部分Variable对象进行初始化操作:
code8.png
既然变量的值是可以改变的,那么我们该如何操作呢?我们可以用Variable对象的assign方法Variable.assign()
来给Variable一个新的值。Variable.assign()
返回的是一个操作(Op), 必须在Session中运行才会起作用:
每个Session对Variable的管理是独立的,所以同一个Variable在不同的Session中可以有不同的值:
code10.png
如果想把Variable的值重置为初始值,就再run一次init操作:
code11.png
未完待续.......
qrcode.jpg
网友评论