Tensorflow背后的核心概念的说明性介绍
什么是TensorFlow
TensorFlow(TF)是一个开源数值计算框架,提供常规使用的机器学习(ML)和深度学习(DL)工具的抽象,以及构建新模型,优化器,损失函数等的能力。相对于无数的在其他ML / DL库中,TensorFlow在研究所需的灵活性与在生产中部署应用程序所需的可扩展性和效率之间提供了关键的平衡。
TF框架使用两个基本概念:
- DataFlow编程范式
- 封装数据作为张量
DataFlow编程范式
大多数程序员所接触的编程范式都是命令式编程。这里的代码是一系列命令,在这些命令中,控制以有序的方式通过代码来生成所需的输出。命令式程序的主要关注点是关于接下来要执行的语句,而不是所述执行所需的数据。更简洁,命令式编程是控制流而不是数据流。
在DataFlow编程中,代码是需要执行的操作定义的集合。操作可以是添加两个数字这样简单的操作,以执行复杂的优化例程。操作可能依赖于某些输入数据,也可能依赖于其他操作的输出。对操作进行评估的主要需求是其所有输入的可用性,从而使其对数据进行响应,因此称为数据流。
DataFlow和TensorFlow
数据流程序的代码通常可视化为有向图,其节点是操作,传入的边表示在操作之间流动的数据。因此,任何TF应用程序的第一步是构建DataFlow图。例如,为了在TF中添加两个数字,我们通过将操作定义为图节点和将对其他操作的依赖关系定义为边来构建图。下图中的三行TF代码正是如此。第1行和第2行定义了保存导致创建蓝色和绿色节点的数据的操作。第3行定义了add操作,由于它使用ip1_op和ip2_op作为op的参数,红色节点和两个红色边缘被创建。需要注意的一件重要事情是,此时3+5尚未进行实际评估,只建立了图。
在数据流编程范式中,执行的概念被看作是数据流经有向图的评估。在TF中,我们计算节点,而不是直接执行图。由于节点具有依赖性,我们最终只计算由这些依赖性引起的子图。如下图所示,对add节点的评估将导致input1和input2节点(此处为3和5)中的数据流流向add节点。由于add节点的所有依赖项现在都已满足,因此它将继续计算自身,即计算3+5=8。因此,按照TF的说法,我们说节点add的值是8。类似地,当我们计算pow节点时,首先计算依赖节点add和sqrt,然后pow节点有必要的数据来计算自己。
Graph Evaluation
为了评估节点,我们使用了一个tf.Session对象。会话对象充当容器,以对图的执行环境进行上下文关联。可以将会话视为DataFlow图的执行引擎 - 要评估的节点被发送到会话,它评估诱导的子图,并吐出输出。执行代码的实际物理位置,即CPU,GPU,TPU,分布式云等,由会话对象管理。也就是说,我们可以灵活地指定我们希望执行某些操作的位置。
为什么要使用DataFlow范式?
许多ML / DL模型(神经网络,Grahpical模型等)表示为用于可视化其理论定义的图。使用图作为这种模型的计算模型是一种自然的延伸。此外,使用图来模拟ML / DL问题也具有许多计算优势。例如,操作(节点)的计算仅需要执行连接到操作的子图,从而节省计算时间。这也允许将计算分解成更小的片段,这有利于分布式计算(将计算分散到不同的CPU,GPU,TPU等)。
大多数ML / DL应用程序都有一个优化器组件,它经常使用基于梯度的方法来最小化损失函数。传统上,损失函数的梯度是手动评估的,并提供给优化器 - 这是繁琐的,有时本身就是一个难题。通过将模型表示为图,我们可以促进自动微分的使用,以消除导出和实现梯度函数的手动步骤。
封装数据作为张量
张量是一个数学对象,表示为多维数字数组。根据上下文,它可能意味着许多事情。例如,张量可以是矢量,标量甚至其他张量之间的线性变换。
可以把张量看作是一种能够以结构化的方式存储对象的存储单元。下图说明了张量在维数上增长时的结构和索引。
在上面的图中,cell表示为用于访问存储值的索引模式。当维数增加时,高维数的指数被固定在左边。例如,2-D张量(矩阵)中的元素被索引为(row, column),而在3-D张量中,则为(depth, row, column)。
很难将大于三维的张量结构可视化。一个技巧是将更高维度视为以结构化(索引)方式存储低维张量阵列的容器。例如,4-D张量是3-D张量的阵列。
类似地,5-D张量是4-D张量的阵列。
一个简单的TensorFlow程序
"""
In this block of code we perform the building of the DataFlow graph to
implement a simple TensorFlow application the performs addition, sqrt,
and the power operations.
"""
# Import the tensorflow library
import tensorflow as tf
# Need to reset the default graph to make sure that graph components from
# previous executions in the same notebook are not present in the graph.
tf.reset_default_graph() # Ignore this at first read.
# Simple operations with 0-D tensors (scalars)
# The constants are given float32 data type to confirm with definition of sqrt
ip1_op = tf.constant(3, name='input1', dtype=tf.float32) # op to hold data 3
ip2_op = tf.constant(5, name='input2', dtype=tf.float32) # op to hold data 5
add_op = tf.add(ip1_op, ip2_op, name="add") # Addition op
# The following is also correct, here TF automatically creates the constant op
# necessary to hold "3" and "5" in the TF graph.
# add_op = tf_add(3, 5, name="add")
sqrt_op = tf.sqrt(ip2_op, name="sqrt") # Takes sqrt of the input2 op
# Exponentiates the value of the add op with the value of the sqrt op.
pow_op = tf.pow(add_op, sqrt_op, name='pow')
# Ignore on First Read
g = tf.get_default_graph() # Get the graph as as an object for Tensorboard
# Make sure that the writer is created only after building the complete graph.
writer = tf.summary.FileWriter('graph', graph=g) # Ignore on first read
""" Evaluate the different nodes in the graph """
# Sessions are responsible for executing a graph (or parts of it) on the
# various computational resources available (CPUs, GPUs, TPUs etc.).
with tf.Session() as sess:
output = sess.run([add_op, sqrt_op, pow_op])
print(output)
writer.close()
[Out]
[8.0, 2.236068, 104.56122]
Tensorboard是随TensorFlow框架一起提供的图形可视化工具。TF提供的FileWriter API将数据流图写入文件,以便Tensorboard能够生成可视化。
结论
TensorFlow是使用DataFlow范式构建的数值计算库,其中在操作之间流动的数据是张量。在TensorFlow中,学习算法表示为数据流图,输入数据表示为流经此图的张量。这就是框架恰当地命名为TensorFlow的原因。下图是一个动画,描述了输入张量通过数据流图的流程。它还展示了并行性是如何作为数据流范式的内置特性出现的。
由于代表TF应用程序的图性质,我们能够以无数种方式组合操作,为研究人员提供实现新想法所需的灵活性。TF还利用DataFlow图提供的内置并行性来提供高效的计算能力。此外,定义和计算之间的明确分离使我们能够轻松地为TF应用程序启用分布式计算,使TensorFlow成为企业ML / DL应用程序的理想框架。