TensorFlow的使用,遵循以下几点:

  • 使用图(graph)来表示计算任务
  • 在会话(session)中执行图
  • 使用tensor表示数据
  • 通过变量(Variable)维护状态
  • 使用feed和fetch可以为任意的操作(arbitrary operation)赋值或者从其中获取数据

一、综述

TensorFlow是一个编程系统,使用图来表示计算任务。图中的节点是一个操作(op),一个op获得0个或多个tensor,执行计算,产生0个或多个tensor。每个tensor是一个类型化的多维数组。一个TensorFlow图描述了计算的过程。为了进行计算,图必须在会话里启动。会话将图的op分发到诸如CPU或GPU之类的设备上,同时提供执行op的方法。这些方法执行后,将产生的tensor返回。在Python语言中,返回的tensor是numpy ndarray对象。

二、计算图和构建图

1. 计算图

TensorFlow程序通常被组织成一个构建阶段和一个执行阶段。在构建阶段,op的执行步骤被描述成一个图。在执行阶段,使用会话执行图中的op。比如,通常在构建阶段创建一个图来表示和训练神经网络,然后在执行阶段反复执行图中的训练op。

2. 构建图

构建图的第一步,是创建源op。源op不需要任何输入,例如常量(Constant),源op的输出被传递给其它op做运算,Python中,op构造器的返回值代表被构造出的op的输出,这些返回值可以传递给其它op构造器作为输入。TensorFlow Python库有一个默认图,op构造器可以为其增加节点。这个默认图对许多程序来说已经足够用。

import tensorflow as tf
# 创建一个常量op,产生一个1x2矩阵,为一个节点,加到默认图中,返回值 代表op的返回值
matrix1 = tf.constant([[3., 3.]])
# 创建另外一个常量op,产生一个2x1矩阵,也为一个节点
matrix2 = tf.constant([[2.], [2.]])
# 创建一个矩阵乘法操作op,把上边常量作为输入,返回值作为乘法的结果
product = tf.matmul(matrix1, matrix2)
print(product)

输出:Tensor("MatMul:0", shape=(1, 1), dtype=float32)

我们创建了三个节点,也就是说默认图中现在有三个节点,两个常量和一个乘法。此时使用print()语句,打印出来的结果是一个张量。此时的操作还没有执行,我们必须启动会话,在会话中执行这个操作。

三、在会话中启动图

构造阶段完成后,我们就进入执行阶段,执行阶段我们需要在会话中启动图。启动图的第一步是创建一个Session对象,如果无任何创建参数,启动的就是默认图。

# 启动默认图
sess = tf.Session()
# 执行操作
result = sess.run(product)
print(result)
# 关闭会话
sess.close()

执行之后,我们得到了运算结果:[[12.]]。这是在TensorFlow中一个最简单程序的执行过程。在创建session的方法中,还有另外一种

with tf.Session() as sess:
    result = sess.run([product])
    print(result)

这种启动图的方式有点是不需要手动关闭session。为了便于使用诸如IPython之类的python交互环境,可以使用InteractiveSession代替Session类,是用Tensor.eval()和Operation.run()方法代替Session.run().这样可以避免使用一个变量来持有会话。

import tensorflow as tf

sess = tf.InteractiveSession()

# 创建节点
x = tf.Variable([1.0, 2.0])
a = tf.constant([3.0, 3.0])

# 使用初始化器的run()方法初始化x
x.initializer.run()

# 增加一个减法操作.
sub = tf.subtract(x, a)
print(sub.eval())

四、Tensor

TensorFlow程序使用tensor数据结构来代表所有的数据,计算图中,操作间传递的数据都是tensor,你可以吧TensorFlow看做是一个n维数组或列表,一个tensor包含一个静态rank,和一个shape。

变量维护图执行过程中的状态信息。下面使用变量来实现一个计数器

# 创建一个变量,初始化为0
state = tf.Variable(0, name='counter')
# 创建一个op,作用是state+1
one = tf.constant(1)
new_value = tf.add(state, one)
update = tf.assign(state, new_value)

# 初始化所有变量
init_op = tf.initialize_all_variables()

# 启动图,运行op
with tf.Session() as sess:
    # 运行初始化
    sess.run(init_op)
    # 打印state初始值
    print(sess.run(state))
    # 运行op,更新state
    for _ in range(3):
        sess.run(update)
        print(sess.run(state))

在一段程序中,如果使用到变量。我们就必须在执行图的时候对变量进行初始化。

五、Fetch和Feed

1. Fetch

为了取回操作的输出内容,可以在使用Session对象的run()调用执行图时,传入一些tensor,这些tensor会帮助你取回结果。在之前的例子里。我们只能取回单个state。但是也可以取回多个tensor。

input1 = tf.constant(3.0)
input2 = tf.constant(2.0)
input3 = tf.constant(5.0)
intermed = tf.add(input2, input3)
mul = tf.multiply(input1, intermed)

with tf.Session() as sess:
    result = sess.run([mul, intermed])
    print(result)

需要获取的多个tensor值,在op的一次运行中一起获得(而不是逐个区获取tensor)

2. Feed

上面我们学习了变量,常量,都是在创建节点的时候给其初始化值。在TensorFlow中还有一种操作是占位符。tf.placeholder()。该机制可以临时替代图中的任意操作中的tensor可以对图中的任何操作提交补丁,直接插入一个tensor。Feed使用一个tensor临时替换一个操作的输出结果。你可以提供feed数据作为run()调用的参数。feed只有在调用它的方法内有效。方法结束,feed就会消失。

input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.multiply(input1, input2)

with tf.Session() as sess:
    print(sess.run([output], feed_dict={input1: [7.], input2: [2.]}))

结果:[array([14.], dtype=float32)],如果没有提供正确的feed。操作将会产生错误。