TF训练相关函数

1.指数衰减学习率

目的:

  • 一开始较快速度收敛
  • 之后快收敛时,更加稳定得收敛至最优解
def exponential_decay(learning_rate,
                      global_step,
                      decay_steps,
                      decay_rate,
                      staircase=False,
                      name=None)

衰减后的学习率计算公式:

decayed_learning_rate = learning_rate * decay_rate ^ (global_step / decay_steps)

global_step==0时,decayed_learning_rate == learning_rate
global_step较大时,decayed_learning_rate == learning_rate * 系数

staircase==Falsedecayed_learning_rate的变化是连续的;

staircase==Truedecayed_learning_rate得变化是阶梯状的,每次迭代次数达到decay_steps时,在原始学习率上乘上系数

Question:你并不知道什么时候该减少学习率,让网络稳定收敛,单纯靠global_step实在草率。所以exponential_decay方法的参数都是超参数,仅能凭经验设置。

2. tf.control_dependecies

此函数表示了tfop的依赖性关系。

x = tf.Variable(1.0, name='x')
x_plus_1 = tf.assign_add(x, 1, name='x_plus')

with tf.control_dependencies([x_plus_1]):
    y = x
    z=tf.identity(x,name='z_added')

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    for i in range(5):
        print(sess.run(z))
        # 输出 2,3,4,5,6
        # 如果改为输出 print(sess.run(y)) ,则结果为 1,1,1,1,1 
        # 原因在我之前博客讲的tf的图流动机制

即对with tf.control_dependencies([pre_op]):内部的op操作,必须先进行pre_op操作.
而简单的y = x并不是图的op,图中的赋值optf.identity(其原理是创建新的结点,再把原节点信息copy过去)

  • tf.control_dependencies常和tf.assign_add配合使用,达到先做更新op再处理后续.

3. tf.train.ExponentialMovingAverage()

ExponentialMovingAverage类的初始化函数:

def __init__(self, decay, num_updates=None, zero_debias=False,
               name="ExponentialMovingAverage"):
	...

更新公式:shadow_variable = decay * shadow_variable + (1 - decay) * variable

其中shadow_variable表示上一次迭代的值;variable表示此次BP更新的后值(w - α*δloss/δw)
decay变量一般取0.99/0.999等接近1的数字。当num_updates不是NONE
系数decay的取值为min(decay, (1 + num_updates) / (10 + num_updates))
可见,decay:

刚开始训练时,不需要滑动平均,取(1 + num_updates) / (10 + num_updates),较小,BP更新后的值variable占主导
训练快结束时,模型参数不需要太多调整,保持稳定即可,同时迭代次数很大(1 + num_updates) / (10 + num_updates)会接近于1,大于0.99/0.999,则让之前的shadow_variable起主导作用

滑动平均机制:作用在BP更新完权重后,让训练在后期变得更加平缓,稳定。
具体代码:

import tensorflow as tf

v1 = tf.Variable(0, dtype=tf.float32)
step = tf.Variable(tf.constant(0))

ema = tf.train.ExponentialMovingAverage(0.99, step)
maintain_average = ema.apply([v1]) # ema.apply([v1])对v1做ExponentialMovingAverage

with tf.Session() as sess:
    init = tf.initialize_all_variables()
    sess.run(init)
    # v1是未进行ExponentialMovingAverage的shadow_variable
    # ema.average(v1)取出本轮被ema.apply([v1])计算的ExponentialMovingAverage后的variable
    print(sess.run([v1, ema.average(v1)]))  # 初始的值都为0  variable和shadow_variable一样

    sess.run(tf.assign(v1, 5))  # 模拟BP后v1变成了5
    print(sess.run(maintain_average))
    print(sess.run([v1, ema.average(v1)]))  # decay=min(0.99, 1/10)=0.1, v1=0.1*0+0.9*5=4.5

    sess.run(tf.assign(step, 10000))  # steps=10000
    sess.run(tf.assign(v1, 10))  # v1=10
    sess.run(maintain_average)
    print(sess.run([v1, ema.average(v1)]))  # decay=min(0.99,(1+10000)/(10+10000))=0.99, v1=0.99*4.5+0.01*10=4.555

    sess.run(maintain_average)
    print(sess.run([v1, ema.average(v1)]))  # decay=min(0.99,(1+10000)/(10+10000))=0.99, v1=0.99*4.555+0.01*10=4.6
  • 只有被ema.apply(var)variable才会在ema.average(var)时,有具体值;否则输出NONE

并且EMA被广泛的应用在深度学习的BN层中,RMSprop,adadelta,adam等梯度下降方法.

你可能感兴趣的:(TF训练相关函数)