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
分类:
技术要点:
相关文章:
暂无评论内容