Tensorflow基本概念

  • 图(Graph):图描述了计算的过程,TensorFlow使用图来表示计算任务。
  • 张量(Tensor):TensorFlow使用tensor表示数据。每个Tensor是一个类型化的多维数组。
  • 操作(op):图中的节点被称为op(opearation的缩写),一个op获得/输入0个或多个Tensor,执行计算,产生0个或多个Tensor。
  • 会话(Session):图必须在称之为“会话”的上下文中执行。会话将图的op分发到诸如CPU或GPU之类的设备上执行。
  • 变量(Variable):运行过程中可以被改变,用于维护状态

边的概念

TensorFlow的边即有两种连接关系:数据依赖,控制依赖。

  • 实线边表示数据依赖,代表数据,即张量。任意维度的数据统称为张量。在机器学习算法中,张量在数据流图中从前往后流一遍就完成一次前向传播,而残差从后向前流动一遍就完成一次反向传播。
  • 虚线边表示控制依赖,可以用于控制操作的运行,这被用来确保happens-before关系,这类边上没有数据流过,但源节点必须在目的节点开始执行前完成。

Tensorflow数据属性

数据类型 Python类型 描述
DT_FLOAT tf.float32 32位浮点型
DT_DOUBLE tf.float64

64位浮点型

DT_INT64 tf.int64 64位有符号整型
DT_INT32 tf.int32 32位有符号整型
DT_INT16 tf.int16 16位有符号整型
DT_INT8 tf.int8 8位有符号整型
DT_UNIT8 tf.unit8 8位无符号整型
DT_STRING tf.string 可变长度的字节数组,每一个张量元素是一个字节数组
DT_BOOL tf.bool 布尔型
DT_COMPLEX64 tf.complex64 由两个32位浮点数组成的复数:实部和虚部
DT_QINT32 tf.qint32 用于量化操作的32 位有符号整型
DT_QINT8 tf.qint8 用于量化操作的8 位有符号整型
DT_QUINT8  tf.quint8 用于量化操作的8 位无符号整型

节点

节点又称为算子,它代表一个操作,一般用来表示施加的数字运算,也可以表示数据输入的起点以及输出的重点,或者是读取/写出持久化变量的终点

类别 示例
数学运算操作 Add、Subtract、Multiply、Div、Exp、Log、Greater、Less、Equal ...
数组运算操作 Concat、Slice、Split、Constant、Rank、Shape、Shuffle ...
矩阵运算操作 MatMul、MatrixInverse、MatrixDeterminant …
有状态的操作 Variable、Assign、AssignAdd …
神经网络构建操作 SoftMax、Sigmoid、ReLU、Convolution2D、MaxPool …
检查点操作 Save、Restore
队列和同步操作 Enqueue、Dequeue、MutexAcquire、MutexRelease …
控制张量流动的操作 Merge、Switch、Enter、Leave、NextIteration

使用Tensorflow必须理解下列概念:

TensorFlow可以认为是一种编程工具,使用TensorFlow来实现具体的业务需求,所以我们可以认为TensorFlow就是一个“工具箱”,然后我们使用TensorFlow这个“工具箱”中的各种“工具”(方法/API)来实现各种功能,比如使用TensorFlow实现基本的数值计算、机器学习、深度学习等;使用TensorFlow必须理解下列概念

  • 使用图(graph)来表示计算任务;
  • 在会话(session)的上下文中执行图;
  • 使用tensor表示数据;
  • 通过变量(Variable)来维护状态 ;
  • 使用feed和fetch可以为任意的操作(Operation/op)赋值或者从其中获取数据。

TensorFlow 的程序一般分为两个阶段:构建阶段 和 执行阶段:

  • 构建阶段:op的执行步骤被描述称为一个图,然后使用 TensorFlow 提供的API构建这个 图。
  • 执行阶段:将构建好的执行图(Operation Graph)在给定的 会话 中执行,并得到执行结果。

图(Graph)

TensorFlow 编程的重点是根据业务需求,使用 TensorFlow 的API将业务转换为执行图(有向无环图)。

图中的节点是Tensor,节点之间的连线是节点之间的操作,连线前的节点可以认为是操作的输入,连线后的节点可以认为操作的输出;根据节点的特性(是否有输入输出),可以将节点分为源节点、中间节点和最终的结果节点。

图构建的第一步就是创建源op(source op); 源op不需要任何的输入。op构造器的返回值代表被构造出的op的输出,这些返回值可以传递给其它op构造器作为输入或者直接获取结果。
TensorFlow 库中有一个默认图(default graph),op构造器可以直接为其添加节点,一般情况下,使用默认的Graph即可完成程序代码的实现。不过 TensorFlow 也支持通过Graph类管理多个图。

