最近,深度学习十分火热,之前,一直学习的传统的机器学习算法,所以,现在打算学习下深度学习。下面,参考了一些资料,以我自己方便理解的思路,介绍了下Tensorflow。
目前,深度学习已经广泛应用于各个领域,比如图像识别,图形定位与检测,语音识别,机器翻译等等。然而,要将深度学习更快且更便捷地应用于新的问题中,选择一款深度学习工具是必不可少的步骤。下面将列出几款常用的深度学习开源工具。
本文将主要讲述Tensorflow。Tensorflow是google于2015年11月9日正式开源的计算框架。Tensorflow计算框架可以很好地支持深度学习的各种算法,Tensorflow已经得到了广泛的应用。
张量(Tensor)
TensorFlow,直观来看,由Tensor和Flow组成,即张量的流动。张量表明了它的数据结构,Flow体现了它的计算模型,其中,张量(tensor)可以理解为多维数组。一维、二维、三维、四维等数据统称为张量。而张量的流动则是指保持计算节点不变,让数据进行流动。
这样的设计是针对连接式的机器学习算法,比如逻辑斯底回归,神经网络等。连接式的机器学习算法可以把算法表达成一张图,张量从图中从前到后走一遍就完成了前向运算;而残差从后往前走一遍,就完成了后向传播。
算子(operation)
TensorFlow是一个通过计算图的形式来表述计算的编程系统,它将算法表达成图,TF中的每一个计算(operation)都是计算图上的一个节点,节点会有0到多个输出,下图是TF实现的一些算子。
每个算子都会有属性,所有的属性都在建立图的时候被确定下来,比如,最常用的属性是为了支持多态,比如加法算子既能支持float32,又能支持int32计算。
核(kernel)
TF中还有一个概念是kernel,kernel是operation在某种设备上的具体实现。TF的库通过注册机制来定义operation和kernel,所以可以通过链接一个其他的库来进行kernel和operation的扩展。
边(edge)
计算图中节点之间的边描述了计算之间的依赖关系。TF的图中的边分为两种:
正常边,正常边上可以流动数据,即正常边就是tensor
特殊边,又称作控制依赖,(control dependencies)
没有数据从特殊边上流动,但是特殊边却可以控制节点之间的依赖关系,在特殊边的起始节点完成运算之前,特殊边的结束节点不会被执行。
也不仅仅非得有依赖关系才可以用特殊边,还可以有其他用法,比如为了控制内存的时候,可以让两个实际上并没有前后依赖关系的运算分开执行。
特殊边可以在client端被直接使用
会话(Session)
客户端使用会话来和TF系统交互,一般的模式是,建立会话,此时会生成一张空图;在会话中添加节点和边,形成一张图,然后执行。
变量(Variables)
机器学习算法都会有参数,而参数的状态是需要保存的。而参数是在图中有其固定的位置的,不能像普通数据那样正常流动。因而,TF中将Variables实现为一个特殊的算子,该算子会返回它所保存的可变tensor的句柄。
实际上编写tensorflow可以总结为两步.
假设我们有这样一个需要计算的表达式。该表达式包括了两个加法与一个乘法,为了更好讲述引入中间变量c与d。由此该表达式可以表示为:
当需要计算e时就需要计算c与d,而计算c就需要计算a与b,计算d需要计算b。这样就形成了依赖关系。这种有向无环图就叫做计算图。
Graph仅仅定义了所有 operation 与 tensor 流向,没有进行任何计算。而session根据 graph 的定义分配资源,计算 operation,得出结果。既然是图就会有点与边,在图计算中 operation 就是点而 tensor 就是边。Operation 可以是加减乘除等数学运算,也可以是各种各样的优化算法。每个 operation 都会有零个或多个输入,零个或多个输出。 tensor 就是其输入与输出,其可以表示一维二维多维向量或者常量。而且除了Variables指向的 tensor 外所有的 tensor 在流入下一个节点后都不再保存。
举例
下面首先定义一个图(其实没有必要,tensorflow会默认定义一个),并做一些计算。
登录后复制
import tensorflow as tf
graph = tf.Graph()
with graph.as_default():
foo = tf.Variable(3,name='foo')
bar = tf.Variable(2,name='bar')
result = foo + bar
initialize = tf.global_variables_initializer()
这段代码,首先会载入tensorflow,定义一个graph类,并在这张图上定义了foo与bar的两个变量,最后对这个值求和,并初始化所有变量。其中,Variable是定义变量并赋予初值。让我们看下result(下方代码)。后面是输出,可以看到并没有输出实际的结果,由此可见在定义图的时候其实没有进行任何实际的计算。
登录后复制
print(result) #Tensor("add:0", shape=(), dtype=int32)
下面定义一个session,并进行真正的计算。
登录后复制
with tf.Session(graph=graph) as sess:
sess.run(initialize)
res = sess.run(result)
print(res) # 5
这段代码中,定义了session,并在session中执行了真正的初始化,并且求得result的值并打印出来。可以看到,在session中产生了真正的计算,得出值为5。
这张图整体是一个graph,其中foo,bar,add这些节点都是operation,而foo和bar与add连接边的就是tensor。当session运行result时,实际就是求得add这个operation流出的tensor值,那么add的所有上游节点都会进行计算,如果图中有非add上游节点(本例中没有)那么该节点将不会进行计算,这也是图计算的优势之一。
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删