(代码基于tensorflow 1.14 cpu版本,读者须要具备良好的python基础和线性代数知识)html
第三章主要介绍TensorFlow的计算模型、数据模型和运行模型,对TensorFlow的工做原理能有一个大体了解。node
TensorFlow程序通常分为两个阶段。第一阶段:定义计算图中全部的计算,而后定义一个计算来获得他们的和;第二阶段:执行计算。python
TensorFlow这个单词由两部分组成:tensor表明张量,是数据模型;flow表明流,是计算模型。下面就引出Flow的具体内涵。数组
流动的事务具备有向性,计算图就是一个具备 “每个节点都是计算图上的一个节点,而节点之间的边描述了计算之间的依赖关系” 性质的有向图。(计算图和数据结构这门课程中的有向图具备高度的类似性,如今能够回忆一下这段记忆)promise
计算图由边(表示依赖关系,又被叫作“张量”)和节点(又被叫作“神经元”、“算子”)组成。若是tensorflow程序只定义了一个Graph,那其内部包含了全部的op和tensor缓存
在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 #经过a.graph属性能够查看这个张量所属的计算图。由于没有特地指定,因此这个计算图应该等于当前默认的计算图 print(a.graph is tf.get_default_graph()) ''' 输出>>> True '''
Tensorflow经过计算图把张量和算子等组合在一块儿,而在不少TensorFlow程序中,看不到Graph,这是为什么?这是由于TensorFlow有个默认缺省的graph
(即Graph.as_default()),咱们添加的tensor和op等都会自动添加到这个缺省计算图中,若是没有特别要求,使用这个默认缺省的Graph便可。固然,若是须要一些更复杂的计算,好比须要建立两个相互之间没有交互的模型,就须要自定义计算图。
除了使用默认的计算图,TensorFlow支持经过tf.Graph函数来生成新的计算图。TensorFlow中的计算图不只能够隔绝张量和计算,它还提供了管理张量和计算的机制,不一样计算图上的张量和运算不会共享。
如下代码示意了如何经过在不一样的计算图上定义和使用变量。函数
import tensorflow as tf g1 = tf.Graph() with g1.as_default(): v = tf.get_variable('v', shape=[1], initializer=tf.zeros_initializer) g2 = tf.Graph() with g2.as_default(): v = tf.get_variable('v', shape=[1], initializer=tf.ones_initializer) ''' tf.Graph()没有实现__enter__()方法,作不到下面那优雅pythonic的写法。 with tf.Graph() as g2: v = tf.get_variable('v', shape=[1], initializer=tf.ones_initializer) 这样写了就会抛出AttributeError异常 Traceback (most recent call last): File "D:/bb/TensorFlow/Untitled1.py", line 7, in <module> with tf.Graph() as g2: AttributeError: __enter__ ''' with tf.Session(graph=g1) as sess: tf.global_variables_initializer().run() with tf.variable_scope("", reuse=True): print(sess.run(tf.get_variable('v'))) with tf.Session(graph=g2) as sess: tf.global_variables_initializer().run() with tf.variable_scope("", reuse=True): print(sess.run(tf.get_variable('v'))) ''' 输出>>> [0.] [1.] 注:先不要管代码是什么含义,继续往下看 '''
若是有多个Graph,建议不使用默认的Graph,直接无视或者为其分配一个句柄,避免发生混乱优化
import tensorflow as tf graph1 = tf.Graph() graph2 = tf.Graph() # 直接无视默认缺省的Graph # graph2 = tf.get_default_graph() 为其分配一个句柄 with graph1.as_default(): pass with graph2.as_default(): pass
在TensorFlow的程序中,全部的数据都经过张量(tensor)的形式表示。ui
张量(tensor)理解为多维数组(multidimensional array),0阶张量是标量(scalar),1阶是向量(vector)(即一维数组),2阶是二维数组,n阶为n维数组。
TensorFlow的运算结果不是一个数,而是一个张量结构。(运算和运行在tensorflow语境中不一样,运算就是用过运算符操做,运行就和会话有关,3.3会提到)
import tensorflow as tf a = tf.constant([1.0, 2.0], name='a') b = tf.constant([1.0, 2.0], name='b') result = tf.add(a, b, name='add') print(result) ''' 输出>>> Tensor("add:0", shape=(2,), dtype=float32) '''
一个张量保存了三个属性:名字(name)、维度(shape)和类型(type)
张量的命名形式:“node:src_output”,node为节点的名称,src_output表示当前张量来自来自节点的第几个输出。
好比上面的代码的输出"add:0"说明张量result是计算节点“add”输出的第一个结果(编号从0开始)
张量和计算图上节点的计算结果是一一对应的。
上面样例的shape(2,)表示一个一维数组,这个数组的长度是2。
TensorFlow支持的14种数据类型
有符号整型
tf.int8:8位整数
tf.int16:16位整数
tf.int32:32位整数
tf.int64:64位整数
无符号整型
tf.uint8:8位无符号整数
tf.uint16:16位无符号整数
浮点型
tf.float16:16位浮点数
tf.float32:32位浮点数
tf.float64:64位浮点数
tf.double:等同于tf.float64
字符串型
tf.string:字符串
布尔型
tf.bool:布尔型
复数型
tf.complex64:64位复数
tf.complex128:128位复数
TensorFlow数据类型和Python原生数据类型的关系
TensorFlow接受了Python本身的原生数据类型,例如Python中的布尔值类型,数值数据类型(整数,浮点数)和字符串类型。单一值将转换为0维张量(标量),列表值将转换为1维张量(向量),列表套列表将被转换成2维张量(矩阵)
你可能已经注意到了Numpy和TensorFlow有不少类似之处。TensorFlow在设计之初就但愿可以与Numpy有着很好的集成效果。Numpy软件包如今已经成为数据科学的通用语言。
TensorFlow数据类型不少也是基于Numpy的,事实上,若是你令 np.int32==tf.int32将会返回True.你也能够直接传递Numpy数据类型直接给TensorFlow中的ops。
tf.ones([2, 2], np.float32) ==> [[1.0 1.0], [1.0 1.0]]
请记得,咱们的好朋友会话tf.Session.run(),要求的输入对象是一个Tensor可是它的输出是一个Numpy数组。事实上,在绝大多数场合,你能够同时混合使用TensorFlow类型和Numpy类型。
张量使用能够归结为两大类。
1.第一类对中间计算结果的引用,提高代码的可读性
使用张量和不使用张量的对比
import tensorflow as tf #使用张量记录 a = tf.constant([1.0, 2.0], name='a') b = tf.constant([1.0, 2.0], name='b') result1 = a + b #不使用张量,简洁可是可读性下降 result2 = tf.constant([1.0, 2.0], name='a') + tf.constant([1.0, 2.0], name='b') #jie'guo'xiang't print(result1) print(result2) ''' 输出>>> Tensor("add:0", shape=(2,), dtype=float32) Tensor("add_1:0", shape=(2,), dtype=float32) '''
2.第二类状况是计算图构造完成后,张量能够用来获取计算结果
使用tf.Session().run(result)语句能够获得计算结果
计算图描述计算
张量是组织数据
会话执行定义好的运算
会话管理TensorFlow程序运行时的全部资源,并在运行结束后释放全部的资源。
会话机制相似于计算图机制:
计算图:在一开始就有一个默认的计算图存在,而且没有特别指定,运算会自动加入到这个默认的计算图中
会话:会要手动建立,张量自动添加。
TensorFlow使用会话模式有两种方式
1.普通模式
import tensorflow as tf # 加入了一个异常处理机制,确保释放资源 try: sess = tf.Session() # 建立一个会话 sess.run(...) # 运行,获得计算结果 except Exception: pass finally: sess.close() # 关闭会话,释放资源
2.上下文模式
这才是pythonic的写法,极力推荐
import tensorflow as tf with tf.Session as sess: sess.run() #运行到这个位置会自动释放sess的资源,优雅尼克
这是2.2程序的引用,会话的写法多种多样,咱们应用最优雅、最pythinc的代码去阐述。
import tensorflow as tf a = tf.constant([1.0, 2.0], name='a') b = tf.constant([1.0, 2.0], name='b') result = tf.add(a, b, name='add') with tf.Session() as sess: # tf.Session.run(),要求的输入对象是一个Tensor可是它的输出是一个Numpy数组 print(sess.run(result)) ''' 输出>>> [2. 4.] '''
Python中使用常量很简单,如a=123,b='python'。TensorFlow表示常量稍微麻烦一点,须要使用tf.constant这个类,具体格式以下:
tf.constant(value, dtype=None, shape=None, name="Const", verify_shape=False)
其中各参数说明以下:
示例以下:
import tensorflow as tf # 构建计算图 a = tf.constant('something', name='a') print(a) with tf.Session() as sess: # 创造会话 result = sess.run(a) # 在会话中执行张量a print(result) ''' 输出>>> Tensor("a:0", shape=(2,), dtype=float32) b'something' '''
变量是TensorFlow中的核心概念,建立一个类使用tf.Variable,具体格式以下:
tf.Variable(initial_value=None,trainable=None,collections=None,validate_shape=True,caching_device=None,name=None,variable_def=None,dtype=None,expected_shape=None,import_scope=None,constraint=None,use_resource=None,synchronization=VariableSynchronization.AUTO, aggregation=VariableAggregation.NONE,shape=None)
主要参数说明:
1.如今让咱们使用tf.Variable()建立变量,这是最简单的、最经常使用的变量建立方法。用的最多的两个参数initial_value和name
import tensorflow as tf girl = tf.Variable('安静宇', name='big') # 这个name大有做用,后面会讲到,须要注意的是,name的值不能够是中文,中文会报错 god = tf.Variable('安静宇', name='big') # 使用tf.Variable()建立的实例,实例名是惟一标识符( Variable()内的参数均可以重复 ) # 写做girl = tf.Variable('安静宇', name='big'),就会覆盖第一个girl print('initializer', girl.initializer) print('initial_value', girl.initial_value) print('graph', girl.graph) print('shape', girl.shape) print('name', girl.name) print('dtype', girl.dtype) print('value', girl.value()) ''' 输出>>> initializer name: "big/Assign" op: "Assign" input: "big" input: "big/initial_value" attr { key: "T" value { type: DT_STRING } } attr { key: "_class" value { list { s: "loc:@big" } } } attr { key: "use_locking" value { b: true } } attr { key: "validate_shape" value { b: true } } initial_value Tensor("big/initial_value:0", shape=(), dtype=string) graph <tensorflow.python.framework.ops.Graph object at 0x000001DF1B542EF0> shape () name big:0 dtype <dtype: 'string_ref'> value Tensor("big/read:0", shape=(), dtype=string) '''
2.除了使用tf.Variable()建立变量,还有一个孪生兄弟,tf.get_variable(),他两的业务逻辑仍是很不同的,使用的惟一标识符不同,前者使用实例名做为惟一标志,后者使用name参数做为惟一标志。
具体用法能够参考这篇博客Variable和get_variable的用法以及区别
按照习惯,get开头的函数都是“查询”、“获取”的意思,可是tf.get_variable()是建立变量,get取的是“建立”的意思
tensorflow中,程序存在变量,在使用前必须初始化
初始化变量有两个方法
手动初始化就是
ses.run(var1.initializer) ses.run(var2.initializer) ses.run(var3.initializer)
一次性全局初始化只要使用一个函数 tf.global_variables_initializer()
init_op = tf.global_variables_initializer() sess.run(init_op)
贴一个完整代码
import tensorflow as tf girl = tf.Variable('安静宇', name='cute') god = tf.Variable('安静宇', name='pretty') with tf.Session() as sess: # 必须先初始化变量才能使用,tf.global_variables_initializer()能够初始化全部的变量 sess.run(girl.initializer) sess.run(god.initializer) # 等价于 sess.run(tf.global_variables_initializer()) print(sess.run(girl).decode()) print(sess.run(god).decode()) ''' 输出>>> 安静宇 安静宇 '''
最后给大家看看安静宇