tensorflow常用函数及概念

版权声明:转载请注明出处,谢谢。 https://blog.csdn.net/NNNNNNNNNNNNY/article/details/70177509

命令式编程与声明式编程

命令式编程(imperative programming):每个语句都按原来的意思执行,可以精确控制行为。通常可以无缝的和主语言交互,方便的利用主语言的各类算法,工具包,bug和性能调试器。缺点是实现统一的辅助函数困和提供整体优化都很困难。比如numpy和Torch。
声明式语言(declarative programing):用户只需要声明要做什么,而具体执行则由系统完成。在真正开始计算的时候已经拿到了整个计算图,所以我们可以做一系列优化来提升性能。实现辅助函数也容易,例如对任何计算图都提供forward和backward函数,对计算图进行可视化,将图保存到硬盘和从硬盘读取。缺点是某些功能在主语言中实现简单,但在这里却经常麻烦,例如if-else语句 ;debug也不容易,例如监视一个复杂的计算图中的某个节点的中间结果并不简单。比如Caffe,mxnet和TensorFlow。
参考:a short introduction to mxnet design and implementation (chinese)

基本概念

TensorFlow程序一般可以分为两个阶段,

  • 构造部分,使用tensor表示数据,使用graph来表示计算任务
  • 执行部分,在被称为Session的context里执行图中的计算(使用feed和fetch可以为任意的op赋值或从中获取数据)

计算图

TensorFlow中每一个计算都是计算图上的一个节点。TensorFlow会自动生成一个默认的计算图,如果没有特殊指定,运算会自动加入这个计算图中。

张量

在TensorFlow中,张量并没有真正保存数字,它只是对TensorFlow中运算结果的引用。一个张量中主要保存了三个属性:名字(name)、维度(shape)和类型(type)。张量的命名是通过“node:src_output”的形式来给出,node为节点的名称,src_ouput表示当前张量来自节点的第几个输出(编号从0开始)。当计算图构造完成后,可以通过会话(session)来得到张量的计算结果(或者借助eval()),如tf.Session().run(result)

会话

TensorFlow中的会话(session)用来执行定义好的运算。TensorFlow不会自动生成默认的会话,需要手动指定。

placeholder机制

TensorFlow提供了placeholder机制用于提供输入数据:placeholder相当于定义了一个位置,这个位置的数据在程序运行时再使用feed_dict来指定。
为什么会出现这个?若每轮迭代选取的数据都要通过常量来表示,计算图的节点就会非常多。(那为什么不适用variable呢?我现在还没想清楚)

collection集合

tf.add_to_collection('losses', mse_loss)
loss = tf.get_collection('losses')

在一个计算图中,可以通过集合(collection)来管理不同类别的资源(可以是张量、变量或者运行Tensorflow程序所需要的队列资源等)。比如通过tf.add_to_collection函数可以将资源加入一个或多个集合中,然后通过tf.get_collection获取一个集合里面的所有资源。
TensorFlow中也自动管理了一些最常用的集合,如:tf.GraphKeys.TRAINABLE_VARIABLES是可学习变量的集合,可通过tf.trainable_variables()获得。

见《TensorFlow实战Google深度学习框架》P42。

tf.constant

a = tf.constant([1.0, 2.0], name='a')
tf.constant是一个计算,这个计算的结果为一个张量,保存在变量a中。
张量主要的三个属性:名字(name)、维度(shape)和类型(type)。
见《TensorFlow实战Google深度学习框架》P43。

tf.matmul

a=tf.matmul(x, w1)
tf.matmul实现了矩阵乘法的功能。

tf.Variable

weights = tf.Variable(tf.random_normal([2, 3], stddev=2))
w2=tf.Variable(weights.initiallized_value())

变量tf.Variable的作用就是保存和更新神经网络中的参数,也支持通过其他变量的初始值来初始化新的变量。tf.Variable是一个类。
tensorflow随机数生成函数:tf.random_normaltf.truncated_normaltf.random_uniformtf.random_gamma
tensorflow常数生成函数:tf.zerostf.onestf.filltf.constant
见《TensorFlow实战Google深度学习框架》P43。

tf.get_variable() 和 tf.variable_scope()

和tf.Variable不同的一点是,tf.get_variable 必须包含一个指定变量名称的参数,它会根据这个名字去创建或者获取变量。如果需要通过tf.get_variable获取一个已经创建的变量,需要通过tf.variable_scope函数生成一个上下文管理器。具体说来,当tf.variable_scope函数使用参数reuse=True生成上下文管理器时,这个上下文管理器内所有的tf.get_variable函数会直接获取已经创建的变量,如果变量不存在则tf.get_variable函数将报错;相反,如果tf.variable_scope函数使用参数reuse=False生成上下文管理器时,tf.get_variable操作将创建新的变量,如果同名的变量已经存在,则tf.get_variable函数将报错。说起来有点绕,可以看下书籍《TensorFlow实战Google深度学习框架》5.3节 变量管理。
想一下,为什么这么做呢?答:这种变量管理的方式就不需要将所有变量都作为参数传递到不同的函数中了,并且大大提高程序的可读性。
除此之外,tf.variable_scope函数也会创建一个命名空间,在命名空间内创建的变量名称都会带上这个命名空间名作为前缀。tf.name_scope也会创建一个命名空间,但和前者的区别在于此函数将会自动忽略tf.get_variable 创建的变量。
参见:《TensorFlow实战Google深度学习框架》5.3节 变量管理 ;What’s the difference of name scope and a variable scope in tensorflow?

tf.assign

