写给初学者的Tensorflow介绍
Posted 云水木石
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了写给初学者的Tensorflow介绍相关的知识,希望对你有一定的参考价值。
注:这是一篇翻译的文章,原文地址:https://towardsdatascience.com/a-beginner-introduction-to-tensorflow-part-1-6d139e038278
Tensorflow是广泛使用的实现机器学习以及其它涉及大量数学运算的算法库之一。Tensorflow由Google开发,是GitHub上最受欢迎的机器学习库之一。Google几乎在所有应用程序中都使用Tensorflow来实现机器学习。 例如,如果您使用到了Google照片或Google语音搜索,那么您就间接使用了Tensorflow模型。它们在大型Google硬件集群上工作,在感知任务方面功能强大。
本文的主要目的是为TensorFlow提供一个对初学者友好的介绍,我假设您已经知道一些python知识。 TensorFlow的核心组件是通过边遍历所有节点的计算图和张量。我们来逐个简单介绍一下。
张量(Tensor)
在数学上,张量是N维向量,这意味着张量可以用来表示N维数据集。上面的图有点复杂,难以理解。我们看看它的简化版本:
上图显示了一些简化的张量。随着维度的不断增加,数据表示将变得越来越复杂。例如,一个3x3的张量,我可以简单地称它为3行和列的矩阵。如果我选择另一个形式的张量(1000x3x3),我可以称之为一个向量或一组1000个3x3的矩阵。在这里我们将(1000x3x3)称为张量的形状或尺寸。张量可以是常数也可以是变量。
计算图(流, flow)
现在我们理解了Tensor的含义,是时候了解流(Flow)了。流是指一个计算图或简单的一个图,图不能形成环路,图中的每个节点代表一个操作,如加法、减法等。每个操作都会导致新的张量形成。
上图展示了一个简单的计算图,所对应的表达式为:
e = (a+b)x(b+1)
计算图具有以下属性:
叶子顶点或起始顶点始终是张量。意即,操作永远不会发生在图的开头,由此我们可以推断图中的每个操作都应该接受一个张量并产生一个新的张量。同样,张量不能作为非叶子节点出现,这意味着它们应始终作为输入提供给操作/节点。
计算图总是以层次顺序表达复杂的操作。通过将a + b表示为c,将b + 1表示为d,可以分层次组织上述表达式。 因此,我们可以将e写为:
e = (c)x(d) 这里 c = a+b 且 d = b+1.
以反序遍历图形而形成子表达式,这些子表达式组合起来形成最终表达式。
当我们正向遍历时,遇到的顶点总是成为下一个顶点的依赖关系,例如没有a和b就无法获得c,同样的,如果不解决c和d则无法获得e。
同级节点的操作彼此独立,这是计算图的重要属性之一。当我们按照图中所示的方式构造一个图时,很自然的是,在同一级中的节点,例如c和d,彼此独立,这意味着没有必要在计算d之前计算c。 因此它们可以并行执行。
计算图的并行
上面提到的最后一个属性当然是最重要的属性之一。它清楚地表明,同级的节点是独立的,这意味着在c被计算之前不需空闲,可以在计算c的同时并行计算d。Tensorflow充分利用了这个属性。
分布执行
Tensorflow允许用户使用并行计算设备更快地执行操作。计算的节点或操作自动调度进行并行计算。这一切都发生在内部,例如在上图中,可以在CPU上调度操作c,在GPU上调度操作d。下图展示了两种分布式执行的过程:
第一种是单个系统分布式执行,其中单个Tensorflow会话(将在稍后解释)创建单个worker,并且该worker负责在各设备上调度任务。在第二种系统下,有多个worker,他们可以在同一台机器上或不同的机器上,每个worker都在自己的上下文中运行。在上图中,worker进程1运行在独立的机器上,并调度所有可用设备进行计算。
计算子图
子图是主图的一部分,其本身就是计算图。例如,在上面的图中,我们可以获得许多子图,其中之一如下所示
上面的图是主图的一部分,从属性2我们可以说子图总是表示一个子表达式,因为c是e的子表达式。 子图也满足最后一个属性。同一级别的子图也相互独立,可以并行执行。因此可以在一台设备上调度整个子图。
上图解释了子图的并行执行。这里有2个矩阵乘法运算,因为它们都处于同一级别,彼此独立,这符合最后一个属性。由于独立性的缘故,节点安排在不同的设备gpu_0和gpu_1上。
在worker之间交换数据
现在我们知道Tensorflow将其所有操作分配到由worker管理的不同设备上。更常见的是,worker之间交换张量形式的数据,例如在e =(c)*(d)的图表中,一旦计算出c,就需要将其进一步传递给e,因此Tensor在节点间前向流动。 该流动如图所示:
此处张量从设备A传递到设备B。这在分布式系统中引起了一些性能延迟。延迟取决于一个重要属性:张量大小。设备B处于空闲模式,直到它接收到设备A的输入。
压缩的必要性
很显然,在计算图中,张量在节点之间流动。在流到达可以处理的节点之前,减少流造成的延迟非常重要。一个方法是使用有损压缩减小尺寸。
张量的数据类型可以发挥重要作用,让我们来理解为什么。很明显机器学习中的操作中有更高的精度。例如,如果我们使用float32作为张量的数据类型,那么每个值都表示为32位浮点数,因此每个值占用32位的大小,这同样适用于64位。假设一个形状为(1000,440,440,3)的张量,其包含的值的数量为1000 * 440 * 440 * 3。如果数据类型是32位,那么占用的空间是这个巨大数字的32倍,从而增加了流的延迟。压缩技术可以用来减小尺寸。
有损压缩
有损压缩涉及压缩数据的大小,并不在意它的值,这意味着它的值可能会在压缩过程中被破坏或不准确。 但是,如果我们有一个像1.01010e-12这样的32位浮点数,那么对于最低有效数字的重要性就会降低。 更改或删除这些值不会在我们的计算中产生太大的差异。因此,Tensorflow会自动将32位浮点数转换为16位表示,忽略所有可忽略的数字。如果它是64位数,则会将其大小减少近一半。如果将64位数压缩到16位将几乎缩小75%。因此张量所占用的空间可以尽可能减少。
一旦张量到达节点,16位表示可以通过追加0回到它的原始形式。因此,32或64位表示将在到达节点进行处理后被还原。
到这里,我们就结束了Tensorflow介绍的第1部分,编程和构建简单的子图将在下一部分进行介绍。
以上是关于写给初学者的Tensorflow介绍的主要内容,如果未能解决你的问题,请参考以下文章