使用默认图

import tensorflow as tf# 1. 定义常量矩阵a和矩阵b
# name属性只是给定这个操作一个名称而已
# 如果给定[[1, 2], [3, 4]],形状已定,可以不指定shape参数
a = tf.constant([[1, 2], [3, 4]], dtype=tf.int32, name='a')
print(type(a))
# 如果给定[5, 6, 7, 8],后面可以通过参数shape来确定形状
b = tf.constant([5, 6, 7, 8], dtype=tf.int32, shape=[2, 2], name='b')# 2. 以a和b作为输入,进行矩阵的乘法操作
c = tf.matmul(a, b, name='matmul')
print(type(c))# 3. 以a和c作为输入,进行矩阵的相加操作
g = tf.add(a, c, name='add')
print(type(g))print("变量a是否在默认图中:{}".format(a.graph is tf.get_default_graph()))

不使用默认图

注意:操作必须属于同一个图,不同图中的节点不能相连

# 使用新的构建的图
graph = tf.Graph()
with graph.as_default():# 此时在这个代码块中,使用的就是新的定义的图graph(相当于把默认图换成了graph)d = tf.constant(5.0, name='d')print("变量d是否在新图graph中:{}".format(d.graph is graph))with tf.Graph().as_default() as g2:e = tf.constant(6.0)print("变量e是否在新图g2中:{}".format(e.graph is g2))# 这段代码是错误的用法,记住:不能使用两个图中的变量进行操作,只能对同一个图中的变量对象(张量)进行操作(op)
# f = tf.add(d, e)
# 报出:Tensor("Const:0", shape=(), dtype=float32) must be from the same graph as Tensor("d:0", shape=(), dtype=float32).

会话(Session)

当执行图构建完成后,才能启动图,进入到执行阶段;启动图的第一步就是创建一个 Session 对象,如果无任何参数的情况下,会话构造器将启动默认图。

Session 会话

# 会话构建&启动(默认情况下(不给定Session的graph参数的情况下),创建的Session属于默认的图)
sess = tf.Session()
result = sess.run(fetches=[c])
# result = sess.run(fetches=[c, g])
print("type:{}, value:\n{}".format(type(result), result))# 会话关闭
sess.close()# 当一个会话关闭后,不能再使用了,所以下面两行代码错误
# result2 = sess.run(c)
# print(result2)
  • 调用 sess 的 run 方法来执行矩阵的乘法,得到c的结果值(所以将c作为参数传递进去)
  • 不需要考虑图中间的运算,在运行的时候只需要关注最终结果对应的对象以及所需要的输入数据值
  • 只需要传递进去所需要得到的结果对象,会自动的根据图中的依赖关系触发所有相关的OP操作的执行
  • 如果op之间没有依赖关系,tensorflow 底层会并行的执行op(有资源) --> 自动进行
  • 如果传递的 fetches 是一个列表,那么返回值是一个 list 集合
  • fetches:表示获取那个op操作的结果值

c的结果:

g的结果:

补充:(可以使用with语句块来开启会话,自动关闭会话)

# 使用with语句块,会在with语句块执行完成后,自动的关闭session
# allow_soft_placement:是否允许动态使用CPU和GPU,默认为False;
# 当我们的安装方式为GPU的时候,建议该参数设置为True,因为TensorFlow中的部分op只能在CPU上运行。
# log_device_placement: 是否打印日志,默认为False,不打印日志
with tf.Session(config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)) as sess2:print(sess2)# 获取张量c的结果: 通过Session的run方法获取print("sess2 run:{}".format(sess2.run(c)))# 获取张量g的结果:通过张量对象的eval方法获取,和Session的run方法一致print("c eval:{}".format(g.eval()))

tf.Session 在构建会话的时候,如果不给定任何参数,那么构建出来的 Session 对应内部的 Graph,其实就是默认 Graph,不过我们可以通过参数给定具体对应的是那一个 Graph 以及当前 Session 对应的配合参数。

Session 的构造主要有三个参数,作用如下:

  • target:给定连接的url,只有当分布式运行的时候需要给定;
  • graph:给定当前Session对应的图,默认为TensorFlow中的默认图;
  • config:给定当前Session的相关参数,详见https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/prot
    obuf/config.proto中的[ConfigProto]

通过Session的config参数可以对TensorFlow的应用的执行进行一些优化调整,主要涉及到的参数如下:

