Tensorflow 一些常用函数
学习一个GAN网络代码,在train函数中,出现了如下调用tf的函数:
def train(self):
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)#以便在每一次训练完后及时更新BN的参数
1、 tf.train.AdamOptimizer
tf.train.AdamOptimizer()函数是Adam优化算法:是一个寻找全局最优点的优化算法,引入了二次方梯度校正。
tf.train.AdamOptimizer.__init__(
learning_rate=0.001, # 学习率,张亮或浮点值
beta1=0.9, # 一个浮点值或一个常量浮点张量。一阶矩估计的指数衰减率
beta2=0.999, # 一个浮点值或一个常量浮点张量。二阶矩估计的指数衰减率
epsilon=1e-08, # 数值稳定性的一个小常数
use_locking=False, # 如果True,要使用lock进行更新操作
name='Adam'# 应用梯度时为了创建操作的可选名称。默认为“Adam”
)
本质上是带有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。
特点:
结合了Adagrad善于处理稀疏梯度和RMSprop善于处理非平稳目标的优点。
对内存需求较小
为不同的参数计算不同的自适应学习率
也适用于大多非凸优化
适用于大数据集和高维空间
注:
还有其他tf的优化函数:其他tf的优化器
2、 tf.control_dependencies
tf.control_dependencies( ):代表当括号里面的参数执行完毕再执行with里面的语句,一般都会与with共用
with tf.control_dependencies(a):
之后再执行的语句
如果是多个参数就是
with tf.control_dependencies([a,b]):当a与b都执行完毕才执行里面的语句
之后再执行的语句
- 例子:
import tensorflow as tf
a_2 = tf.Variable(1)#a_2值为1
b_2 = tf.Variable(2)
op = tf.assign(a_2, 10)#把a_2的值赋值为10
add_with_dependencies = tf.add(a_2, b_2)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())#初始化
ans_2 = sess.run([add_with_dependencies])
print("Add: ", ans_2)
输出:Add:[3]
上面例子看出,直接1+2=3,没有涉及赋值op,当然有人说直接在with tf.Session() as sess:里面添加一个操作sess.run(tf.assign(a,10)),或者
add_with_dependencies = tf.add(op, b_2)呢?
的确运行以后的结果是一样的,这个只是一个操作,如果很多的呢?而且当项目很多的时候,方便管理代码
with tf.control_dependencies([op]):就代表要输出add_with_dependencies,就必须完成op的操作
import tensorflow as tf
a_2 = tf.Variable(1)
b_2 = tf.Variable(2)
op = tf.assign(a_2, 10)
# 添加该行
with tf.control_dependencies([op]):
add_with_dependencies = tf.add(a_2, b_2)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
ans_2 = sess.run([add_with_dependencies])
print("Add: ", ans_2)
输出:Add:[12]
还有 control_dependencies 不 work 的情况:
需要注意的是,除了 对于Variable 的 identity op 会在 control dependence 后重新计算,其它 op 都不会重新计算,
下面有这种情况,control_dependencies不work,其实并不是它真的不work,而是我们的使用方法有问题。
import tensorflow as tf
w = tf.Variable(1.0)
ema = tf.train.ExponentialMovingAverage(0.9)
update = tf.assign_add(w, 1.0)
ema_op = ema.apply([update])
with tf.control_dependencies([ema_op]):
ema_val = ema.average(update)
with tf.Session() as sess:
tf.global_variables_initializer().run()
for i in range(3):
print(sess.run([ema_val]))
因为ema.average(update) 不是一个 op,它只是从ema对象的一个字典中取出键对应的 tensor 而已,然后赋值给ema_val。这个 tensor是由一个在 tf.control_dependencies([ema_op]) 外部的一个 op 计算得来的,所以 control_dependencies会失效。解决方法也很简单,看代码:
import tensorflow as tf
w = tf.Variable(1.0)
ema = tf.train.ExponentialMovingAverage(0.9)
update = tf.assign_add(w, 1.0)
ema_op = ema.apply([update])
with tf.control_dependencies([ema_op]):
ema_val = tf.identity(ema.average(update)) #一个identity搞定
with tf.Session() as sess:
tf.global_variables_initializer().run()
for i in range(3):
print(sess.run([ema_val]))
3、 tf.check_numerics
check_numerics 操作本身被添加到每个 half,float 或 double 张量所在的图中.对于图中的所有 ops,check_numerics 其所有(half,float 或 double)都保证在其任何输出 check_numerics 操作之前运行.
运行时,如果 tensor 具有任何不是数字 (NaN) 或无穷大 (Inf) 的值 check_numerics ( tensor, message, name = None ) ,则报告 InvalidArgument 错误。否则,返回输入张量。
4、 tf.identity
tf.identity()函数用于返回一个和input一样的新的tensor。与上面讲的with tf.control_dependencies搭配使用
tf.identity(input, name=None)
#返回一个tensor,contents和shape都和input的一样
5、 optimizer.compute_gradients
compute_gradients()的源码如下:
compute_gradients(self, loss, var_list=None,
gate_gradients=GATE_OP,
aggregation_method=None,
colocate_gradients_with_ops=False,
grad_loss=None)
# 返回梯度和可导的变量
loss: Tensor
,需要优化的损失;
var_list: 需要更新的变量(tf.Varialble)组成的列表或者元组,默认值为GraphKeys.TRAINABLE_VARIABLES
,即tf.trainable_variables()
optimizer.compute_gradients是tf.gradients的封装,作用相同,但是tf.gradients只返回梯度,compute_gradients返回梯度和可导的变量;tf.compute_gradients是optimizer.minimize()的第一步,optimizer.compute_gradients返回一个[(gradient, variable),…]的元组列表,其中gradient是tensor。
直观上,optimizer.compute_gradients只比tf.gradients多了一个variable输出。
optimizer = tf.train.GradientDescentOptimizer(learning_rate = 1.0)
self.train_op = optimizer.minimize(self.cost)
sess.run([train_op], feed_dict={x:data, y:labels})
在这个过程中,调用minimize方法的时候,底层进行的工作包括:
(1) 使用tf.optimizer.compute_gradients计算trainable_variables 集合中所有参数的梯度
(2) 用optimizer.apply_gradients来更新计算得到的梯度对应的变量
上面代码等价于下面代码:
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
grads_and_vars = optimizer.compute_gradients(loss)
train_op = optimizer.apply_gradients(grads_and_vars)
sess.run([train_op], feed_dict={x:data, y:labels})
补充:tf.gradients
tf.gradients(
ys,
xs,
grad_ys=None,
name='gradients',
colocate_gradients_with_ops=False,
gate_gradients=False,
aggregation_method=None,
stop_gradients=None,
unconnected_gradients=tf.UnconnectedGradients.NONE
)
计算ys关于xs的梯度,tf.gradients返回的结果是一个长度为len(xs)的tensor列表list,例如
tf.gradients(y, [x1, x2, x3]返回[dy/dx1, dy/dx2, dy/dx3]
当y与x无关时,即graph无x到y的路径, 则求y关于x的梯度时返回[None];参数stop_gradients指定的变量对当前梯度求解而言, 梯度求解将止于这些变量。
a = tf.constant(0.)
b = 2 * a
g = tf.gradients(a + b, [a, b], stop_gradients=[a, b]) #梯度计算不再追溯a,b之前的变量
输出:
In: sess.run(g)
out:[1.0, 1.0]
#如果不设置stop_gradients参数则反向传播梯度计算将追溯到最开始的值a,输出结果为:
In : sess.run(g)
Out: [3.0, 1.0]
补充:tf.stop_gradient
tf.stop_gradient(input,name=None)
tf.stop_gradient阻止input的变量参与梯度计算,即在梯度计算的过程中屏蔽input之前的graph。
返回:关于input的梯度
应用:
- EM算法,其中M步骤不应涉及通过E步骤的输出的反向传播。
- Boltzman机器的对比散度训练,在区分能量函数时,训练不得反向传播通过模型生成样本的图形。
- 对抗性训练,通过对抗性示例生成过程不会发生反向训练。
6、 tf.global_norm
计算多个张量的全局范数。
global_norm(
t_list, # 混合张量、IndexedSlices 或 None 的元组或列表
name=None # 操作的名称(可选)
)
返回值:
该函数返回一个浮点型的 0维(标量)张量.
给定一个元组或张量列表:t_list,此操作返回 t_list 中所有张量的元素的全局范数.全局范数计算如下:
global_norm = sqrt(sum([l2norm(t)**2 for t in t_list]))
t_list 中任何类型为 None 的项都将被忽略.
可能引发的异常:
TypeError:如果 t_list 不是一个序列时,引发异常.
7、 optimizer.apply_gradients
minimize()就是compute_gradients()和apply_gradients()这两个方法的简单组合。
apply_gradients(grads_and_vars, global_step=None, name=None)
返回一个执行梯度更新的 ops。
grads_and_vars的格式就是compute_gradients()所返回的(gradient, variable)对,当然数据类型也是“tf.Tensor”,作用是,更新grads_and_vars中variable的梯度,不在里面的变量的梯度不变。
8、 tf.global_variables()
在使用tensorflow搭建模型时,需要定义许多变量,例如一个映射层就需要权重与偏置。当网络结果越来越复杂,变量越来越多的时候,就需要一个查看管理变量的函数,在tensorflow中,tf.trainable_variables(), tf.all_variables(),和tf.global_variables()可以来满足查看变量的要求。
(1)tf.trainable_variable()
顾名思义,这个函数可以也仅可以查看可训练的变量,在我们生成变量时,无论是使用tf.Variable()还是tf.get_variable()生成变量,都会涉及一个参数trainable,其默认为True。以tf.Variable()为例:
__init__(
initial_value=None,
trainable=True,
collections=None,
validate_shape=True,
...
)
对于一些我们不需要训练的变量,比较典型的例如学习率或者计步器这些变量,我们都需要将trainable设置为False,这时tf.trainable_variables() 就不会打印这些变量。举个简单的例子,在下图中共定义了4个变量,分别是一个权重矩阵,一个偏置向量,一个学习率和计步器,其中前两项是需要训练的而后两项则不需要。
(2) tf.global_variables()
回到第一个例子,如果我希望查看全部变量,包括我的学习率等信息,可以通过tf.global_variables()来实现。效果如下:
(3)tf.all_variables()
与tf.global_variables()作用拥有相似的功能,只是版本问题,可以看到:
运行时会有warning的提示。还有一点需要注意的是,tf.all_variables()似乎是没有scope输入参数的,这点作用性不如前两个那么强。
9、 tf.local_variables()
返回值:
局部变量对象的列表.
局部变量 - 每个进程变量,通常不保存或还原到检查点,并用于临时值或中间值.例如,可以将它们用作度量值计算的计数器或此计算机已读取数据的 epochs 数.该tf.contrib.framework.local_variable() 函数自动将新变量添加到 GraphKeys.LOCAL_VARIABLES.这个方便函数返回该集合的内容.
局部变量的替代方法是全局变量,参考 tf.global_variables.
10、 tf.train.Saver
saver = tf.train.Saver(...variables...)
__init__(
var_list=None, #var_list指定要保存和恢复的变量
reshape=False,
sharded=False,
max_to_keep=5,
keep_checkpoint_every_n_hours=10000.0,
name=None,
restore_sequentially=False,
saver_def=None,
builder=None,
defer_build=False,
allow_empty=False,
write_version=tf.train.SaverDef.V2,
pad_step_number=False,
save_relative_paths=False,
filename=None
)
max_to_keep :用来设置保存模型的个数,默认为5,即 max_to_keep=5,保存最近的5个模型。如果想每训练一代(epoch)就想保存一次模型,则可以将 max_to_keep设置为None或者0,但是这样做除了多占用硬盘,并没有实际多大的用处,因此不推荐,如:saver=tf.train.Saver(max_to_keep=0)
当然,如果你只想保存最后一代的模型,则只需要将max_to_keep设置为1即可:saver=tf.train.Saver(max_to_keep=1)
保存参数:
weight=[weights['wc1'],weights['wc2'],weights['wc3a']]
saver = tf.train.Saver(weight)#创建一个saver对象,.values是以列表的形式获取字典值
saver.save(sess,'model.ckpt')
恢复参数:
weight=[weights['wc1'],weights['wc2'],weights['wc3a']]
saver = tf.train.Saver(weight)#创建一个saver对象,.values是以列表的形式获取字典值
saver.restore(sess, model_filename)
11、 tf.global_variables_initializer()
# 必须要使用global_variables_initializer的场合
# 含有tf.Variable的环境下,因为tf中建立的变量是没有初始化的,也就是在debug时还不是一个tensor量,而是一个Variable变量类型
size_out = 10
tensor = tf.Variable(tf.random_normal(shape=[size_out]))
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init) # initialization variables
print(sess.run(tensor))
# 可以不适用初始化的场合
# 不含有tf.Variable、tf.get_Variable的环境下
# 比如只有tf.random_normal或tf.constant等
size_out = 10
tensor = tf.random_normal(shape=[size_out]) # 这里debug是一个tensor量哦
init = tf.global_variables_initializer()
with tf.Session() as sess:
# sess.run(init) # initialization variables
print(sess.run(tensor))
返回一个用来初始化计算图中所有global variable的op。
12、 tf.summary.FileWriter
#========================================================================================================
#类定义原型:
# class FileWriter(SummaryToEventTransformer)
#类说明:
# [1]将Summary protocol buffers写入磁盘文件
# [2]FileWriter类提供了一种用于在给定目录下创建事件文件的机制,并且将summary数据写入硬盘
#构造函数:
# def __init__(self,logdir,graph=None,max_queue=10,flush_secs=120,graph_def=None,filename_suffix=None):
#参数说明:
# [1]self : 类对象自身
# [2]logdir:用于存储【日志文件】的目录
# [3]graph : 将要存储的计算图
#应用示例:
# summary_writer = tf.summary.FileWriter(SUMMARY_DIR,sess.graph):创建一个FileWrite的类对象,并将计算图
# 写入文件
例如:将summary数据写入硬盘
merged = tf.summary.merge_all()
#【8】创建回话Session
with tf.Session() as sess:
#【9】实例化一个FileWriter的类对象,并将当前TensoirFlow的计算图写入【日志文件】
summary_writer = tf.summary.FileWriter(SUMMARY_DIR,sess.graph)
#【10】Tensorflow中创建的变量,在使用前必须进行初始化,下面这个为初始化函数
tf.global_variables_initializer().run()
#【11】开始训练
for i in range(TRAIN_STEPS):
xs,ys = mnist.train.next_batch(BATCH_SIZE)
#【12】运行训练步骤以及所有的【日志文件生成操作】,得到这次运行的【日志文件】。
summary,_,acc = sess.run([merged,train_step,accuracy],feed_dict={x:xs,y_:ys})
print('Accuracy at step %s: %s' % (i, acc))
#【13】将所有的日志写入文件,TensorFlow程序就可以那这次运行日志文件,进行各种信息的可视化
summary_writer.add_summary(summary,i)
summary_writer.close()
writer = tf.summary.FileWriter(path, session.graph)
指定一个文件用来保存图。
log是事件文件所在的目录,这里是工程目录下的log目录。
第二个参数是事件文件要记录的图,也就是TensorFlow默认的图。
可以调用其add_summary()方法将训练过程数据保存在filewriter指定的文件中。
tf.summary.scalar('accuracy',acc) #生成准确率标量图
merge_summary = tf.summary.merge_all()
train_writer = tf.summary.FileWriter(dir,sess.graph)#定义一个写入summary的目标文件,dir为写入文件地址
......(交叉熵、优化器等定义)
for step in xrange(training_step): #训练循环
train_summary = sess.run(merge_summary,feed_dict = {...})#调用sess.run运行图,生成一步的训练过程数据
train_writer.add_summary(train_summary,step)#调用train_writer的add_summary方法将训练过程以及训练步数保存
tf.summary的其他函数用法:tf.summary总结
13、tf.name_scope
用于定义Python op的上下文管理器。
此上下文管理器将推送名称范围,这将使在其中添加的所有操作的名称带有前缀。
tf.name_scope(
name #在名称范围内创建的所有名称上使用的前缀。
)
tf.variable_scope可以让变量有相同的命名方式,包括tf.get_variable变量和tf.Variable变量
tf.name_scope可以让变量有相同的命名方式,只限于tf.Variable变量
14、 tf.summary.scalar
用于收集标量信息,格式为:
tf.summary.scalar(tags, values, collections=None, name=None)
例如:
f.summary.scalar('train_loss', train_loss)
tf.summay.scalar('eval_loss',eval_loss)
tf.summary.scalar('accuracy', accuracy)
常见应用如下:
import tensorflow as tf
# 定义两个变量
a = tf.placeholder(dtype=tf.float32, shape=[])
b = tf.placeholder(dtype=tf.float32, shape=[])
#添加变量进去
tf.summary.scalar('a', a)
tf.summary.scalar('b', b)
# 将所有summary全部保存到磁盘,以便tensorboard显示
smy = tf.summary.merge_all()
#初始化全局变量
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
# 初始化变量
sess.run(init_op)
#把信息存储在具体的文件夹里面
writer = tf.summary.FileWriter("tjn", sess.graph)
for i in range(5):
#赋值
sumers=sess.run(smy,feed_dict={a:i+9,b:i+2})
#把步骤都记录下来
writer.add_summary(summary=sumers,global_step=i)
运行结束以后,tjn文件夹里面会有日志文件:
打开cmd命令,切换到相应的文件夹下,启动tensorborder:
可页面上输入localhost:6006,或复制地址到网页
若要显示直方图信息:
tf.summary.histogram(tags, values, collections=None, name=None)
例如:
tf.summary.histogram('histogram', var)
#一般用来显示训练过程中变量的分布情况
还有:
tf.summary.distribution:分布图,一般用于显示weights分布
tf.summary.text:可以将文本类型的数据转换为tensor写入summary中
tf.summary.image:输出带图像的probuf,汇总数据的图像的的形式如下: ’ tag /image/0’, ’ tag /image/1’…,如:input/image/0等。
tf.summary.audio:展示训练过程中记录的音频
15、 tf.summary.merge
格式:
tf.summary.merge(inputs, collections=None, name=None)
一般选择要保存的信息,还需要用到tf.get_collection()函数
tf.summary.scalar('accuracy',acc) #生成准确率标量图
merge_summary = tf.summary.merge([tf.get_collection(tf.GraphKeys.SUMMARIES,'accuracy'),...(其他要显示的信息)])
train_writer = tf.summary.FileWriter(dir,sess.graph)#定义一个写入summary的目标文件,dir为写入文件地址
......(交叉熵、优化器等定义)
for step in xrange(training_step): #训练循环
train_summary = sess.run(merge_summary,feed_dict = {...})#调用sess.run运行图,生成一步的训练过程数据
train_writer.add_summary(train_summary,step)#调用train_writer的add_summary方法将训练过程以及训练步数保存
使用tf.get_collection函数筛选图中summary信息中的accuracy信息,这里的tf.GraphKeys.SUMMARIES 是summary在collection中的标志。
当然,也可以直接:
acc_summary = tf.summary.scalar('accuracy',acc) #生成准确率标量图
merge_summary = tf.summary.merge([acc_summary ,...(其他要显示的信息)]) #这里的[]不可省
如果要在tensorboard中画多个数据图,需定义多个tf.summary.FileWriter并重复上述过程。