assign(ref, value, validate_shape=None, use_locking=None, name=None)
tf.assign用来更新模型中变量的值,效果等同于 ref = value。

tf.train.ExponentialMovingAverage滑动平均

ema = tf.train.ExponentialMovingAverage(decay, num_updates)  # 定义了一个滑动平均类的对象,初始化时给定了衰减率deay和控制衰减率的变量num_updates
maintain_averages_op = ema.apply([v1])  #定义一个更新变量滑动平均的操作,每次执行这个操作时参数中的变量都会被更新
sess.run(maintain_averages_op)  # 更新v1的滑动平均值
v1_shadow = ema.average(v1) # 获取滑动平均之后变量的取值 

滑动平均不会改变变量本身的取值,而是会维护一个影子变量来记录其滑动平均值。所以当需要使用这个滑动平均值时,需要明确调用average函数。
参见《TensorFlow实战Google深度学习框架》P90

tf.contrib.layer.l2_regularizer 正则化

TensorFlow提供了tf.contrib.layer.l2_regularizer 函数,它可以返回一个函数,这个函数可以计算一个给定参数的L2正则化的值。

loss_regular = tf.contrib.layer.l2_regularizer(lambda)(weights)  # lambda为正则化项的权重,weights为需要正则化的值

参见《TensorFlow实战Google深度学习框架》P88

tf.train.exponential_decay 指数衰减学习率

learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE, global_step, mnist.train.num_examples/BATCH_SIZE, LEARNING_RATE_DECAY)  # (基础学习率,当前迭代轮数,衰减速度(通常为过完一次所有训练数据需要的迭代次数),学习率衰减系数)
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(my_loss, global_step=global_step) # 使用指数衰减的学习率。在minimize函数中传入global_step将自动更新global_step参数,从而使得学习率也得到相应更新。

衰减公式: learning_rate=learning_rate_basedecay_rate(global_step/decay_steps)

参见《TensorFlow实战Google深度学习框架》P85

placeholder机制

为什么会出现这个?若每轮迭代选取的数据都要通过常量来表示,计算图的节点就会非常多。为了避免这个问题,TensorFlow提供了placeholder机制用于提供输入数据:placeholder相当于定义了一个位置,这个位置的数据在程序运行时再使用feed_dict来指定。

x = tf.placeholder(tf.float32, shape=(3, 2), name="input")
sess.run(y, feed_dict={x:[[0.7, 0.9], [0.1, 0.4], [0.5, 0.8]]})

tf.control_dependencies控制依赖

with g.control_dependencies([a, b, c]): 
# `d` 和 `e` 将在 `a`, `b`, 和`c`执行完之后运行 
d = … 
e = … 

在训练神经网络模型时,每过一遍数据既要通过反向传播来更新神经网络中的参数,又要更新每一个参数的滑动平均值。为了一次完成多个操作,TensorFlow提供了tf.control_dependencies和tf.group两种机制。下面两行程序和train_op = tf.group(train_step, variables_averages_op)是等价的。

with tf.control_dependencies([train_step, variables_averages_op]):
    train_op = tf.no_op(name='train')

tf.nn.sparse_softmax_cross_entropy_with_logits交叉熵函数

cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(y, tf.argmax(y_, 1))

当分类问题只有一个正确答案时,可以使用这个函数来加速交叉熵的计算。这个函数的第一个参数时神经网络不包括softmax层的前向传播结果,第二个是训练数据的正确答案。因为标准答案是一个长度为10的一维数组,而该函数需要提供的是一个正确答案的数字,所以需要使用tf.argmax函数来得到正确答案对应的类别编号。

tf.train.GradientDescentOptimizer优化算法

train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)

使用其来优化损失函数,注意在这个函数中会把global_step的值加1。

tf.train.Saver()保存加载模型

保存模型:

saver = tf.train.Saver()
saver.save(sess, path_to_save, global_step=global_step)

通过变量重命名的方式加载部分模型:

variable_averages = tf.train.ExponentialMovingAverage(mnist_train.MOVING_AVERAGE_DECAY) 
variables_to_restore = variable_averages.variables_to_restore() # Returns a map of names to Variables to restore
saver = tf.train.Saver(variables_to_restore) #参数可以是一个dict(即这里的用法)也可以是一个list
saver.restore(sess, path_saved)

参考:变量:创建、初始化、保存和加载variables_to_restore(moving_avg_variables=None)

tf.gfile.FastGFile

一个文件读写的封装类。
tf.gfile.FastGFile(image_path, ‘rb’).read() # Returns the contents of a file as a string.
参考:tf.gfile.FastGFile

tf.argmax

返回沿着某个维度最大值的位置。

a = np.arange(6).reshape(2,3)
a.argmax()
#输出:5
a.argmax(0)
#输出:array([1, 1, 1])
a.argmax(1)
#输出:array([2, 2])

GPU配置

gpu_options = tf.GPUOptions(visible_device_list="0,1", allow_growth=True) # 指定使用的GPU设备号;允许运行过程中tf根据需求增长扩大显存的使用
gpu_options = tf.GPUOptions(visible_device_list="0", per_process_gpu_memory_fraction=0.4)    # 指定使用的GPU设备号;指定每个可用GPU上的显存分配比率
session_config = tf.ConfigProto(gpu_options=gpu_options, allow_soft_placement=True, log_device_placement=True)    # gpu配置;如果指定的设备不存在允许tf自动分配设备;打印设备分配日志
sess = tf.Session(config=session_config)

猜你喜欢

转载自blog.csdn.net/NNNNNNNNNNNNY/article/details/70177509