属性 作用
gpu_options GPU相关参数,主要参数:per_process_gpu_memory_fraction和allow_growth
allow_soft_placement 是否允许动态使用CPU和GPU,默认为False;当我们的安装方式为GPU的时候,
建议该参数设置为True,因为TensorFlow中的部分op只能在CPU上运行
log_device_placement 是否打印日志,默认为False,不打印日志
graph_options Graph优化相关参数,一般不需要给定,默认即可,主要参数:
optimizer_options(do_common_subexpression_elimination、do_constant_folding和opt_level)
import tensorflow as tf# 构建一个图
a = tf.constant('10', tf.string, name='a_const')
b = tf.string_to_number(a, out_type=tf.float64, name='str_2_double')
c = tf.to_double(5.0, name='to_double')
d = tf.add(b, c, name='add')# 构建Session并执行图
# 1、构建GPU相关参数
gpu_options = tf.GPUOptions()
# per_process_gpu_memory_fraction:给定对于每一个进程,分配多少的GPU内存,默认为1
# 设置为0.5表示分配50%的GPU内存
gpu_options.per_process_gpu_memory_fraction = 0.5
# allow_growth:设置为True表示在GPU内存分配的时候,采用动态分配方式,默认为False
# 动态分配的意思是指,在启动之前,不分配全部的内存,根据需要后面动态的进行分配
# 在开启动态分配后,GPU内存部分自动释放,所以复杂、长时间运行的任务不建议开启
gpu_options.allow_growth = True# 2、构建Graph优化的相关参数
optimizer = tf.OptimizerOptions(do_common_subexpression_elimination=True,  # 设置为True表示开启公共执行子句优化do_constant_folding=True,  # 设置为True表示开始常数折叠优化opt_level=0  # 设置为0,表示开启上述两个优化,默认为0
)graph_options = tf.GraphOptions(optimizer_options=optimizer)# 3、构建Session的Config相关参数
config_proto = tf.ConfigProto(allow_soft_placement=True, log_device_placement=True,graph_options=graph_options, gpu_options=gpu_options)# 4、构建Session并运行
with tf.Session(config=config_proto) as sess:print(sess.run(d))

InteractiveSession会话(交互式会话)

使用交互式会话可以降低代码的复杂度,使用 Tensor.eval() 或者 Operation.run() 来代替 Session.run() 方法,这样可以避免一个变量来维持会话;

备注:Session也可以使用Tensor.eval()和Operation.run()获取数据/执行操作(只要明确当前会话)。

import tensorflow as tf# 构建一个图
a = tf.constant(4)
b = tf.constant(3)
c = tf.multiply(a, b)# 运行
with tf.Session():print(c.eval())# 进入交互式会话
sess = tf.InteractiveSession()# 定义变量和常量
x = tf.constant([1.0, 2.0])
a = tf.constant([2.0, 4.0])# 进行减操作
sub = tf.subtract(x, a)# 输出结果
print(sub.eval())
print(sess.run(sub))

张量(Tensor)

TensorFlow 使用 Tensor 数据结构来代表所有数据,计算图中,操作间传递的数据都是 Tensor。Tensor 可以看作是一个 N 维的数组或者列表,一个 Tensor 主要由一个静态数据类型和动态类型的维数(Rank、Shape)组成。Tensor 可以在图中的节点之间流通。

变量(Variables)

变量(Variables)是维护图执行过程中的状态信息。在训练模型过程中,可以通过变量来存储和更新参数。变量包含张量(Tensor)存放于内存的缓存区。建模的时候变量必须被明确的初始化,模型训练后变量必须被存储到磁盘。这些变量的值可以在之后的模型训练和分析中被加载。

在构建变量的时候,必须将一个 张量 或者 可以转化为张量的 Python对象 作为初始值传入构造函数Variable中。

import tensorflow as tf# 创建一个变量,初始化值为变量3.0
a = tf.Variable(3.0)# 创建一个常量
b = tf.constant(2.0)
c = tf.add(a, b)# 启动图后,变量必须先进行初始化操作
# 增加一个初始化变量的op到图中
init_op = tf.initialize_all_variables()# 启动图
with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:# 运行init_opsess.run(init_op)# 获取值print("a = {}".format(sess.run(a)))print("c = {}".format(c.eval))

变量依赖案例:

import tensorflow as tf# 创建一个变量
w1 = tf.Variable(tf.random_normal([10], stddev=0.5, dtype=tf.float32), name='w1')
# 基于第一个变量创建第二个变量
a = tf.constant(2, dtype=tf.float32)
w2 = tf.Variable(w1.initialized_value() * a, name='w2')# 进行全局初始化
init_op = tf.initialize_all_variables()# 启动图
with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:# 运行init_opsess.run(init_op)# 获取值result = sess.run([w1, w2])print("w1 = {}\nw2 = {}".format(result[0], result[1]))

