一、第一个TF程序
无论学哪种语言的语法, 都要从helloworld开始抓起
第一部分
import 模块包含代码将使用的所有库,在目前的代码中只使用 TensorFlow,其中语句 import tensorflow as tf 则允许 Python 访问 TensorFlow 所有的类、方法和符号。
import tensorflow as tf
第二部分
创建想要的计算图
由于要打印的信息是一个常量字符串,因此使用 tf.constant:
message = tf.constant('helloworld!')
第三部分
通过会话执行计算图,这部分使用 with 关键字创建了会话,最后在会话中执行以上计算图
为了执行计算图,利用 with 语句定义 Session,并使用 run 来运行:
with tf.Session() as sess:
print(sess.run(message).decode())
输出
helloworld!
二、计算图和会话
计算图
计算图包含节点和有向边, 用来表示神经网络,之所以用计算图来表示是因为它可以帮助复杂网络分散计算量,使其以最优效率运行
每个节点代表的不是单一的神经元, 而是张量和运算操作;同时,箭头不代表连接关系,而代表网络中的信息流
每个节点可以有零个或多个输入,但只有一个输出。
所以, 计算图定义神经网络的蓝图
会话
使用会话对象的run来实现计算图的执行
这里真正实现了运算操作并将信息从网络的一层传递到另外一层。不同张量对象的值仅在会话对象中被初始化、访问和保存。在此之前张量对象只被抽象定义,在会话中才被赋予实际的意义。
举个栗子
1、假设有两个向量 v_1 和 v_2 将作为输入提供给 Add 操作。建立的计算图如下:
这里有三个节点, 分别是向量v_1和向量v_2和Add操作符. 同时, 还有两条有向边,分别指向Add节点
注: 关于张量、向量、矩阵、标量的关系将在下一讲专门解释
2、定义该图的相应代码如下所示:
v_1 = tf.constant([1,2,3,4])
v_2 = tf.constant([2,1,5,3])
v_add = tf.add(v_1,v_2) # 或者 v_add = v_1 + v_2
操作符仅仅是计算图上的节点, 所以在会话运行之前, 它们是不会执行的
3、然后在会话中执行这个图:
接下来,为了使这个图生效,首先需要使用 tf.Session() 定义一个会话对象 sess。然后使用 Session 类中定义的 run 方法运行它:
run(fetches,feed_dict=None,options=None,run_metadata)
代码如下:
with tf.Session() as sess:
print(sess.run(v_add))
[3 3 8 7]
以上两行相当于下面的代码。上面的代码的优点是不必显式写出关闭会话的命令
sess = tf.Session()
print(sess.run(v_add))
sess.close() #需要显式写出关闭会话
[3 3 8 7]
请记住,每个会话都需要使用 close() 来明确关闭,而 with 格式可以在运行结束时隐式关闭会话
另外, 提取的值(fetches )不同运行的结果也会不同;在示例中,提取的张量为 v_add, 那么将对与 v_add 相关的张量和操作进行赋值。如果抽取的不是 v_add 而是 v_1,那么最后给出的运行结果会不同.
v_1 = tf.constant([1,2,3,4])
v_2 = tf.constant([2,1,5,3])
v_add = tf.add(v_1,v_2) # v_add = v_1 + v_2
with tf.Session() as sess:
print(sess.run(v_1))
[1 2 3 4]
同理
v_1 = tf.constant([1,2,3,4])
v_2 = tf.constant([2,1,5,3])
v_add = tf.add(v_1,v_2) # v_add = v_1 + v_2
with tf.Session() as sess:
print(sess.run(v_2))
[2 1 5 3]
此外,一次可以提取一个或多个张量或操作对象,例如,如果结果抽取的是 [v_1 v_2 v_add],那么输出如下:
v_1 = tf.constant([1,2,3,4])
v_2 = tf.constant([2,1,5,3])
v_add = tf.add(v_1,v_2) # v_add = v_1 + v_2
with tf.Session() as sess:
print(sess.run([v_1,v_2,v_add]))
[array([1, 2, 3, 4], dtype=int32), array([2, 1, 5, 3], dtype=int32), array([3, 3, 8, 7], dtype=int32)]
三、扩展阅读
为什么必须编写这么多行的代码来完成一个简单的向量加,或者显示一条简单的消息。其实你可以利用下面这一行代码非常方便地完成这个工作:
print(tf.Session().run(tf.add(tf.constant([1,2,3,4]),tf.constant([2,1,5,3]))))
[3 3 8 7]
编写这种类型的代码不仅影响计算图的表达,而且当在 for 循环中重复执行相同的操作(OP)时,可能会导致占用大量内存。养成显式定义所有张量和操作对象的习惯,不仅可使代码更具可读性,还可以帮助你以更清晰的方式可视化计算图
使用TensorBoard可视化图形是 TensorFlow 最有用的功能之一,特别是在构建复杂的神经网络时。我们构建的计算图可以在图形对象的帮助菜单下进行查看。
如果你正在使用 Jupyter Notebook 或者 Python shell 进行编程,使用 tf.InteractiveSession 将比 tf.Session 更方便。InteractiveSession 使自己成为默认会话,因此你可以使用 eval() 直接调用运行张量对象而不用显式调用会话。下面给出一个例子:
sess = tf.InteractiveSession()
v_1 = tf.constant([1,2,3,4])
v_2 = tf.constant([2,1,5,3])
v_add = v_1 + v_2 # v_add = tf.add(v_1,v_2)
print(v_add.eval()) #不用显式调用会话
sess.close()
[3 3 8 7]
原文参考:http://c.biancheng.net/tensorflow/