目录
Tensor? Flow?
import tensorflow as tf
tensor
是张量的意思,顾名思义,是一个能够存储多维数组的tensorflow
数据结构,它的元素可以是int
类型,float
类型,bool
类型,还有string
类型等等.
flow
是流动的意思,tensor
为什么可以flow
呢?我们通过官网的例子来一探究竟.
a = tf.constant(32)
b = tf.constant(10)
c = tf.add(a, b)
sess = tf.Session()
print(sess.run(c))
sess.close()
上面这段代码看上去非常简单,从结果上来看是在计算一个数学表达式32+10
的值,却也完整展示了tensorflow
运行的基本构架.
首先,第一行a = tf.constant(32)
定义了一个常量tensor
,它的值为32
,第二行也是类似.在我们运行tensorflow
程序的时候,任何数据都必须转换成tensor
类型才能够进入这个系统,我们先牢记这一点,之后会对它进行优缺点分析.那么现在我们就有了两个常量tensor
.
但是仅仅定义了两个用于存储数据的tensor
毫无用处,我们希望能够实现的是这两个数的加法运算.相信大家小时候学数学加减法的时候老师都会在黑板上作出这样的图:
到这里, 我们通过构建两个tensor
以及一个operation
完成了一个Graph
的创建. 这些是我们运行tensorflow
程序的标准步骤, 但还并没有结束.
运行以下代码:
此时相信我们中的大部分都会心里产生巨大的疑惑, 怎么会输出这么一堆看不懂的东西, 我只是想让它像定义时那样输出32, 10, 42
就好了啊, 难道我的print
函数坏掉了?无论你如何进行尝试, 你会发现都没有出现你想要的结果, 因为就像刚才说的, 在tensorflow
下, 所有的tensor
都是一种符号, 用来构建整个Graph
的, 它是什么值并不重要, 所以就无法在构建图之后进行打印看它的值了。
TensorFlow将tansor作为节点保存,没有具体的值。
但这显然不是我们想要看到的, 如何才能正确打印这些值呢? 事实上, tensorflow
将构建图和执行图分成了两个独立的步骤, 也就是说你要先构建一个完整的计算图, 此时你无法获取图的具体信息, 但是随后你可以开始进入图的执行过程, 这样你就可以获得图执行时每个tensor
的具体值了.
Tensors:
tensor
还可以有名字, 在定义每个tensor
的时候添加参数name
的值就可以.这是一个可选参数, 不过在后面有很大的意义。
my_name_is_hello = tf.constant('Hello', name='Hello')
my_name_is_world = tf.constant('World', name='World')
print('tensor {}: {}'.format(my_name_is_hello.name, sess.run(my_name_is_hello)))
print('tensor {}: {}'.format(my_name_is_world.name, sess.run(my_name_is_world)))
tensor Hello:0: Hello
tensor World:0: World
Session
(会话)
sess = tf.Session()
# 开启Session(会话)
简单的sess = tf.Session()
就可以搞定. 开启会话后, 我们就可以执行图中的各个tensor
了, 用的正是sess.run()
这个语句.
session
可以打开就需要被关闭, 用下面这行命令
sess.close()
我们可以将执行图的结果保存到正常的变量中, tensorflow
称这个过程为fetch
. 运行下面的命令, 相信你会对fetch
有一个初步的了解.
py_a = sess.run(a)
print(type(py_a))
print(py_a)
py_r = sess.run([a, b, c])
print(type(py_r))
print(py_r[0], py_r[1], py_r[2])
执行图
- TensorFlow运行图中的tensor的过程称做 :“执行图”
- 在TensorFlow中,图的构造和执行时分离的,因此图定义好了,它的执行就是固定的,不会变化。
Operations
tensorflow
原生支持很多的operation
, 以后我们将用op
来简称operation
. 注意, op
也可以有名字用来标识.
就是操作的意思,刚刚把2个tensor 相加,这就是op 以下都是op
Variable
前面的这些是tensorflow
的一些常量tensor
, 通常来说它们一旦被定义就无法更改. 在我们训练机器学习模型的时候, 最重要的一步便是更新参数, 这些常量tensor
无法满足.
那么我们就需要变量(variables
).
variable是TensorFlow下可以修改的tensor,它需要定义一个初始值,可以是数组、列表、numpy矩阵、tensor
也和tensor一样,通过print也不能获得具体的值。
定义variable:
var_a = tf.Variable(0, dtype=tf.int32)
var_b = tf.Variable([1, 2], dtype=tf.float32)
var_w = tf.Variable(tf.zeros((1024, 10)))
每个变量都有一个initializer
的函数, 规定这个变量的初始值是什么. 因此, 在执行图的过程中必须要先初始化变量后才能够使用. 可以通过下面的这些方法进行初始化。
在此之前, 我们先了解一下tensorflow
的交互式session
:InteractiveSession()
,在处理variable
的时候, 它比普通的Session
更为灵活一点。
初始化
- 开启交互式`session`:
sess = tf.InteractiveSession()
- 一次性初始化所有的变量:
init = tf.global_variables_initializer()
sess.run(init)
init = tf.global_variables_initializer()
init.run()
- 初始化某些变量
init_ab = tf.variables_initializer([var_a, var_b])
init_ab.run()
- 初始化某个变量
var_w.initializer.run()
初始化完成后仍然不能打印值, 需要用session
去run
这个variable
,或者是调用InteractiveSession
下面的eval()
函数, 大家观察一下下面输出的不同
W = tf.Variable(10)
sess.run(W.initializer)
print(W)
print(sess.run(W))
print(W.eval())
Variable赋值
assign
是为variable
赋值的一个op
,大家可以看下面的代码来理解operation
和assign
的应用
错误示例:
W.assign(100)
W.initializer.run() # 这里只是run初始化时的值,就是10
print(W.eval(sess))
10
正确示例:
assign_op = W.assign(100)
W.initializer.run()
assign_op.eval()
print(W.eval())
print(assign_op.eval())
100
100
Placeholder占位符
在前面我们介绍计算图的时候, 我们注意到构建图的时候可以脱离具体值进行定义它的整体结构, 在运行的时候可以根据需要带入具体的数值. 可是前面我们定义的常量tensor
以及变量tensor
都需要一个初始值. 因此, 为了更加契合图的构建过程, tensorflow
引入了一个占位符.(placeholder
)的概念. 字如其面, 它只是占着构建图的一个位置,没有具体数值, 但必须要有具体的类型以及形状.
##定义一个占位符
##`tf.placeholder(dtype, shape=None, name=None)`
# 定义一个`float32`型的占位符,它是一个长为3的向量
a = tf.placeholder(tf.float32, shape=[3])
# 定义一个`bool`型的占位符, 它是一个`1x2`的矩阵
b = tf.placeholder(tf.bool, shape=[1, 2])
给placeholder赋值:feed
如果我们还像之前那样企图用a.eval()
的话, 就会体会到placeholder
的特别之处, 因为它真的没有任何值! 实际上,在执行图的过程中, 我们必须要用字典的方式给placeholder
喂入具体值, 字典的key是placeholder,value就是具体的值,这个过程称为feed
.
print(sess.run(a, feed_dict={a: [1, 2, 3]}))
print(sess.run([a, b], feed_dict={a: [1, 2, 3], b: [[True, False]]}))
graph
TensorFlow是通过定义静态图的方法来运行的,在执行图之前, 需要将整个计算图都构建完成。我们当然可以获得这张计算图,这张图就是我们前面定义的所有tensor的集合。
能获得这个完整的图:
g = tf.get_default_graph()
print(g)
得到这个图之后, 我们当然可以往前回溯我们创建过的图的每一个节点, 通过g.get_operations()
就可以查到所有的节点. 我们还可以通过g.get_tensor_by_name()
获得对应name
的tensor
查到所有的节点:
for op in g.get_operations():
print(op.name)
获得对应name
的tensor:
what_is_this = g.get_tensor_by_name('Hello:0')
print(what_is_this.eval())
Hello
graph可视化:tensorboard
tensorboard
在我们安装tensorflow
的过程中就已经被自动安装了, 非常方便.
在它的帮助下, 我们可以将刚才我们构造的图可视化, 让它变得更加清晰直观.
- 首先我们需要将我们想要可视化的图导入到
tensorboard
可以解析的文件中
with tf.Session() as sess:
graph_writer = tf.summary.FileWriter('.', sess.graph)
这个时候在当前目录中你就会多一个events.*
的文件, 这个就是需要的文件.
- 然后我们在当前目录打开终端(一般来说是右键, 点击
Open in New Terminal
或者是在终端中打开),键入以下命令:
$ tensorboard --logdir=.
不会再当前目录打开cmd的查看:https://blog.csdn.net/sinat_32238399/article/details/85927822
- 然后就会有一个这样的输出
如果显示:“Original error was: DLL load failed: 找不到指定的模块”
请查看:https://www.cnblogs.com/jisongxie/p/10248879.html
- 然后我们打开浏览器, 输入
at
后面的链接(不要输入at!!!!),进入.你就会发现这样的界面
如果显示:
无法访问此网站127.0.0.1 拒绝了我们的连接请求。
在cmd中引入tensorboard后的链接在网页中显示为服务器拒绝链接(换浏览器也不行)
在网上看了很多方法后发现将原本链接中的计算机名改为localhost,即http://localhost:6006/后能成功解决该问题,显示结果
至此, 我们完成了tensorflow
的初步概览. 接下来我们将要进入深度学习环节.