取回(fetch)

为了取回操作的输出内容,可以在使用 Session 对象的 run 方法调用执行图的时候,传入一些tensor,通过 run 方法就可以获取这些 tensor 对应的结果值。

如果需要获取多个tensor的值,那么尽量一次运行就获取所有的结果值,而不是采用逐个获取的方式。

with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:# 运行init_opsess.run(init_op)# 获取值result = sess.run(fetches=[w1, w2])print("w1 = {}\nw2 = {}".format(result[0], result[1]))

填充(feed)

在构建图时使用 placeholder 类型的 API 临时替代任意操作的张量(占位符),在调用 Session 对象的run() 方法去执行图时,使用填充数据作为调用的参数,调用结束后,填充数据就消失了。

  feed 使用一个 tensor 值临时替换一个操作的输出结果,在获取数据的时候必须给定对应的 feed 数据作为参数。feed 只有在调用它的方法内有效,方法结束,feed 就消失了。

  feed 可以使用 placeholder 类型的API创建占位符,常见API:tf.placeholder、tf.placeholder_with_default

import tensorflow as tf# 创建占位符,创建图
m1 = tf.placeholder(tf.float32)
m2 = tf.placeholder(tf.float32)
m3 = tf.placeholder_with_default(4.0, shape=None)
output = tf.multiply(m1, m2)
ot1 = tf.add(m1, m3)# 运行图
with tf.Session() as sess:print(sess.run(output, feed_dict={m1: 3, m2: 4}))print(output.eval(feed_dict={m1: 8, m2: 10}))print(sess.run(ot1, feed_dict={m1: 3, m3: 3}))print(sess.run(ot1, feed_dict={m1: 3}))

变量更新(assign)

实例1:累加器

import tensorflow as tf# 1. 定义一个变量
x = tf.Variable(0, dtype=tf.int32, name='v_x')# 2. 变量的更新
assign_op = tf.assign(ref=x, value=x + 1)# 3. 变量初始化操作
x_init_op = tf.global_variables_initializer()# 3. 运行
with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:# 变量初始化sess.run(x_init_op)# 模拟迭代更新累加器for i in range(5):# 执行更新操作sess.run(assign_op)r_x = sess.run(x)print(r_x)

实例二:动态的更新变量的维度数目

import tensorflow as tf# 1. 定义一个不定形状的变量
x = tf.Variable(initial_value=[],dtype=tf.float32,trainable=False,validate_shape=False # 设置为True,表示在变量更新的时候,进行shape的检查,默认为True
)# 2. 变量更改
concat = tf.concat([x, [0.0, 0.0]], axis=0)
assign_op = tf.assign(x, concat, validate_shape=False)  # validate_shape 允许改变形状# 3. 变量初始化操作
x_init_op = tf.global_variables_initializer()# 3. 运行
with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:# 变量初始化sess.run(x_init_op)# 模拟迭代更新累加器for i in range(5):sess.run(assign_op)r_x = sess.run(x)print(r_x)

控制依赖

实例三:求阶乘(控制依赖)

我们可以通过 Variable 和 assign 完成变量的定义和更新,但是如果在更新变量之前需要更新其它变量,那么会导致一个比较严重的问题:也就是需要多次调用 sess.run 方法来进行变量的更新。通过这种方式,代码复杂程度上升,同时也没有执行效率。

解决该问题的方案就是:控制依赖。

通过 TensorFlow 中提供的一组函数来处理不完全依赖的情况下的操作排序问题(即给定哪个操作先执行的问题), 通过 tf.control_dependencies API完成。

import tensorflow as tf# 1. 定义一个变量
sum = tf.Variable(1, dtype=tf.int32)
# 2. 定义一个占位符
i = tf.placeholder(dtype=tf.int32)# 3. 更新操作
tmp_sum = sum * i
# tmp_sum = tf.multiply(sum, i)
assign_op = tf.assign(sum, tmp_sum)
with tf.control_dependencies([assign_op]):# 如果需要执行这个代码块中的内容,必须先执行control_dependencies中给定的操作/tensorsum = tf.Print(sum, data=[sum, sum.read_value()], message='sum:')# 4. 变量初始化操作
x_init_op = tf.global_variables_initializer()# 5. 运行
with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:# 变量初始化sess.run(x_init_op)# 模拟迭代更新累加器for j in range(1, 6):# 执行更新操作# sess.run(assign_op, feed_dict={i: j})# 通过control_dependencies可以指定依赖关系,这样的话,就不用管内部的更新操作了r = sess.run(sum, feed_dict={i: j})print("5!={}".format(r))

