第1话 TensorFlow基础概念 (计算图、张量、会话、常量、变量、占位符)

cherry
(代码基于tensorflow 1.14 cpu版本,读者须要具备良好的python基础线性代数知识)html

第三章主要介绍TensorFlow计算模型数据模型运行模型,对TensorFlow的工做原理能有一个大体了解。node

TensorFlow程序通常分为两个阶段。第一阶段:定义计算图中全部的计算,而后定义一个计算来获得他们的和;第二阶段:执行计算。python

1 计算图————TensorFlow的计算模型

1.1 计算图的概念

TensorFlow这个单词由两部分组成:tensor表明张量,是数据模型;flow表明流,是计算模型。下面就引出Flow的具体内涵。数组

流动的事务具备有向性,计算图是一个具备 “每个节点都是计算图上的一个节点,而节点之间的边描述了计算之间的依赖关系” 性质的有向图。(计算图和数据结构这门课程中的有向图具备高度的类似性,如今能够回忆一下这段记忆)promise

计算图由边(表示依赖关系,又被叫作“张量”)和节点(又被叫作“神经元”、“算子”)组成。若是tensorflow程序只定义了一个Graph,那其内部包含了全部的op和tensor缓存

1.2 计算图的使用

在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

2 张量————TensorFlow数据类型

2.1 张量的概念

在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)

  1. 名字name一个张量的惟一标识符以及这个张量是如何计算出来的。

张量的命名形式:“node:src_output”node为节点的名称,src_output表示当前张量来自来自节点的第几个输出。
好比上面的代码的输出"add:0"说明张量result是计算节点“add”输出的第一个结果(编号从0开始)

张量和计算图上节点的计算结果是一一对应的。

  1. 维度shape:描述了一个张量的维度信息。

上面样例的shape(2,)表示一个一维数组,这个数组的长度是2。

  1. 类型type:每个张量都有一个惟一的类型,经常使用的是tf.int32,tf.float32。参与运算的张量须要保持数据类型相同,否则会报错。
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维张量(矩阵)

TensorFlow数据类型和Numpy数据类型的关系

你可能已经注意到了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类型。

2.2 张量的使用

张量使用能够归结为两大类。

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)语句能够获得计算结果

3 会话————TensorFlow运行模型

3.1会话的概念

计算图描述计算
张量是组织数据
会话执行定义好的运算

会话管理TensorFlow程序运行时的全部资源,并在运行结束后释放全部的资源。

会话机制相似于计算图机制:
计算图:在一开始就有一个默认的计算图存在,而且没有特别指定,运算会自动加入到这个默认的计算图中
会话:会要手动建立,张量自动添加。

3.2会话的使用

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.]
'''

4 其余基本概念——常量、变量、占位符

4.1 常量

Python中使用常量很简单,如a=123,b='python'。TensorFlow表示常量稍微麻烦一点,须要使用tf.constant这个类,具体格式以下:

tf.constant(value, dtype=None, shape=None, name="Const", verify_shape=False)

其中各参数说明以下:

  • value : 一个dtype类型(若是指定了)的常量值(列表)。要注意的是,若value是一个列表,那么列表的长度不可以超过形状参数指定的大小(若是指定了)。若是列表长度小于指定的大小,那么多余的空间由列表的最后一个元素来填充。
  • dtype : 返回的tensor的类型
  • shape : 返回的tensorflow的形状
  • name : tensor的名字
  • verify_shape : 布尔值,用于验证值的形状。

示例以下:

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'
'''

4.2 变量

变量是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)

主要参数说明

  • initial_value一个 Tensor类型或者是可以转化为Tensor的python对象类型。它是这个变量的初始值。这个初始值必须指定形状信息,否则后面的参数validate_shape须要设置为False。固然,也可以传入一个无参数可调用而且返回指定初始值的对象,在这种状况下,dtype必须指定。
  • trainable :若是设置为True (默认也为True),这个变量能够被优化器类(optimizer)自动修改Variable的值;若是设置为False,则说明Variable 只能手工修改,不容许使用优化器类自动修改。
  • collections :图的collection键列表,新的变量被添加到这些collection 中。默认是
  • validate_shape :若是是False的话,就容许变量可以被一个形状未知的值初始化,默认是True,表示必须知道形状。
  • caching_device :可选,描述设备的字符串,表示哪一个设备用来为读取缓存。默认是变量的device。
  • name :可选,变量的名称。
  • dtype若是被设置,初始化的值就会按照这里的类型来定。

4.2.1.建立变量

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取的是“建立”的意思

4.2.2.初始化变量

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())

'''
输出>>>
安静宇
安静宇
'''

4.2.3.保存和恢复变量

最后给大家看看安静宇
安静宇

相关文章
相关标签/搜索