1、滑动平均求解对象初始化

2022-02-07

移动平均线将为目标变量保留一个影子变量。影子变量不影响原变量的更新和维护,但在测试或实际预测(非训练)的过程中,影子变量用来代替原变量。

1、滑动平均求解器对象初始化

ema = tf.train.ExponentialMovingAverage(decay,num_updates)

参数衰减

` = 衰变 * + (1 – 衰变) * `

范围

`min(衰减, (1 + ) / (10 + ))`

2、添加/更新变量

添加目标变量以维护影子变量

注意维护不是自动的,每轮训练都需要跑这句话,所以一般用tf来make和bind,这样每次更新变量

ema.apply([var0, var1])

3、获取影子变量值

这一步不需要定义图,从影子变量集中提取目标值

sess.run(ema.average([var0, var1]))

4、保存和加载阴影变量

我们知道,在 中,变量的移动平均线由影子变量维护。如果要获取变量的移动平均值,则需要获取影子变量而不是变量本身。

保存阴影变量

tf.train.rage对象创建后,Saver会在正常保存时将其存储在变量中。命名规则为“v/rage”对应变量“v”

import tensorflow as tf  
if __name__ == "__main__":  
    v = tf.Variable(0.,name="v")  
    #设置滑动平均模型的系数  
    ema = tf.train.ExponentialMovingAverage(0.99)  
    #设置变量v使用滑动平均模型,tf.all_variables()设置所有变量  
    op = ema.apply([v])  
    #获取变量v的名字  
    print(v.name)  
    #v:0  
    #创建一个保存模型的对象  
    save = tf.train.Saver()  
    sess = tf.Session()  
    #初始化所有变量  
    init = tf.initialize_all_variables()  
    sess.run(init)  
    #给变量v重新赋值  
    sess.run(tf.assign(v,10))  
    #应用平均滑动设置  
    sess.run(op)  
    #保存模型文件  
    save.save(sess,"./model.ckpt")  
    #输出变量v之前的值和使用滑动平均模型之后的值  
    print(sess.run([v,ema.average(v)]))  
    #[10.0, 0.099999905]  

加载阴影变量并映射到变量

使用 Saver 的变量名映射功能加载模型,其实对所有变量都可以这样做。””模型加载方法总结

v = tf.Variable(1.,name="v")  
#定义模型对象  
saver = tf.train.Saver({"v/ExponentialMovingAverage":v})  
sess = tf.Session()  
saver.restore(sess,"./model.ckpt")  
print(sess.run(v))  
#0.0999999  

这里需要注意的一点是,使用 tf.train.Saver 函数时,传递的模型参数是 {“v/rage”:v} 而不是 {“v”:v},如果使用后一个参数,那么你将得到 10 而不是 0.09,因为后者获取变量本身而不是影子变量。

使用这种方法读取模型文件时,还需要输入一长串变量名。

函数的使用

v = tf.Variable(1.,name="v")  
#滑动模型的参数的大小并不会影响v的值  
ema = tf.train.ExponentialMovingAverage(0.99)  
print(ema.variables_to_restore())  
#{'v/ExponentialMovingAverage': }  
sess = tf.Session()  
saver = tf.train.Saver(ema.variables_to_restore())  
saver.restore(sess,"./model.ckpt")  
print(sess.run(v))  
#0.0999999 

识别网络中的变量并自动生成影子变量名称。

通过使用该函数,可以在加载模型时直接将影子变量映射到变量本身,因此我们在获取变量的滑动平均值时只需要获取变量本身的值,而不需要获取影子变量。

5、官方文档示例

官方文档中,每次apply更新都会自动训练一侧的模型。事实上,两者的关系是可以颠倒的。P128中有“tf战斗”的例子

| 模型时的用法:

|

| ““

| # .

| var0 = tf.(…)

| var1 = tf.(…)

| # … 使用 构建模型…

| …

| # 一个操作,. 这就是我们

| # 将用作操作。

| = opt.(, [var0, var1])

|

| #愤怒

| ema = tf.train.rage(衰减=0.9999)

|

| 与 tf.([]):

| # , 并将操作添加到

| # of var0 and var1. 这也是一个操作

| # 每一步之后。这就是我们将使用的地方

| #通常的操作。

| = ema.apply([var0, var1])

|

| …通过…训练模型

| ““

6、 示例

和上面不同的是,不容易绑定到(位于函数体之外),所以将两个输出过程强制转换为节点,绑定到参数更新步骤

def batch_norm(x,beta,gamma,phase_train,scope='bn',decay=0.9,eps=1e-5):
    with tf.variable_scope(scope):
        # beta = tf.get_variable(name='beta', shape=[n_out], initializer=tf.constant_initializer(0.0), trainable=True)
        # gamma = tf.get_variable(name='gamma', shape=[n_out],
        #                         initializer=tf.random_normal_initializer(1.0, stddev), trainable=True)
        batch_mean,batch_var = tf.nn.moments(x,[0,1,2],name='moments')
        ema = tf.train.ExponentialMovingAverage(decay=decay)
 
        def mean_var_with_update():
            ema_apply_op = ema.apply([batch_mean,batch_var])
            with tf.control_dependencies([ema_apply_op]):
                return tf.identity(batch_mean),tf.identity(batch_var)
                # identity之后会把Variable转换为Tensor并入图中,
                # 否则由于Variable是独立于Session的,不会被图控制control_dependencies限制
 
        mean,var = tf.cond(phase_train,
                           mean_var_with_update,
                           lambda: (ema.average(batch_mean),ema.average(batch_var)))
       normed = tf.nn.batch_normalization(x, mean, var, beta, gamma, eps)
    return normed

分类:

技术要点:

相关文章:

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片