设备(device)

设备 是指一块可以用来运算并且拥有自己的地址空间的硬件,如 CPU 和 GPU 。Tensorflow 为了在执行操作的时候,充分利用计算资源,可以明确指定操作在哪个设备上执行。

一般情况下,不需要显示指定使用 CPU 还是 GPU ,TensorFlow 会自动检测。如果检测到 GPU,TensorFlow会尽可能地利用第一个GPU来执行操作。

注意:如果机器上有超过一个可用的 GPU,那么除了第一个外其它GPU默认是不参与计算的。所以,在实际TensorFlow编程中,经常需要明确给定使用的 CPU 和 GPU。

  • “/cpu:0”:表示使用机器CPU运算,cpu默认只有0个
  • “/gpu:0”:表示使用第一个GPU运算,如果有的话
  • “/gpu:1”:表示使用第二个GPU运算,以此类推
import tensorflow as tf# with tf.device("/cpu:0"):
with tf.device("/gpu:0"):a = tf.constant([1, 2, 3], name='a')b = tf.constant(2, name='b')c = tf.multiply(a, b)# 新建Seesion,并将log_device_placement设置为True
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))# 运行这个op
print(sess.run(c))

变量作用域(scope)

通过 tf.Variable 我们可以创建变量,但是当模型复杂的时候,需要构建大量的变量集,这样会导致我们对于变量管理的复杂性,而且没法共享变量(存在多个相似的变量)。针对这个问题,可以通过 TensorFlow 提供的变量作用域机制来解决,在构建一个图的时候,就可以非常容易的使用共享命名过的变量。

Tensorflow中有两个作用域:一个是 name_scope,另一个是 variable_scope

variable_scope

变量作用域机制在 TensorFlow 中主要通过两部分组成:

  • tf.get_variable:通过所给定的名字创建或者返回一个对应的变量
  • tf.variable_scope:为通过创建的变量或者操作Operation指定命名空间

get_variable方法:

  • tf.get_variable 方法在调用的时候,主要需要给定参数名称name,形状shape,数据类型dtype以及初始化方式initializer四个参数。
  • 该API底层执行的时候,根据variable score的属性reuse的值决定采用何种方式来获取变量。
  • 当reuse值为False的时候(不允许设置),作用域就是创建新变量设置的,此时要求对应的变量不存在,否则报错;
  • 当reuse值为True的时候,作用域就是为重用变量所设置的,此时要求对应的变量必须存在,否则报错。
  • 当reuse的值为tf.AUTO_REUSE的时候,表示如果变量存在就重用变量,如果变量不存在,就创建新变量返回。
  • (备注:reuse一般设置在variable score对象上)
import tensorflow as tf# 方式一:不加作用域的
def my_func1(x):w1 = tf.Variable(tf.random_normal([1]))[0]b1 = tf.Variable(tf.random_normal([1]))[0]result1 = w1 * x + b1w2 = tf.Variable(tf.random_normal([1]))[0]b2 = tf.Variable(tf.random_normal([1]))[0]result2 = w2 * x + b2return result1, w1, b1, result2, w2, b2# 下面两行代码还是属于图的构建
x = tf.constant(3, dtype=tf.float32)
r = my_func1(x)with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:# 初始化tf.global_variables_initializer().run()# 执行结果print(sess.run(r))# 方式二:加作用域
def my_func2(x):# initializer:初始化器w = tf.get_variable('weight', [1], initializer=tf.random_normal_initializer())[0]b = tf.get_variable('bias', [1], initializer=tf.random_normal_initializer())[0]result = w * x + breturn result, w, bdef func(x):with tf.variable_scope('op1', reuse=tf.AUTO_REUSE):r1 = my_func2(x)with tf.variable_scope('op2', reuse=tf.AUTO_REUSE):r2 = my_func2(x)return r1, r2# 下面两行代码还是属于图的构建
x1 = tf.constant(3, dtype=tf.float32, name='x1')
x2 = tf.constant(4, dtype=tf.float32, name='x2')
with tf.variable_scope('func1'):  # 支持嵌套r1 = func(x1)
with tf.variable_scope('func2'):r2 = func(x2)with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:# 初始化tf.global_variables_initializer().run()# 执行结果print(sess.run([r1, r2]))

TF底层使用 '变量作用域/变量名称:0'的方式标志变量(eg: func/op1/weight:0)

tf.get_variable 常用的 initializer 初始化器:

