TensorFlow中优化DNN模型tips

TensorFlow中优化DNN模型tips


一、学习率的设置

指数衰减法–tf.train.exponential_decay

exponential_decay(learning_rate, global_step, decay_steps, decay_rate, staircase=False, name=None)

通过这个函数,可以先使用较大的学习率来快速得到一个比较优的解,然后随着迭代的继续逐步减小学习率,使得模型在训练后更加稳定,即指数级的减小学习率。

exponential_decay实现了以下代码的功能:

decayed_learning_rate = \
    learning_rate * decay_rate ^(global_step / decay_steps)

其中:

  • decayed_learning_rate:为每一轮优化时使用的学习率;
  • learning_rate:为事先设定的初始学习率;
  • decay_rate:为衰减系数;
  • decay_steps:为衰减速度;
  • staircase:可以通过设置来选择不同的衰减方式,默认值为False;当为True时,global_step/decay_stpes会被转化成整数,学习率成为一个阶梯函数。

二、正则化

正则化时,即在优化的时候不是直接优化损失函数 J(θ) ,而是优化 J(θ)+λR(w)

L1、L2正则化

常用的 R(w) 有两种:

  • L1正则化: R(w)=w1=i|wi|
  • L2正则化: R(w)=w22=iw2i

无论是那种正则化方式,基本思想都是希望通过限制权重的大小,使得模型不能任意拟合训练数据中的随机噪音。

其中,L1正则化会让参数变得更稀疏,而L2正则化则不会。所谓参数变得更稀疏是指会有更多的参数变为0,这样可以达到类似特征选取的功能。之所以L2正则化不会让参数变得稀疏是因为当参数很小时,如0.001,这个参数的平方基本上就可以忽略了,于是模型不会进一步将这个参数调整为0。

其次,L1正则化的计算公式不可导,而L2正则化公式可导,在优化时需要计算损失函数的偏导数,所以对含有L2正则化损失函数的优化要更加简洁,优化带L1正则化的损失函数要更加复杂。

在实践中,可以将L1正则化和L2正则化同时使用:

R(w)=iα|wi|+(1α)w2i

带L2正则化的损失函数:

w = tf.Variable(tf.random_normal([2,1],stddev=1, seed=1))
y = tf.matmul(x, w)

loss = tf.reduce_mean(tf.square(y_ - y)) + tf.contrib.layers.l2_regularize(lambda)(w)

当神经网络结构复杂之后,定义网络结果的部分和计算损失函数的部分可能不在同一个函数中,这样通过变量方式计算损失函数就不方便了。此时TensorFlow提供结合(collection)。如下为计算一个5层神经网络带L2正则化的损失函数计算方法。

import tensorflow as tf

# 定义一个获取权重,并自动加入正则项到损失的函数
def get_weight(shape, lambda1):
    var = tf.Variable(tf.random_normal(shape), dtype=tf.float32)
    tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(lambda1)(var))
    return var

# 定义神经网络
x = tf.placeholder(tf.float32, shape=(None, 2))
y_ = tf.placeholder(tf.float32, shape=(None, 1))
sample_size = len(data)

# 每层节点的个数
layer_dimension = [2,10,5,3,1]

n_layers = len(layer_dimension)

cur_layer = x
in_dimension = layer_dimension[0]

# 循环生成网络结构
for i in range(1, n_layers):
    out_dimension = layer_dimension[i]
    weight = get_weight([in_dimension, out_dimension], 0.003)
    bias = tf.Variable(tf.constant(0.1, shape=[out_dimension]))
    cur_layer = tf.nn.elu(tf.matmul(cur_layer, weight) + bias)
    in_dimension = layer_dimension[i]

y= cur_layer

# 损失函数的定义。
mse_loss = tf.reduce_sum(tf.pow(y_ - y, 2)) / sample_size
tf.add_to_collection('losses', mse_loss)
loss = tf.add_n(tf.get_collection('losses'))

三、滑动平均模型 – tf.train.ExponentialMovingAverage

滑动平均模型,可以在采用随机梯度下降的算法中,在一定程度上提高最终模型在测试数据上的表现。

shadow_variable=decay×shadow_variable+(1decay)×variable

其中:

  • shadow_variable:影子变量;
  • variable:待更新的变量;
  • num_updates:动态设置decay的大小。
  • decay:衰减率;
    decay决定了模型更新的速度,decay越大模型就越趋于稳定。实际应用中,decay一般会设为接近1的数,如0.999或0.9999。
__init__(
    decay,
    num_updates=None,
    zero_debias=False,
    name='ExponentialMovingAverage'
)

如果使用num_updates,则每次使用的衰减率为:

min{decay,1+num_updates10+num_updates}

# 定义变量及滑动平均类
v1 = tf.Variable(0, dtype=tf.float32)
step = tf.Variable(0, trainable=False)
ema = tf.train.ExponentialMovingAverage(0.99, step)
maintain_averages_op = ema.apply([v1]) 

# 查看不同迭代中变量取值的变化
with tf.Session() as sess:

    # 初始化
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    print sess.run([v1, ema.average(v1)])

    # 更新变量v1的取值
    sess.run(tf.assign(v1, 5))
    sess.run(maintain_averages_op)
    print sess.run([v1, ema.average(v1)]) 

    # 更新step和v1的取值
    sess.run(tf.assign(step, 10000))  
    sess.run(tf.assign(v1, 10))
    sess.run(maintain_averages_op)
    print sess.run([v1, ema.average(v1)])       

    # 更新一次v1的滑动平均值
    sess.run(maintain_averages_op)
    print sess.run([v1, ema.average(v1)])

output:
[0.0, 0.0]
[5.0, 4.5]
[10.0, 4.5549998]
[10.0, 4.6094499]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值