知识图谱
TensorFlow运行机制
TensorFlow是基于计算图的深度学习编程模型
Tensor表示张量,其实质上是某种类型的多维数组
Flow表示基于数据流图的计算,实质上是张量在不同节点间的转化过程。
在TensorFlow中,计算图中的节点称为OP(即operation的缩写),节点之间的边描述了计算之间的依赖关系。
在计算过程中,一个节点可获得0或多个张量,产生0或多个张量。
TensorFlow程序通常被组织成图的构建阶段和执行阶段
在构建阶段,节点的执行步骤被描述成一个图
在执行阶段,使用会话执行图中的OP
TensorFlow系统架构
TensorFlow支持各种异构平台,支持多CPU/GPU、移动设备、具有良好的跨平台的特性;
架构灵活,能支持各种网络模型,具有良好的通用性。
系统结构以C API为界限,将整个系统分为前端和后端两个系统
如图所示组件构成TensorFlow 系统分布式运行机制的核心,其中每个组件的作用如下。
Client: 是前端系统的主要组成部分。它是一个 支持多语言的编程环境, 提供了基于计算图的编程模型,方便用户构造各种复杂的计算图,实现各种形式的模型设计。
Distrubuted Runtime: 在分布式的运行时环境中,Distributed Master根据Session.run的Fetching 参数,从计算图中反向遍历,找到所依赖的最小子图。对于每个任务,TensorFlow 都将启动一个Worker Service,按照计算图中节点之间的依赖关系,根据当前的可用的硬件环境(CPU/GPU),调用节点的Kernel实现完成节点的运算。
Kermnel Implements: 大多数Kernel 基于Eigen::Tensor实现。Eigen:Tensor 是一 个使用C++模板技术,为多核CPU/GPU生成高效的并发代码,包含200 多个标准的张量,包括数值计算、多维数组操作、控制流、状态管理等。每一个节点根据设备类型都会存在一个优化了的Kernel实现,在运行时,运行时根据本地设备的类型,为节点选择特定的Kernel实现,完成该节点的计算
构建计算图
计算图描述了一组需要依次序完成的计算单元以及这些计算单元之间相互依赖的关系。
计算图的构建阶段也称为计算图的定义阶段,该过程会在图模型中定义所需的运算,每次运算的结果以及原始的输入数据都可称为一个节点。
下面代码给出了计算图的定义过程
上述代码定义了两个张量相加的计算图如下
每个节点表示一个运算,每条边代表计算之间的依赖关系。
a、b节点表示两个1行2列的矩阵,result节点则依赖于读取a和b的值,从a、b有两条到result的边,没有任何计算依赖result的结果,result节点没有指向其他节点的边。
#导入tensorflow类库,取别名为tf
import tensorflow as tf
#定义一个整型张量a,表示1行2列的矩阵,其值为[3,5]
a = tf.constant([3,5],dtype=tf.int32)
#定义一个整型张量b,表示1行2列的矩阵,其值为[2,4]
b = tf.constant([2,4],dtype=tf.int32)
#tf.add()函数用于对张量a,b相加,并将计算结果返回给result节点。
result = tf.add(a,b)
#print(result)函数打印result节点的信息
print(result)
运行程序,输出结果如下:
Tensor("Add_1:0", shape=(2,), dtype=int32)
从运行结果上可看出,上述程序并没有输出矩阵相加的结果,而是输出了一个包含3个属性的张量,第1个属性表示加法运算,第2个属性表示包含2个元素的一维数组,第3个属性表示数据类型为整型。
需要注意的是,TensorFlow计算图一般包含两个特殊节点,分别为Source节点(也称Start节点)与Sink节点(也称为Finish节点)。其中,Sourse节点表示此节点不依赖任何其他节点作为输入,Sink节点表示该节点无任何输出作为其他节点的输入。
在会话中运行计算图
在TensorFlow中启动会话有两种方法:
①明确调用创建会话函数和关闭会话函数,代码格式如下:
#创建一个会话
sess = tf.Session()
#使用该会话来运行相关节点,得到运算结果
sess.run(...)
#关闭会话
sees.close()
上述代码中,所有计算完成后,需要明确调用close()函数来关闭会话并释放资源。
若程序因为异常退出,就可能无法执行close()函数,进而导致资源泄露。为了解决异常退出时的资源泄露问题,TensorFlow中还可通过上下文管理器来管理会话。
②通过上下文管理器来管理会话,代码格式如下:
#创建一个会话,并使用上下文管理器管理会话
with tf.Session() as sess:
#使用该会话来运行相关节点,得到运算结果
sees.run(...)
#不需要调用close()函数,当上下文退出时会话关闭,资源自动释放
下面通过上下文管理器来实现两个张量的相加,代码如下:
在TensorFlow,系统会自动维护默认的计算图
通过tf.get_default_graph()函数可以获得当前的默认的计算图,代码如下
import tensorflow as tf
a = tf.constant([1.0,2.0],name = 'a')
b = tf.constant([1.0,2.0],name = 'b')
result = a + b
print(a.graph is tf.get_default_graph)
第五行代码:通过a.graph查看张量所属的计算图。如果没有特别指定,则查看当前默认的计算图
指定GPU设备
如果下载的Tensorflow是GPU版本,在程序运行过程中系统会自动检测可用利用的GPU来执行操作
如果计算机上有不止一个GPU资源,除第一个之外,其他的GPU不参与计算。为了让Tensorflow能够使用这些GPU资源,必须将节点明确地指派给定的GPU执行。
with……device语句用来指定CPU或GPU
示例:
import tensorflow as tf
with tf.device('/gpu:1') # 指定在第一块GPU设备上运行v1 = tf.constant([1.0,2.0,3.0],shape = [3],name = 'v1')v2 = tf.constant([4.0,5.0,6.0],shape = [3],name = 'v2')sum = v1 + v2
with tf.Session() as sess:print(sees.run(sum))
TensorFlow数据类型
张量及其属性
张量是TensorFlow中最重要的数据结构,用来表示程序中的数据。
在计算图节点间传递的数据都是张量
可以把张量看作一个n维数组或列量,每个张量都包含 类型、阶、形状
类型
TensorFlow吸收了Python的原生数据类型,如布尔型,数值型(整数、浮点数)和字符串型。
除此之外,TensorFlow还有一些自有的数据类型
数据类型 | 描述 |
tf.float32 | 32位浮点数 |
tf.float64 | 64位浮点数 |
tf.int64 | 64位有符号整型 |
tf.int32 | 32位有符号整型 |
tf.int16 | 16位有符号整型 |
tf.int8 | 8位有符号整型 |
tf.uint8 | 8位无符号整型 |
tf.string | 可变长的字节数组,每一个张量元素都是一个字节数组 |
tf.bool | 布尔型 |
tf.complex64 | 由两个32位浮点数组成的复数:实数和虚数 |
以下代码定义了不同类型的张量
import tensorflow as tf
hello = tf.constant("Hello,world!",dtype=tf.string)
boolean = tf.constant(False,dtype=tf.bool)
int = tf.constant(100,dtype=tf.int8)
uint = tf.constant(100,dtype=tf.uint8)
float = tf.constant(100,dtype=tf.float32)
with tf.Session() as sess:print(sess.run(hello))print(sess.run(boolean))print(sess.run(int))print(sess.run(uint))print(sess.run(float))
阶
在TensorFlow系统中,张量的维数被描述为阶。
注意,张量的阶和矩阵的阶并不是同一个概念,张量的阶是张量维数的数量描述。
例如:下面张量是2阶张量
t = [[1,2,3],[4,5,6],[7,8,9]] (最外层中括号有几个就是几阶)
一阶张量可以认为是一个向量,二阶张量可以认为是二维数组,用t[i,j]访问其中的元素,三阶张量可以用t[i,j,k]访问其中的元素
常见的张量及其对应的阶
阶 | 实例 | 例子 |
0 | 纯量(只有大小) | a = 1 |
1 | 向量(大小和方向) | v = [1,2,3] |
2 | 矩阵(二维数组) | m = [[1,2,3],[4,5,6],[7,8,9]] |
3 | 3阶张量(数据立体) | t=[[[1],[2],[3]],[[4],[5],[6]],[[7],[8],[9]]] |
N | n阶 | n中的括号数 |
形状
形状用于描述张量内部的组织关系。
简单来讲,就是该张量有几行几列
下面来定义一个张量,并分别输出张量的类型、形状以及阶
import tensorflow as tf
c = tf.constant([[3.0,4.0,5.0],[6.0,7.0,8.0]])
print("张量类型:",c.dtype)
print("张量形状:",c.get_shape())
print("张量的阶:",c.get_shape().ndims)
类型转换
TensorFlow程序运行过程中,常常会涉及不同类型张量之间相互转换。
TensorFlow提供了多种类型转换函数,其语法格式为:
函数名 | 含义 |
tf.string_to_number(string_tensor,out_type = None,name = None) | 将字符串转换为数字 out_type:可选tf.float32、tf.int32,默认为f.float32 |
tf.to_double(x,name = None) | 将其他类型转换为double类型 |
tf.int32(x,name = None) | 将其他类型转换为int32 |
tf.cast(x,dtype,name = None) | 将x的值转换为dtype指定的类型 |
下面我们来将整型张量转换为浮点张量
import tensorflow as tf
float_tensor = tf.cast(tf.constant([1,2,3]),dtype=tf.float32)
init = tf.global_variables_initializer()
with tf.Session() as sess:sess.run(init)print(sess.run(float_tensor))
形状变换
在实际应用过程中,有时需要将张量从一个形状转换为另外一个形状,以满足计算需要
TensorFlow中,reshape()函数用来实现张量的形状变换,其语法格式如表:
函数 | 说明 |
tf.reshape( tensor, shape, name=None) | 将张量从一个形状变换为另一个形状 tensor:待改变形状的tensor shape:必须是int32或int64,决定了输出张量的形状 name:可选,操作名称 如果形状的一个分量是特殊值-1,则计算该维度的大小,以使总大小不变 |
import tensorflow as tf #导入tensorflow类库,别名为tf
#定义c1是一维张量,共有12个元素
c1 = tf.constant([1,2,3,4,5,6,7,8,9,10,11,12],dtype = tf.float32,name = "c1")
c2 = tf.reshape(c1,[2,3,2])
with tf.Session() as sess:sess.run(tf.global_variables_initializer())print(sess.run(c2))
下一节,简单介绍变量的内容