初始化器 描述
tf.constant_initializer(value) 初始化为给定的常数值value
tf.random_uniform_initializer(a, b) 初始化为从a到b的均匀分布的随机值
tf.random_normal_initializer(mean, stddev)  初始化为均值为mean、方差为stddev的服从高斯分布的随机值
tf.orthogonal_initializer(gini=1.0)  初始化一个正交矩阵,gini参数作用是最终返回的矩阵是随机矩阵乘以gini的结果
tf.identity_initializer(gini=1.0)  初始化一个单位矩阵,gini参数作用是最终返回的矩阵是随机矩阵乘以gini的结果

tf.variable_score

tf.variable_score方法的作用就是定义一个作用域,定义在 variable_score 作用域中的变量和操作,会将variable score 的名称作为前缀添加到变量/操作名称前,支持嵌套的作用域,添加前缀规则和文件目录路径的规则类似。

  tf.variable_score参数如果给定的是一个已经存在的作用域对象的时候,那么构建变量的时候表示直接跳过当前作用域前缀,直接成为一个完全不同与现在的作用域(直接创建给定作用域下的变量)。但是构建操作的时候,还是和嵌套的方式一样,直接添加子作用域。

  tf.variable_score参数中,可以给定当前作用域中默认的初始化器initializer,并且子作用域会直接继承父作用域的相关参数(是否重用、默认初始化器等)

import tensorflow as tfwith tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:with tf.variable_scope('foo', initializer=tf.constant_initializer(4.0)) as foo:v = tf.get_variable("v", [1])w = tf.get_variable("w", [1], initializer=tf.constant_initializer(3.0))with tf.variable_scope('bar'):l = tf.get_variable("l", [1])with tf.variable_scope(foo):h = tf.get_variable('h', [1])g = v + w + l + hwith tf.variable_scope('abc'):a = tf.get_variable('a', [1], initializer=tf.constant_initializer(5.0))b = a + gsess.run(tf.global_variables_initializer())print("{},{}".format(v.name, v.eval()))print("{},{}".format(w.name, w.eval()))print("{},{}".format(l.name, l.eval()))print("{},{}".format(h.name, h.eval()))print("{},{}".format(g.name, g.eval()))print("{},{}".format(a.name, a.eval()))print("{},{}".format(b.name, b.eval()))

name_scope

name_score 的主要作用是为 op_name 前加前缀,variable_score 是为 get_variable 创建的变量的名字加前缀。

name_score 的主要作用就是:Tensorflow 中常常会有数以千计的节点,在可视化的过程中很难一下子展示出来,因此用 name_scope 为变量划分范围,在可视化中,这表示在计算图中的一个层级。name_scope 会影响op_name,不会影响用get_variable()创建的变量,而会影响通过Variable()创建的变量。

简单来讲:使用 tf.Variable 创建的变量受 name_score 和 variable_score 的影响,会给变量添加前缀,但是使用 tf.get_variable 创建变量只受 variable_score 的影响。

import tensorflow as tfwith tf.Session() as sess:with tf.name_scope('name1'):with tf.variable_scope('variable1'):v = tf.Variable(1.0, name='v')w = tf.get_variable(name='w', shape=[1], initializer=tf.constant_initializer(2.0))h = v + wwith tf.variable_scope('variable2'):with tf.name_scope('name2'):v2 = tf.Variable(2.0, name='v2')w2 = tf.get_variable(name='w2', shape=[1], initializer=tf.constant_initializer(2.0))h2 = v2 + w2sess.run(tf.global_variables_initializer())print("{},{}".format(v.name, v.eval()))print("{},{}".format(w.name, w.eval()))print("{},{}".format(h.name, h.eval()))print("{},{}".format(v2.name, v2.eval()))print("{},{}".format(w2.name, w2.eval()))print("{},{}".format(h2.name, h2.eval()))

可视化(Tensorboard)

TensorFlow提供了一套可视化工具:TensorBoard,在通过pip安装 TensorFlow 的情况下,默认也会安装TensorBoard。通过TensorBoard可以展示TensorFlow的图像、绘制图像生成的定量指标以及附加数据等信息。

TensorBoard 通过读取 TensorFlow 的事件文件来运行,TensorFlow 的事件文件包括了在 TensorFlow运行中涉及到的主要数据,比如:scalar、image、audio、histogram和graph等。

通过 tf.summary 相关API,将数据添加 summary 中,然后在 Session 中执行这些操作得到一个序列化Summary protobuf 对象,然后使用 FileWriter 对象将汇总的序列数据写入到磁盘,然后使用 tensorboard 命令进行图标展示,默认访问端口是:6006

TensorBoard中支持结构视图和设备视图。

