tensorflow中的计算过程可以表示为一个计算图(Computation Graph)或有向图(Direction Graph)。计算图中每一个运算操作视为一个节点(Node),每个节点可以有任意个输入和任意个输出。如果一个运算的输入取值自另一个运算的输出,那么称这两个运算存在依赖关系,存在依赖关系的两个节点通过边(Edge)相互连接。
**张量(Tensor)**就是在边中流动(flow)的数据,其数据类型可以在编程时事先定义,也可以根据计算图中的上下文结构推断而来。
编写TensorFlow程序时,系统会自动维护一个默认的计算图,当我们需要更多的计算图来完成工作的时候,可以通过Graph()函数来生成新的计算图。对于生成的计算图,可以通过as_default()函数将其指定为默认的。
import tensorflow as tf
#使用Graph创建一个计算图
g1 = tf.graph()
with g1.as_defaut():
pass
张量——TensorFlow的数据模型
张量可以简单理解为不同维度的数组,其中零阶张量的表示形式是标量(Scalar),也就是一个数;一阶张量的表示形式是向量,也就是一维数组;二阶张量的表示形式是一个二维数组;以此类推。
张量只是引用了程序中的运算结果而不是一个真正的数组。张量保存的是运算结果的属性并不是真正的数字。
import tensorflow as tf
a = tf.constant([1.0,2.0]name="a")
b = tf.constant([3.0,4.0]name="b")
result = a + b
print(result)
#输出
Tensor("add:0",shape=(2,0),dtype=float32)
result是一个张量,主要保存了加法运算结果的3个属性:操作(op)、维度(shape)和数据类型(dtype)。任意一个张量都具备这3个属性。
可以调用会话session,在调用会话的run()函数时将想要得到真实数字的张量传递进去。
import tensorflow as tf
a = tf.constant([1.0,2.0]name="a")
b = tf.constant([3.0,4.0]name="b")
result = a + b
# 定义会话
with tf.Session() as sess:
tf.initialize_all_variables().run()
print(sess.run(result))
# 输出
[4. 6.]
会话——TensorFlow的运行模型
Session类提供了run()方法来执行计算图
# 函数原型run(self,fetches,feed_dict,options,run_metadata)
在生成会话时,通常会设置构造函数的config参数来配置会话的一些选项,比如并行的线程数、GPU分配策略、运算超时时间等。可以使用TensorFlow提供的ConfigProto()函数的返回值作为config参数的依据。
ConfigProto函数常用的两个参数选项:
(1)log_device_placement,布尔型
为True时,日志中会记录每个节点所用的计算设备并打印,在一定程度上方便调试,但是生产上一般设置为False以减少日志量。
(2)allow_soft_placement,布尔型
True:当运算无法在GPU上执行的时候会转移到CPU上进行。
config = tf.ConfigProto(log_device_placement=True,allow_soft_placement=True)
sess1 = tf.Session(config = config)
#或者用于创建默认会话的时候
sess2 = tf.InteractiveSession(config = config)
Tensorflow变量
声明一个变量需要使用变量声明函数——Variable(),在声明这个变量的时候需要提供初始值,函数内部需要给出该变量的初始化方法。
weights = tf.Variable(tf.random_normal([3,4], stddev=1))
上述代码使用random_normal()函数返回了一个大小为3×4,元素均值为0,标准差为1的随机数矩阵,这些随机数满足正态分布。
常用的随机数生成函数
参考链接https://blog.csdn.net/tz_zs/article/details/75948350#t0。
(1)tf.random_normal
从正态分布中输出随机值。
random_normal(shape,mean=0.0,stddev=1.0,dtype=tf.float32,seed=None,name=None)
shape:一个一维整数张量或Python数组。代表张量的形状。
mean:数据类型为dtype的张量值或Python值。是正态分布的均值。
stddev:数据类型为dtype的张量值或Python值。是正态分布的标准差。
dtype: 输出的数据类型。
seed:一个Python整数。是随机种子。
name: 操作的名称(可选)
(2)tf.random_uniform
从均匀分布中返回随机值。
random_uniform(
shape,# 生成的张量的形状
minval=0,
maxval=None,
dtype=tf.float32,
seed=None,
name=None
)
返回值的范围默认是0到1的左闭右开区间,即[0,1)。minval为指定最小边界,默认为1。maxval为指定的最大边界,如果是数据浮点型则默认为1,如果数据为整形则必须指定。
(3)tf.truncated_normal
truncated_normal(
shape,#一个一维整数张量或Python数组。代表张量的形状。
mean=0.0,#数据类型为dtype的张量值或Python值。是正态分布的均值。
stddev=1.0,#数据类型为dtype的张量值或Python值。是正态分布的标准差
dtype=tf.float32,#输出的数据类型。
seed=None,#一个Python整数。是随机种子。
name=None#操作的名称(可选)
)
常用的常量生成函数
函数名称 | 功能 |
---|---|
zeros() | 产生全0的数组 |
ones() | 产生全1的数组 |
fill() | 产生一个值为给定数字的数组 |
constant() | 产生一个给定值的常量 |
管理变量的变量空间
(1)get_variable()函数
用于创建或者获取变量,在实现创建变量功能时,使用方法与Variable()函数基本相同。
# 通过常数来初始化一个变量
a = tf.Variable(tf.constant(1.0,shape=[1],name='a'))
a = tf.get_variable('a',shape=[1],initializer=tf.constant_initializer(1.0))
在get_variable()函数中,name是必选参数,会根据这个名字创建或者获取变量,这样设计有助于避免由于无意识的变量复用造成的错误。
get_variable()函数通过initializer参数提供初始化方法,这些初始化方法被设计成了一系列的initializer函数。
初始化函数 | 功能 |
---|---|
constant_initializer() | 将变量初始化为给定常量 |
random_normal_initializer() | 将变量初始化为满足正态分布的随机数值 |
truncated_normal_initializer() | 将变量初始化为满足正态分布的随机数值,但如果随机出来的值偏离平均值超过2个标准差,那么这个数将被重新随机 |
random_uniform_initializer() | 将变量初始化为满足平均分布的随机数值 |
uniform_unit_scaling_initializer() | 将变量初始化为满足平均分布但不影响输出数量级的随机数值 |
zeros_initializer() | 将变量初始化为全0 |
ones_initializer() | 将变量初始化为全1 |
conatant_initializer()与常数生成函数constant()在功能上就是一致的。
(2)variable_scope()与name_scope()
在相同的变量空间内使用get_variable()函数创建name属性相同的两个变量会发生错误,可以用variable_scope()函数来控制get_variable()函数获取已经创建过的变量:
import tensorflow as tf
# 在名为one的变量空间内创建名字为a的变量
with tf.variable_scope("one"):
a = tf.get_variable("a", [1], initializer = tf.constant_initializer(1.0))
# 下面代码报错
with tf.variable_scope("one"):
a2 = tf.get_variable("a", [1])
使用variable_scope()函数创建变量空间时,在变量空间内创建的变量名称都会带上这个变量空间名称作为前缀。
name_scope()函数提供了类似于variable_scope()函数的变量空间管理功能,但是有所区别。
在name_scope()内部使用get_variable()函数时,生成的变量名称不会被添加变量空间名称前缀;而相反的是,Variable()函数在name_scope()内部会被添加变量空间名称前缀。