神经网络优化-滑动平均与正则化

只是草稿,借鉴某一位用户的,等晚上学习的时候再加上自己的心得。

老夫马上要回学校了,这几天先不更了。

滑动平均:记录了一段时间内模型中所有参数w和b各自的平均值。利用滑动平均值可以增强模型的泛化能力。

滑动平均值(影子)计算公式:

影子 = 衰减率 * 影子 +(1 - 衰减率)* 参数

其中,衰减率,影子初值=参数初值

用Tesnsorflow函数表示为:

ema =tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step) 

其中,MOVING_AVERAGE_DECAY表示滑动平均衰减率,一般会赋接近1的值,global_step表示当前训练了多少轮。

ema_op =ema.apply(tf.trainable_variables())

其中,ema.apply()函数实现对括号内参数求滑动平均,tf.trainable_variables()函数实现把所有待训练参数汇总为列表。

扫描二维码关注公众号,回复: 3049278 查看本文章
with tf.control_dependencies([train_step,ema_op]):
     train_op = tf.no_op(name='train')

其中,该函数实现将滑动平均和训练过程同步运行。

查看模型中参数的平均值,可以用ema.average()函数。 例如:

在神经网络模型中,将MOVING_AVERAGE_DECAY设置为0.99,参数w1设置为0,w1的滑动平均值设置为0。

①开始时,轮数global_step设置为0,参数w1更新为1,则w1的滑动平均值为:

w1滑动平均值=min(0.99,1/10)*0+(1–min(0.99,1/10)*1 = 0.9

②当轮数global_step设置为100时,参数w1更新为10,则滑动平均值变为:

w1滑动平均值=min(0.99,101/110)*0.9+(1–min(0.99,101/110)*10 = 0.826+0.818=1.644

③再次运行,参数w1更新为1.644,则滑动平均值变为:

w1滑动平均值=min(0.99,101/110)*1.644+(1–min(0.99,101/110)*10 = 2.328

④再次运行,参数w1更新为2.328,则滑动平均值:

w1滑动平均值=2.956

代码范式:

#coding:utf-8
import tensorflow as tf
 
#1. 定义变量及滑动平均类
#定义一个32位浮点变量,初始值为0.0  这个代码就是不断更新w1参数,优化w1参数,滑动平均做了个w1的影子
w1 = tf.Variable(0, dtype=tf.float32)
#定义num_updates(NN的迭代轮数),初始值为0,不可被优化(训练),这个参数不训练
global_step = tf.Variable(0, trainable=False)
#实例化滑动平均类,给衰减率为0.99,当前轮数global_step
MOVING_AVERAGE_DECAY = 0.99
ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
#ema.apply后的括号里是更新列表,每次运行sess.run(ema_op)时,对更新列表中的元素求滑动平均值。
#在实际应用中会使用tf.trainable_variables()自动将所有待训练的参数汇总为列表
#ema_op = ema.apply([w1])
ema_op = ema.apply(tf.trainable_variables())
 
#2. 查看不同迭代中变量取值的变化。
with tf.Session() as sess:
    # 初始化
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
	#用ema.average(w1)获取w1滑动平均值 (要运行多个节点,作为列表中的元素列出,写在sess.run中)
	#打印出当前参数w1和w1滑动平均值
    print "current global_step:", sess.run(global_step)
    print "current w1", sess.run([w1, ema.average(w1)]) 
    
    # 参数w1的值赋为1
    sess.run(tf.assign(w1, 1))
    sess.run(ema_op)
    print "current global_step:", sess.run(global_step)
    print "current w1", sess.run([w1, ema.average(w1)]) 
    
    # 更新global_step和w1的值,模拟出轮数为100时,参数w1变为10, 以下代码global_step保持为100,每次执行滑动平均操作,影子值会更新 
    sess.run(tf.assign(global_step, 100))  
    sess.run(tf.assign(w1, 10))
    sess.run(ema_op)
    print "current global_step:", sess.run(global_step)
    print "current w1:", sess.run([w1, ema.average(w1)])       
    
    # 每次sess.run会更新一次w1的滑动平均值
    sess.run(ema_op)
    print "current global_step:" , sess.run(global_step)
    print "current w1:", sess.run([w1, ema.average(w1)])
 
    sess.run(ema_op)
    print "current global_step:" , sess.run(global_step)
    print "current w1:", sess.run([w1, ema.average(w1)])
 
    sess.run(ema_op)
    print "current global_step:" , sess.run(global_step)
    print "current w1:", sess.run([w1, ema.average(w1)])
 
    sess.run(ema_op)
    print "current global_step:" , sess.run(global_step)
    print "current w1:", sess.run([w1, ema.average(w1)])
 
    sess.run(ema_op)
    print "current global_step:" , sess.run(global_step)
    print "current w1:", sess.run([w1, ema.average(w1)])
 
    sess.run(ema_op)
    print "current global_step:" , sess.run(global_step)
    print "current w1:", sess.run([w1, ema.average(w1)])
 
#更改MOVING_AVERAGE_DECAY 为 0.1  看影子追随速度

运行结果如下:

从运行结果可知,最初参数w1和滑动平均值都是0;参数w1设定为1后,滑动平均值变为0.9;当迭代轮数更新为100轮时,参数w1更新为10后,滑动平均值变为1.644。随后每执行一次,参数 w1的滑动平均值都向参数w1靠近。可见,滑动平均追随参数的变化而变化。 

猜你喜欢

转载自blog.csdn.net/qq_42229034/article/details/82078246