import tensorflow as tfwith tf.variable_scope("foo"):with tf.device("/cpu:0"):x_init1 = tf.get_variable('init_x', [10], tf.float32, initializer=tf.random_normal_initializer())[0]x = tf.Variable(initial_value=x_init1, name='x')y = tf.placeholder(dtype=tf.float32, name='y')z = x + ywith tf.variable_scope("bar"):a = tf.constant(3.0) + 4.0# update xassign_op = tf.assign(x, x + 1)with tf.control_dependencies([assign_op]):with tf.device('/gpu:0'):out = x * ywith tf.device('/cpu:0'):with tf.variable_scope("bar"):a = tf.constant(3.0) + 4.0w = z * a# 开始记录信息(需要展示的信息的输出)
tf.summary.scalar('scalar_init_x', x_init1)
tf.summary.scalar(name='scalar_x', tensor=x)
tf.summary.scalar('scalar_y', y)
tf.summary.scalar('scalar_z', z)
tf.summary.scalar('scala_w', w)
tf.summary.scalar('scala_out', out)with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:# merge all summarymerged_summary = tf.summary.merge_all()# 得到输出到文件的对象writer = tf.summary.FileWriter('./result', sess.graph)# 初始化sess.run(tf.global_variables_initializer())for i in range(1, 5):summary, r_out, r_x, r_w = sess.run([merged_summary, out, x, w], feed_dict={y: i})writer.add_summary(summary, i)print("{},{},{}".format(r_out, r_x, r_w))# 关闭操作writer.close()

API

API 描述
tf.summary.scalar 添加一个标量
tf.summary.audio 添加一个音频变量
tf.summary.image 添加一个图片变量
tf.summary.histogram 添加一个直方图变量
tf.summary.text 添加一个字符串类型的变量(一般很少用)

查看可视化结果步骤:

  • 打开cmd命令行输入:tensorboard --helpfull 可以查看相关帮助命名
  • 输入:tensorboard --logdir F:\All_worlspace\Pycharm_workspace\DeepLearning\Tensorflow-basic\result 这里的路径是你保存输出文件对象的路径

  • 在浏览器中输入上图红色框内的

  • 双击图中的foo或bar会打开,如下图

模型保存、提取(Saver)

TensorFlow 使用 tf.train.Saver 类实现模型的保存和提取。

Saver对象的saver方法将TensorFlow模型保存到指定路径中。

通过Saver对象的restore方法可以加载模型,并通过保存好的模型变量相关值重新加载完全加载进来。

如果不希望重复定义计算图上的运算,可以直接加载已经持久化的图,通过 tf.train.import_meta_graph 方法直接加载

备注:在加载的时候,可以在Saver对象构建的时候,明确给定变量名之间的映射关系

import tensorflow as tf# # 模型保存
# v1 = tf.Variable(tf.constant(3.0), name='v1')
# v2 = tf.Variable(tf.constant(4.0), name='v2')
# result = v1 + v2
#
# saver = tf.train.Saver()
# with tf.Session() as sess:
#     sess.run(tf.global_variables_initializer())
#     sess.run(result)
#     # 模型保存到model文件夹下,文件前缀为:model.ckpt
#     saver.save(sess, './model/model.ckpt')# 模型的提取(完整提取:需要完整恢复保存之前的数据格式)
v1 = tf.Variable(tf.constant(1.0), name='v1')
v2 = tf.Variable(tf.constant(4.0), name='v2')
result = v1 + v2saver = tf.train.Saver()
with tf.Session() as sess:# 会从对应的文件夹中加载变量、图等相关信息saver.restore(sess, './model/model.ckpt')print(sess.run([result]))# 直接加载图,不需要定义变量了
saver = tf.train.import_meta_graph('./model/model.ckpt.meta')with tf.Session() as sess:saver.restore(sess, './model/model.ckpt')print(sess.run(tf.get_default_graph().get_tensor_by_name("add:0")))# 模型的提取(给定映射关系)
a = tf.Variable(tf.constant(1.0), name='a')
b = tf.Variable(tf.constant(2.0), name='b')
result = a + bsaver = tf.train.Saver({"v1": a, "v2": b})
with tf.Session() as sess:# 会从对应的文件夹中加载变量、图等相关信息saver.restore(sess, './model/model.ckpt')print(sess.run([result]))

总结

至此,关于Tensorflow的基础入门大概就这么多,此外还会涉及到线程和队列、数据读取、分布式训练等,可以在以后深入学习,理解。

TensorFlow 基本操作相关推荐

  1. Tensorflow从入门到精通之——Tensorflow基本操作

    前边的章节介绍了什么是Tensorflow,本节将带大家真正走进Tensorflow的世界,学习Tensorflow一些基本的操作及使用方法.同时也欢迎大家关注我们的网站和系列教程:http://ww ...

  2. 【小白学习tensorflow教程】一、tensorflow基本操作、快速构建线性回归和分类模型

    @Author:Runsen TF 目前发布2.5 版本,之前阅读1.X官方文档,最近查看2.X的文档.tensorflow是非常强的工具,生态庞大. tensorflow提供了Keras的分支,这里 ...

  3. Tensorflow从入门到精通之:Tensorflow基本操作

    Tensorflow是一种计算图模型,即用图的形式来表示运算过程的一种模型.Tensorflow程序一般分为图的构建和图的执行两个阶段.图的构建阶段也称为图的定义阶段,该过程会在图模型中定义所需的运算 ...

  4. 机器学习Tensorflow基本操作:线程队列图像

    一.线程和队列 在使用TensorFlow进行异步计算时,队列是一种强大的机制. 为了感受一下队列,让我们来看一个简单的例子.我们先创建一个"先入先出"的队列(FIFOQueue) ...

  5. 少走弯路:强烈推荐的TensorFlow快速入门资料(可下载)

    (图片付费下载自视觉中国) 作者 | 黄海广 来源 | 机器学习初学者(ID: ai-start-com) 知识更新非常快,需要一直学习才能跟上时代进步,举个例子:吴恩达老师在深度学习课上讲的Tens ...

  6. 上手必备!不可错过的TensorFlow、PyTorch和Keras样例资源

    作者 | 黄海广来源 | 机器学习初学者(ID: ai-start-com)TensorFlow.Keras和PyTorch是目前深度学习的主要框架,也是入门深度学习必须掌握的三大框架,但是官方文档相 ...

  7. 附录5:TensorFlow基础(一)

    目录 TensorFlow简介 什么是tensorflow tensorflow的核心 Numpy与TensorFlow Tensorflow基本操作 初步认识tensorflow与tensorboa ...

  8. 2_初学者快速掌握主流深度学习框架Tensorflow、Keras、Pytorch学习代码(20181211)

    初学者快速掌握主流深度学习框架Tensorflow.Keras.Pytorch学习代码 一.TensorFlow 1.资源地址: 2.资源介绍: 3.配置环境: 4.资源目录: 二.Keras 1.资 ...

  9. 带你少走弯路:强烈推荐的TensorFlow快速入门资料和翻译(可下载)

    知识更新非常快,需要一直学习才能跟上时代进步,举个例子:吴恩达老师在深度学习课上讲的TensorFlow使用,这个肯定是他近几年才学的,因为谷歌开源了TensorFlow也就很短的时间. 吴恩达老师以 ...

最新文章

  1. 前端img里面的src能是bmp么_实习|字节跳动前端实习生(非科班已定offer)三技术面+一HR面...
  2. 数组中子数组的最大累乘积
  3. [EF4] CompiledQuery预编译性能提升 + 数据载入之大彻大悟
  4. iOS学习之CoreLocation相关知识
  5. debian 9 安装后的配置,debian 9 开发环境。
  6. Spring Data JPA初使用 *****重要********
  7. WebApi client 的面向切面编程
  8. SX1301吞吐量是SX1276/8的多少倍?
  9. 彩灯(洛谷-P3857)
  10. 用虚拟 router 连通 subnet - 每天5分钟玩转 OpenStack(141)
  11. c-free5.0运行程序错误_web前端之异常/错误监控
  12. MVC 中 Html.RenderPartial()与Html.Partial()区别
  13. CentOS8.3部署GlusterFS
  14. 人机平台:商业未来行动路线图
  15. 全国快递物流查询-快递查询接口-阿里云代码封装
  16. 网易邮箱服务器邮箱协议,网易邮箱全面支持Exchange协议
  17. 2020第六届上海市大学生网络安全大赛线上赛Misc-可乐加冰
  18. undefined reference to `__strncpy_chk‘ 解决方法
  19. Spring-初识Spring框架-IOC控制反转(DI依赖注入)
  20. bzoj 4763: 雪辉

热门文章

  1. Android 为控件设置阴影
  2. 18个不可不知的有用潜规则
  3. mp4(H264容器)的详细文件格式分析
  4. H.264的NALU,RTP封包说明(转自牛人)
  5. NGINX 配置超时时间
  6. 【快写】基本思路及模板
  7. vue根据数组对象中某个唯一标识去重
  8. memmove 对同一个指针不操作
  9. background 与backgroundcolor区别
  10. 基于sqlite数据库的C语言编程